mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-26 03:01:50 +01:00
[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:
parent
405c54555e
commit
47761b9b8f
@ -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 |
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
@ -66,8 +66,8 @@
|
||||
#define MCYCLES_PER_LINE 3420
|
||||
|
||||
/* Horizontal timing offsets when running in Z80 mode */
|
||||
#define SMS_CYCLE_OFFSET 530
|
||||
#define PBC_CYCLE_OFFSET 560
|
||||
#define SMS_CYCLE_OFFSET 530
|
||||
#define PBC_CYCLE_OFFSET 560
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -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_ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user