[Core/MD] added emulation of Z80 halt when accessing 68k bus during DMA from 68k bus

This commit is contained in:
ekeeke 2024-02-23 15:40:42 +01:00
parent 9a0a1c2922
commit ed7988f8ca
11 changed files with 97 additions and 53 deletions

View File

@ -74,6 +74,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 emulation of Z80 halt when accessing 68k bus during DMA from 68k bus
* added basic emulation of 68k bus access refresh delays (fixes Super Airwolf graphical glitch during intro & some Krikzz's mcd-verificator timing tests) * 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

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

@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware * Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
* *
* 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:
@ -50,7 +50,7 @@ uint8 boot_rom[0x800]; /* Genesis BOOT ROM */
uint8 work_ram[0x10000]; /* 68K RAM */ uint8 work_ram[0x10000]; /* 68K RAM */
uint8 zram[0x2000]; /* Z80 RAM */ uint8 zram[0x2000]; /* Z80 RAM */
uint32 zbank; /* Z80 bank window address */ uint32 zbank; /* Z80 bank window address */
uint8 zstate; /* Z80 bus state (d0 = /RESET, d1 = BUSACK) */ uint8 zstate; /* Z80 bus state (d0 = /RESET, d1 = BUSREQ, d2 = WAIT) */
uint8 pico_current; /* PICO current page */ uint8 pico_current; /* PICO current page */
static uint8 tmss[4]; /* TMSS security register */ static uint8 tmss[4]; /* TMSS security register */

View File

@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware * Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
* *
* 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:

View File

@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access * Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access
* *
* 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:
@ -92,6 +92,26 @@ INLINE unsigned char z80_lockup_r(unsigned int address)
/* Z80 Memory handlers (Genesis mode) */ /* Z80 Memory handlers (Genesis mode) */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static void z80_request_68k_bus_access(void)
{
/* check if 68k bus is accessed by VDP DMA */
if ((Z80.cycles < dma_endCycles) && (dma_type < 2))
{
/* force Z80 to wait until end of DMA */
Z80.cycles = dma_endCycles;
/* check if DMA is not finished at the end of current timeframe */
if (dma_length)
{
/* indicate Z80 will still be waiting for 68k bus at the end of current DMA timeframe */
zstate |= 4;
}
}
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
}
unsigned char z80_memory_r(unsigned int address) unsigned char z80_memory_r(unsigned int address)
{ {
switch((address >> 13) & 7) switch((address >> 13) & 7)
@ -111,8 +131,10 @@ unsigned char z80_memory_r(unsigned int address)
{ {
if ((address >> 8) == 0x7F) if ((address >> 8) == 0x7F)
{ {
/* average Z80 wait-states when accessing 68k area */ /* request access to 68k bus */
Z80.cycles += 3 * 15; z80_request_68k_bus_access();
/* read from $C00000-$C0FFFF area */
return (*zbank_memory_map[0xc0].read)(address); return (*zbank_memory_map[0xc0].read)(address);
} }
return z80_unused_r(address); return z80_unused_r(address);
@ -120,9 +142,10 @@ unsigned char z80_memory_r(unsigned int address)
default: /* $8000-$FFFF: 68k bank (32K) */ default: /* $8000-$FFFF: 68k bank (32K) */
{ {
/* average Z80 wait-states when accessing 68k area */ /* request access to 68k bus */
Z80.cycles += 3 * 15; z80_request_68k_bus_access();
/* read from 68k banked area */
address = zbank | (address & 0x7FFF); address = zbank | (address & 0x7FFF);
if (zbank_memory_map[address >> 16].read) if (zbank_memory_map[address >> 16].read)
{ {
@ -163,8 +186,10 @@ void z80_memory_w(unsigned int address, unsigned char data)
case 0x7F: /* $7F00-$7FFF: VDP */ case 0x7F: /* $7F00-$7FFF: VDP */
{ {
/* average Z80 wait-states when accessing 68k area */ /* request access to 68k bus */
Z80.cycles += 3 * 15; z80_request_68k_bus_access();
/* write to $C00000-$C0FFFF area */
(*zbank_memory_map[0xc0].write)(address, data); (*zbank_memory_map[0xc0].write)(address, data);
return; return;
} }
@ -179,9 +204,10 @@ void z80_memory_w(unsigned int address, unsigned char data)
default: /* $8000-$FFFF: 68k bank (32K) */ default: /* $8000-$FFFF: 68k bank (32K) */
{ {
/* average Z80 wait-states when accessing 68k area */ /* request access to 68k bus */
Z80.cycles += 3 * 15; z80_request_68k_bus_access();
/* write to 68k banked area */
address = zbank | (address & 0x7FFF); address = zbank | (address & 0x7FFF);
if (zbank_memory_map[address >> 16].write) if (zbank_memory_map[address >> 16].write)
{ {

View File

@ -5,7 +5,7 @@
* Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access * Support for SG-1000, Mark-III, Master System, Game Gear & Mega Drive ports access
* *
* 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:

View File

@ -662,6 +662,7 @@ void system_frame_gen(int do_skip)
m68k.refresh_cycles -= mcycles_vdp; m68k.refresh_cycles -= mcycles_vdp;
m68k.cycles -= mcycles_vdp; m68k.cycles -= mcycles_vdp;
Z80.cycles -= mcycles_vdp; Z80.cycles -= mcycles_vdp;
dma_endCycles = 0;
} }
void system_frame_scd(int do_skip) void system_frame_scd(int do_skip)
@ -987,6 +988,7 @@ void system_frame_scd(int do_skip)
m68k.refresh_cycles -= mcycles_vdp; m68k.refresh_cycles -= mcycles_vdp;
m68k.cycles -= mcycles_vdp; m68k.cycles -= mcycles_vdp;
Z80.cycles -= mcycles_vdp; Z80.cycles -= mcycles_vdp;
dma_endCycles = 0;
} }
void system_frame_sms(int do_skip) void system_frame_sms(int do_skip)

View File

@ -72,6 +72,8 @@ uint8 hint_pending; /* 0= Line interrupt is pending */
uint8 vint_pending; /* 1= Frame interrupt is pending */ uint8 vint_pending; /* 1= Frame interrupt is pending */
uint16 status; /* VDP status flags */ uint16 status; /* VDP status flags */
uint32 dma_length; /* DMA remaining length */ uint32 dma_length; /* DMA remaining length */
uint32 dma_endCycles; /* DMA end cycle */
uint8 dma_type; /* DMA mode */
/* Global variables */ /* Global variables */
uint16 ntab; /* Name table A base address */ uint16 ntab; /* Name table A base address */
@ -138,13 +140,11 @@ static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF };
static uint8 border; /* Border color index */ static uint8 border; /* Border color index */
static uint8 pending; /* Pending write flag */ static uint8 pending; /* Pending write flag */
static uint8 code; /* Code register */ static uint8 code; /* Code register */
static uint8 dma_type; /* DMA mode */
static uint16 addr; /* Address register */ static uint16 addr; /* Address register */
static uint16 addr_latch; /* Latched A15, A14 of address */ static uint16 addr_latch; /* Latched A15, A14 of address */
static uint16 sat_base_mask; /* Base bits of SAT */ static uint16 sat_base_mask; /* Base bits of SAT */
static uint16 sat_addr_mask; /* Index bits of SAT */ static uint16 sat_addr_mask; /* Index bits of SAT */
static uint16 dma_src; /* DMA source address */ static uint16 dma_src; /* DMA source address */
static uint32 dma_endCycles; /* 68k cycles to DMA end */
static int dmafill; /* DMA Fill pending flag */ static int dmafill; /* DMA Fill pending flag */
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 ring-buffer */ static uint16 fifo[4]; /* FIFO ring-buffer */
@ -630,7 +630,7 @@ void vdp_dma_update(unsigned int cycles)
else if (rate == 204) rate = 198; /* 6 refresh slots per line in H40 mode when display is off */ else if (rate == 204) rate = 198; /* 6 refresh slots per line in H40 mode when display is off */
} }
/* Remaining DMA cycles */ /* Available DMA cycles */
if (status & 8) if (status & 8)
{ {
/* Process DMA until the end of VBLANK */ /* Process DMA until the end of VBLANK */
@ -645,14 +645,14 @@ void vdp_dma_update(unsigned int cycles)
dma_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - cycles; dma_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - cycles;
} }
/* Remaining DMA bytes for that line */ /* Max number of DMA bytes to be processed */
dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE; dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE;
#ifdef LOGVDP #ifdef LOGVDP
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, (v_counter + (cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE,dma_type, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg(M68K_REG_PC)); error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, (v_counter + (cycles - mcycles_vdp)/MCYCLES_PER_LINE)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE,dma_type, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg(M68K_REG_PC));
#endif #endif
/* Check if DMA can be finished before the end of current line */ /* Check if DMA can be finished within current timeframe */
if (dma_length < dma_bytes) if (dma_length < dma_bytes)
{ {
/* Adjust remaining DMA bytes */ /* Adjust remaining DMA bytes */
@ -660,25 +660,35 @@ void vdp_dma_update(unsigned int cycles)
dma_cycles = (dma_bytes * MCYCLES_PER_LINE) / rate; dma_cycles = (dma_bytes * MCYCLES_PER_LINE) / rate;
} }
/* Update DMA timings */ /* Set DMA end cycle */
dma_endCycles = cycles + dma_cycles;
#ifdef LOGVDP
error("-->DMA ends at %d cycles\n", dma_endCycles);
#endif
/* Check if 68k bus is accessed by DMA */
if (dma_type < 2) if (dma_type < 2)
{ {
/* 68K is frozen during DMA from 68k bus */ /* 68K is waiting during DMA from 68k bus */
m68k.cycles = cycles + dma_cycles; m68k.cycles = dma_endCycles;
#ifdef LOGVDP #ifdef LOGVDP
error("-->CPU frozen for %d cycles\n", dma_cycles); error("-->68K CPU waiting for %d cycles\n", dma_cycles);
#endif #endif
/* Check if Z80 is waiting for 68k bus */
if (zstate & 4)
{
/* force Z80 to wait until end of DMA timeframe */
Z80.cycles = dma_endCycles;
#ifdef LOGVDP
error("-->Z80 CPU waiting for %d cycles\n", dma_cycles);
#endif
}
} }
else else
{ {
/* Set DMA Busy flag */ /* Set DMA Busy flag only when 68K can read it */
status |= 0x02; status |= 0x02;
/* 68K is still running, set DMA end cycle */
dma_endCycles = cycles + dma_cycles;
#ifdef LOGVDP
error("-->DMA ends in %d cycles\n", dma_cycles);
#endif
} }
/* Process DMA */ /* Process DMA */
@ -707,6 +717,9 @@ void vdp_dma_update(unsigned int cycles)
vdp_68k_ctrl_w(cached_write); vdp_68k_ctrl_w(cached_write);
cached_write = -1; cached_write = -1;
} }
/* indicate Z80 is not waiting for 68k bus at the end of DMA timeframe */
zstate &= ~4;
} }
} }
} }

View File

@ -52,6 +52,8 @@ extern uint8 hint_pending;
extern uint8 vint_pending; extern uint8 vint_pending;
extern uint16 status; extern uint16 status;
extern uint32 dma_length; extern uint32 dma_length;
extern uint32 dma_endCycles;
extern uint8 dma_type;
/* Global variables */ /* Global variables */
extern uint16 ntab; extern uint16 ntab;