[Core/MD] added basic emulation of 68k bus access refresh delays (fixes Super Airwolf graphical glitch during intro & some Krikzz's mcd-verificator timing tests)

This commit is contained in:
ekeeke 2024-02-21 19:50:08 +01:00
parent 405c54555e
commit 47761b9b8f
9 changed files with 44 additions and 19 deletions

View File

@ -73,6 +73,7 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* added support for some new unlicensed games with copy protection (Thunderbolt II, Tom Clown, Chaoji Puke / Super Poker, Rock Heaven, Rock World)
* added support for Everdrive extended SSF mapper
* added support for MegaSD CD hardware overlay (MD+ hacks) and extended SSF2 / ROM write mappers
* added basic emulation of 68k bus access refresh delays (fixes Super Airwolf graphical glitch during intro & some Krikzz's mcd-verificator timing tests)
* added (very basic) emulation of Flashkit MD hardware
* added emulation of Micro Machines USA on-board TMSS bypass logic hardware
* added SRAM support for games larger than 8MB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

@ -238,7 +238,8 @@ typedef struct
cpu_idle_t poll; /* polling detection */
uint cycles; /* current master cycle count */
sint cycles; /* current master cycle count */
sint refresh_cycles; /* external bus refresh cycle */
uint cycle_end; /* aimed master cycle count for current execution frame */
uint dar[16]; /* Data and Address Registers */

View File

@ -299,6 +299,13 @@ void m68k_run(unsigned int cycles)
/* Decode next instruction */
REG_IR = m68ki_read_imm_16();
/* 68K bus access refresh delay (Mega Drive / Genesis specific) */
if (m68k.cycles >= (m68k.refresh_cycles + (128*7)))
{
m68k.refresh_cycles = (m68k.cycles / (128*7)) * (128*7);
m68k.cycles += (2*7);
}
/* Execute instruction */
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
@ -382,6 +389,9 @@ void m68k_pulse_reset(void)
#endif
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]);
/* Synchronize 68k bus refresh mechanism (Mega Drive / Genesis specific) */
m68k.refresh_cycles = (m68k.cycles / (128*7)) * (128*7);
}
void m68k_pulse_halt(void)

View File

@ -8,7 +8,7 @@ INLINE void UseDivuCycles(uint32 dst, uint32 src)
int i;
/* minimum cycle time */
uint mcycles = 38 * MUL;
uint mcycles = 76 * MUL;
/* 16-bit divisor */
src <<= 16;
@ -27,27 +27,33 @@ INLINE void UseDivuCycles(uint32 dst, uint32 src)
{
/* shift dividend and add two cycles */
dst <<= 1;
mcycles += (2 * MUL);
mcycles += (4 * MUL);
if (dst >= src)
{
/* apply divisor and remove one cycle */
dst -= src;
mcycles -= 1 * MUL;
mcycles -= 2 * MUL;
}
}
}
USE_CYCLES(mcycles << 1);
USE_CYCLES(mcycles);
/* one 68K bus refresh cycle should be skipped if instruction processing time is longer than refresh period (128 CPU cycles on Mega Drive / Genesis) */
if (mcycles >= (128*MUL))
{
m68ki_cpu.refresh_cycles += (128*MUL);
}
}
INLINE void UseDivsCycles(sint32 dst, sint16 src)
{
/* minimum cycle time */
uint mcycles = 6 * MUL;
uint mcycles = 12 * MUL;
/* negative dividend */
if (dst < 0) mcycles += 1 * MUL;
if (dst < 0) mcycles += 2 * MUL;
if ((abs(dst) >> 16) < abs(src))
{
@ -57,30 +63,36 @@ INLINE void UseDivsCycles(sint32 dst, sint16 src)
uint32 quotient = abs(dst) / abs(src);
/* add default cycle time */
mcycles += (55 * MUL);
mcycles += (110 * MUL);
/* positive divisor */
if (src >= 0)
{
/* check dividend sign */
if (dst >= 0) mcycles -= 1 * MUL;
else mcycles += 1 * MUL;
if (dst >= 0) mcycles -= 2 * MUL;
else mcycles += 2 * MUL;
}
/* check higher 15-bits of quotient */
for (i=0; i<15; i++)
{
quotient >>= 1;
if (!(quotient & 1)) mcycles += 1 * MUL;
if (!(quotient & 1)) mcycles += 2 * MUL;
}
}
else
{
/* absolute overflow */
mcycles += (2 * MUL);
mcycles += (4 * MUL);
}
USE_CYCLES(mcycles << 1);
USE_CYCLES(mcycles);
/* one 68K bus refresh cycle should be skipped if instruction processing time is longer than refresh period (128 CPU cycles on Mega Drive / Genesis) */
if (mcycles >= (128*MUL))
{
m68ki_cpu.refresh_cycles += (128*MUL);
}
}
INLINE void UseMuluCycles(uint16 src)
@ -18692,6 +18704,7 @@ static void m68k_op_reset(void)
{
m68ki_output_reset() /* auto-disable (see m68kcpu.h) */
USE_CYCLES(CYC_RESET);
m68ki_cpu.refresh_cycles += (128*MUL); /* skip one 68K bus refresh cycle as instruction processing time is longer than refresh period (128 CPU cycles on Mega Drive / Genesis) */
return;
}
m68ki_exception_privilege_violation();

View File

@ -5,7 +5,7 @@
* Support for 16-bit & 8-bit hardware modes
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2021 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@ -659,6 +659,7 @@ void system_frame_gen(int do_skip)
/* adjust timings for next frame */
input_end_frame(mcycles_vdp);
m68k.refresh_cycles -= mcycles_vdp;
m68k.cycles -= mcycles_vdp;
Z80.cycles -= mcycles_vdp;
}
@ -983,6 +984,7 @@ void system_frame_scd(int do_skip)
/* adjust timings for next frame */
scd_end_frame(scd.cycles);
input_end_frame(mcycles_vdp);
m68k.refresh_cycles -= mcycles_vdp;
m68k.cycles -= mcycles_vdp;
Z80.cycles -= mcycles_vdp;
}

View File

@ -5,7 +5,7 @@
* Support for 16-bit & 8-bit hardware modes
*
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
* Copyright (C) 2007-2022 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@ -95,7 +95,6 @@ typedef struct
blip_t* blips[3]; /* Blip Buffer resampling (stereo) */
} t_snd;
/* Global variables */
extern t_bitmap bitmap;
extern t_snd snd;
@ -119,4 +118,3 @@ extern void system_frame_scd(int do_skip);
extern void system_frame_sms(int do_skip);
#endif /* _SYSTEM_H_ */