.improved FIFO timings accuracy (fixes Sol Deace intro)
.code cleanup
This commit is contained in:
ekeeke31 2010-04-06 23:22:27 +00:00
parent 68ceeb3b8c
commit 0794c4a5d6

View File

@ -127,12 +127,12 @@ static const uint32 dma_rates[16] = {
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Functions prototype */ /* Functions prototype */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline void fifo_update(); static void fifo_update();
static inline void data_w(unsigned int data); static void data_w(unsigned int data);
static inline void reg_w(unsigned int r, unsigned int d); static void reg_w(unsigned int r, unsigned int d);
static inline void dma_copy(void); static void dma_copy(void);
static inline void dma_vbus (void); static void dma_vbus (void);
static inline void dma_fill(unsigned int data); static void dma_fill(unsigned int data);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Init, reset, shutdown functions */ /* Init, reset, shutdown functions */
@ -172,7 +172,7 @@ void vdp_reset(void)
interlaced = 0; interlaced = 0;
fifo_write_cnt = 0; fifo_write_cnt = 0;
fifo_lastwrite = 0; fifo_lastwrite = 0;
fifo_latency = 192; /* default FIFO timings */ fifo_latency = 190; /* default FIFO timings */
status = vdp_pal | 0x0200; /* FIFO empty */ status = vdp_pal | 0x0200; /* FIFO empty */
@ -248,7 +248,7 @@ void vdp_restore(uint8 *vdp_regs)
bitmap.viewport.changed = 1; bitmap.viewport.changed = 1;
/* restore FIFO timings */ /* restore FIFO timings */
fifo_latency = (reg[12] & 1) ? 192 : 210; fifo_latency = (reg[12] & 1) ? 190 : 214;
if ((code & 0x0F) == 0x01) if ((code & 0x0F) == 0x01)
fifo_latency = fifo_latency * 2; fifo_latency = fifo_latency * 2;
@ -387,22 +387,21 @@ void vdp_ctrl_w(unsigned int data)
} }
/* /*
FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch) FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch, Sol Deace)
--------------------------------------------------------------- --------------------------------------------------------------------------
HDISP is 2560 mcycles (same in both modes)
CPU access per line is limited during active display: CPU access per line is limited during active display:
H32: 16 access --> 2560/16 = 160 cycles between access H32: 16 access --> 3420/16 = ~214 Mcycles between access
H40: 18 access --> 2560/18 = 142 cycles between access H40: 18 access --> 3420/18 = ~190 Mcycles between access
FIFO access seems to require some additional cyles (VDP latency). This is an approximation, on real hardware, the delay between access is
more likely 16 pixels (128 or 160 Mcycles) with no access allowed during
HBLANK (~860 Mcycles), H40 mode being probably a little more restricted.
Also note that VRAM access are byte wide, so one VRAM write (word) Each VRAM access is byte wide, so one VRAM write (word) need twice cycles.
takes twice CPU cycles.
*/ */
fifo_latency = (reg[12] & 1) ? 192 : 210; fifo_latency = (reg[12] & 1) ? 190 : 214;
if ((code & 0x0F) == 0x01) if ((code & 0x0F) == 0x01)
fifo_latency = fifo_latency * 2; fifo_latency = fifo_latency * 2;
} }
@ -432,7 +431,7 @@ unsigned int vdp_ctrl_r(void)
if ((status & 2) && !dma_length && (mcycles_68k >= dma_endCycles)) if ((status & 2) && !dma_length && (mcycles_68k >= dma_endCycles))
status &= 0xFFFD; status &= 0xFFFD;
uint32 temp = status; unsigned int temp = status;
/* display OFF: VBLANK flag is set */ /* display OFF: VBLANK flag is set */
if (!(reg[1] & 0x40)) if (!(reg[1] & 0x40))
@ -554,6 +553,12 @@ unsigned int vdp_data_r(void)
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC)); error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
#endif #endif
break; break;
#ifdef LOGVDP
default:
error("[%d(%d)][%d(%d)] Unknown (%d) 0x%x read (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, code, addr, m68k_get_reg (NULL, M68K_REG_PC));
break;
#endif
} }
/* Increment address register */ /* Increment address register */
@ -616,12 +621,12 @@ int vdp_int_ack_callback(int int_level)
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* FIFO emulation */ /* FIFO emulation */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline void fifo_update() static void fifo_update()
{ {
if (fifo_write_cnt > 0) if (fifo_write_cnt > 0)
{ {
/* update FIFO reads */ /* update FIFO reads */
uint32 fifo_read = ((mcycles_68k - fifo_lastwrite) / fifo_latency); int fifo_read = ((mcycles_68k - fifo_lastwrite) / fifo_latency);
if (fifo_read > 0) if (fifo_read > 0)
{ {
fifo_write_cnt -= fifo_read; fifo_write_cnt -= fifo_read;
@ -649,16 +654,14 @@ static inline void fifo_update()
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Memory access functions */ /* Memory access functions */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static inline void data_w(unsigned int data) static void data_w(unsigned int data)
{ {
switch (code & 0x0F) switch (code & 0x0F)
{ {
case 0x01: /* VRAM */ case 0x01: /* VRAM */
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg (NULL, M68K_REG_PC)); error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
#endif #endif
/* Byte-swap data if A0 is set */ /* Byte-swap data if A0 is set */
if (addr & 1) if (addr & 1)
data = ((data >> 8) | (data << 8)) & 0xFFFF; data = ((data >> 8) | (data << 8)) & 0xFFFF;
@ -724,19 +727,25 @@ static inline void data_w(unsigned int data)
#endif #endif
*(uint16 *) &vsram[(addr & 0x7E)] = data; *(uint16 *) &vsram[(addr & 0x7E)] = data;
break; break;
#ifdef LOGVDP
default:
error("[%d(%d)][%d(%d)] Unknown (%d) 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, code, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
break;
#endif
} }
/* Increment address register */ /* Increment address register */
addr += reg[15]; addr += reg[15];
} }
static inline void reg_w(unsigned int r, unsigned int d) static void reg_w(unsigned int r, unsigned int d)
{ {
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] VDP register %d write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, r, d, m68k_get_reg (NULL, M68K_REG_PC)); error("[%d(%d)][%d(%d)] VDP register %d write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, r, d, m68k_get_reg (NULL, M68K_REG_PC));
#endif #endif
/* See if Mode 4 (SMS mode) is enabled /* Mode 4 (SMS mode) is enabled
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4) Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4)
*/ */
@ -921,7 +930,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
bitmap.viewport.x = 16; bitmap.viewport.x = 16;
/* Update fifo timings */ /* Update fifo timings */
fifo_latency = ((code & 0x0F) == 0x01) ? 384 : 192; fifo_latency = 190;
} }
else else
{ {
@ -940,8 +949,11 @@ static inline void reg_w(unsigned int r, unsigned int d)
bitmap.viewport.x = 12; bitmap.viewport.x = 12;
/* Update fifo timings */ /* Update fifo timings */
fifo_latency = ((code & 0x0F) == 0x01) ? 420 : 210; fifo_latency = 214;
} }
if ((code & 0x0F) == 0x01)
fifo_latency *= 2;
/* Update viewport */ /* Update viewport */
bitmap.viewport.changed = 1; bitmap.viewport.changed = 1;
@ -995,11 +1007,11 @@ static inline void reg_w(unsigned int r, unsigned int d)
- see how source addr is affected - see how source addr is affected
(can it make high source byte inc?) (can it make high source byte inc?)
*/ */
static inline void dma_copy(void) static void dma_copy(void)
{ {
int name; int name;
uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF; unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
uint32 source = (reg[22] << 8 | reg[21]) & 0xFFFF; unsigned int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
if (!length) if (!length)
length = 0x10000; length = 0x10000;
@ -1025,12 +1037,12 @@ static inline void dma_copy(void)
} }
/* 68K Copy to VRAM, VSRAM or CRAM */ /* 68K Copy to VRAM, VSRAM or CRAM */
static inline void dma_vbus (void) static void dma_vbus (void)
{ {
uint32 source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE; unsigned int source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE;
uint32 base = source; unsigned int base = source;
uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF; unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
uint32 temp; uint16 temp;
if (!length) if (!length)
length = 0x10000; length = 0x10000;
@ -1098,10 +1110,10 @@ static inline void dma_vbus (void)
} }
/* VRAM FILL */ /* VRAM FILL */
static inline void dma_fill(unsigned int data) static void dma_fill(unsigned int data)
{ {
int name; int name;
uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF; unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
if (!length) if (!length)
length = 0x10000; length = 0x10000;