[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 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 Everdrive extended SSF mapper
* added support for MegaSD CD hardware overlay (MD+ hacks) and extended SSF2 / ROM write mappers * 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 (very basic) emulation of Flashkit MD hardware
* added emulation of Micro Machines USA on-board TMSS bypass logic hardware * added emulation of Micro Machines USA on-board TMSS bypass logic hardware
* added SRAM support for games larger than 8MB * 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 */ 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 cycle_end; /* aimed master cycle count for current execution frame */
uint dar[16]; /* Data and Address Registers */ uint dar[16]; /* Data and Address Registers */

View File

@ -299,6 +299,13 @@ void m68k_run(unsigned int cycles)
/* Decode next instruction */ /* Decode next instruction */
REG_IR = m68ki_read_imm_16(); 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 */ /* Execute instruction */
m68ki_instruction_jump_table[REG_IR](); m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]); USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
@ -382,6 +389,9 @@ void m68k_pulse_reset(void)
#endif #endif
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]); 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) void m68k_pulse_halt(void)

View File

@ -8,7 +8,7 @@ INLINE void UseDivuCycles(uint32 dst, uint32 src)
int i; int i;
/* minimum cycle time */ /* minimum cycle time */
uint mcycles = 38 * MUL; uint mcycles = 76 * MUL;
/* 16-bit divisor */ /* 16-bit divisor */
src <<= 16; src <<= 16;
@ -27,27 +27,33 @@ INLINE void UseDivuCycles(uint32 dst, uint32 src)
{ {
/* shift dividend and add two cycles */ /* shift dividend and add two cycles */
dst <<= 1; dst <<= 1;
mcycles += (2 * MUL); mcycles += (4 * MUL);
if (dst >= src) if (dst >= src)
{ {
/* apply divisor and remove one cycle */ /* apply divisor and remove one cycle */
dst -= src; 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) INLINE void UseDivsCycles(sint32 dst, sint16 src)
{ {
/* minimum cycle time */ /* minimum cycle time */
uint mcycles = 6 * MUL; uint mcycles = 12 * MUL;
/* negative dividend */ /* negative dividend */
if (dst < 0) mcycles += 1 * MUL; if (dst < 0) mcycles += 2 * MUL;
if ((abs(dst) >> 16) < abs(src)) if ((abs(dst) >> 16) < abs(src))
{ {
@ -57,30 +63,36 @@ INLINE void UseDivsCycles(sint32 dst, sint16 src)
uint32 quotient = abs(dst) / abs(src); uint32 quotient = abs(dst) / abs(src);
/* add default cycle time */ /* add default cycle time */
mcycles += (55 * MUL); mcycles += (110 * MUL);
/* positive divisor */ /* positive divisor */
if (src >= 0) if (src >= 0)
{ {
/* check dividend sign */ /* check dividend sign */
if (dst >= 0) mcycles -= 1 * MUL; if (dst >= 0) mcycles -= 2 * MUL;
else mcycles += 1 * MUL; else mcycles += 2 * MUL;
} }
/* check higher 15-bits of quotient */ /* check higher 15-bits of quotient */
for (i=0; i<15; i++) for (i=0; i<15; i++)
{ {
quotient >>= 1; quotient >>= 1;
if (!(quotient & 1)) mcycles += 1 * MUL; if (!(quotient & 1)) mcycles += 2 * MUL;
} }
} }
else else
{ {
/* absolute overflow */ /* 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) INLINE void UseMuluCycles(uint16 src)
@ -18692,6 +18704,7 @@ static void m68k_op_reset(void)
{ {
m68ki_output_reset() /* auto-disable (see m68kcpu.h) */ m68ki_output_reset() /* auto-disable (see m68kcpu.h) */
USE_CYCLES(CYC_RESET); 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; return;
} }
m68ki_exception_privilege_violation(); m68ki_exception_privilege_violation();

View File

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

View File

@ -5,7 +5,7 @@
* Support for 16-bit & 8-bit hardware modes * Support for 16-bit & 8-bit hardware modes
* *
* Copyright (C) 1998-2003 Charles Mac Donald (original code) * 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 * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -66,8 +66,8 @@
#define MCYCLES_PER_LINE 3420 #define MCYCLES_PER_LINE 3420
/* Horizontal timing offsets when running in Z80 mode */ /* Horizontal timing offsets when running in Z80 mode */
#define SMS_CYCLE_OFFSET 530 #define SMS_CYCLE_OFFSET 530
#define PBC_CYCLE_OFFSET 560 #define PBC_CYCLE_OFFSET 560
typedef struct typedef struct
{ {
@ -95,7 +95,6 @@ typedef struct
blip_t* blips[3]; /* Blip Buffer resampling (stereo) */ blip_t* blips[3]; /* Blip Buffer resampling (stereo) */
} t_snd; } t_snd;
/* Global variables */ /* Global variables */
extern t_bitmap bitmap; extern t_bitmap bitmap;
extern t_snd snd; extern t_snd snd;
@ -119,4 +118,3 @@ extern void system_frame_scd(int do_skip);
extern void system_frame_sms(int do_skip); extern void system_frame_sms(int do_skip);
#endif /* _SYSTEM_H_ */ #endif /* _SYSTEM_H_ */