summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2022-05-23 15:53:17 +0200
committer GitHub <noreply@github.com>2022-05-23 15:53:17 +0200
commit641c55693bbbe35b8044d960ad5b65d65e322c23 (patch)
tree067352d2e775e223e9e32f4987fcac1b08994c65 /src
parent0c98b7e1d2fa884cf0d75e6283ae03d5e63dcc3f (diff)
megadriv.xml: compatibility field cleanups, apply minor fixes (#9732) [Angelo Salese, 0kmg]
- megadriv.xml: fix booger ROM loading; - megadriv.xml: fix wboy5 and turmamon EEPROM saving; - megadriv.xml: add SRAM to shijie, fixes roster names; - megadriv.xml: allow nba2k and nba2k5 to boot; - megacd.cpp: remove gross hack, allow megacdj & megacd2j to boot again; - jcart.cpp: fix P3 and P4 labels; - megadriv.xml: add SRAM to fengshen; - megadriv_acbl.cpp: make sonic3mb to boot, add basic protection sim;
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/megadrive/jcart.cpp33
-rw-r--r--src/devices/video/315_5313.cpp53
-rw-r--r--src/mame/drivers/megadriv_acbl.cpp61
-rw-r--r--src/mame/includes/megadriv_acbl.h25
-rw-r--r--src/mame/machine/megacd.cpp42
-rw-r--r--src/mame/machine/megadriv.cpp95
6 files changed, 191 insertions, 118 deletions
diff --git a/src/devices/bus/megadrive/jcart.cpp b/src/devices/bus/megadrive/jcart.cpp
index f823fb8dfa2..d41116d762e 100644
--- a/src/devices/bus/megadrive/jcart.cpp
+++ b/src/devices/bus/megadrive/jcart.cpp
@@ -90,25 +90,24 @@ void md_seprom_mm96_device::device_add_mconfig(machine_config &config)
static INPUT_PORTS_START( jcart_ipt )
PORT_START("JCART3") /* Joypad 3 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(3)
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Up")
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Down")
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Left")
+ PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Right")
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("%p B")
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("%p C")
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("%p A")
+ PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("%p Start")
PORT_START("JCART4") /* Joypad 4 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(4)
-
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Up")
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Down")
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Left")
+ PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Right")
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("%p B")
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("%p C")
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("%p A")
+ PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("%p Start")
INPUT_PORTS_END
ioport_constructor md_jcart_device::device_input_ports() const
diff --git a/src/devices/video/315_5313.cpp b/src/devices/video/315_5313.cpp
index ec0a9d8dc96..fad6d4a39de 100644
--- a/src/devices/video/315_5313.cpp
+++ b/src/devices/video/315_5313.cpp
@@ -3,12 +3,12 @@
/*
Sega 315-5313 VDP emulation, used by Mega Drive/Genesis
- TODO:
- - Video, DMA timing and HV counter seem incorrect,
- they need verification on real hardware.
- - Support 128KB VRAM configuration, did any hardware use it?
- - Is border area displayable?
- - 32X overlay with H32 mode, did all known software use this?
+TODO:
+- Video, DMA timing and HV counter are incorrect,
+ they need verification on real hardware.
+- Support 128KB VRAM configuration, did any hardware use it?
+- Is border area displayable?
+- 32X overlay with H32 mode, did all known software use this?
*/
#include "emu.h"
@@ -168,7 +168,8 @@ static const unsigned hres_mul[4] = { 5, 5, 4, 4 };
inline u8 sega315_5313_device::get_hres() { return (MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1)) & 3; }
int sega315_5313_device::screen_hpos() { return screen().hpos() / (m_lcm_scaling ? hres_mul[get_hres()] : 1); }
-#define MAX_HPOSITION 480 // TODO: 342(H32) or 427.5(H40), each scanline used 3420 cycle
+// TODO: 342(H32) or 427.5(H40), each scanline used 3420 cycle
+#define MAX_HPOSITION 480
DEFINE_DEVICE_TYPE(SEGA315_5313, sega315_5313_device, "sega315_5313", "Sega 315-5313 Megadrive VDP")
@@ -577,6 +578,9 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
{
m_regs[regnum] = value;
+// if (regnum == 1)
+// printf("%02x %02x (%lld %d %d)\n", regnum, value, screen().frame_number(), screen().hpos(), screen().vpos());
+
/* We need special handling for the IRQ enable registers, some games turn
off the irqs before they are taken, delaying them until the IRQ is turned
back on */
@@ -585,6 +589,12 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
{
//osd_printf_debug("setting reg 0, irq enable is now %d\n", MEGADRIVE_REG0_IRQ4_ENABLE);
+ // fatalrew and sesame are very fussy about pending interrupts.
+ // Former in particular will quickly enable both after the EA logo (cfr. killshow at PC=0x2267a),
+ // and irq 6 will jump to illegal addresses because the correlated routine isn't set in stack
+ // but delayed a bit.
+ // Note that irq 6 is masked for about 5 frames, leaving the assumption that it mustn't
+ // be left on during all this time.
if (m_irq4_pending)
{
if (MEGADRIVE_REG0_IRQ4_ENABLE)
@@ -592,12 +602,6 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
else
m_lv4irqline_callback(false);
}
-
- /* ??? Fatal Rewind needs this but I'm not sure it's accurate behavior
- it causes flickering in roadrash */
- // m_irq6_pending = 0;
- // m_irq4_pending = 0;
-
}
if (regnum == 0x01)
@@ -608,13 +612,7 @@ void sega315_5313_device::vdp_set_register(int regnum, u8 value)
m_lv6irqline_callback(true);
else
m_lv6irqline_callback(false);
-
}
-
- /* ??? */
- // m_irq6_pending = 0;
- // m_irq4_pending = 0;
-
}
// if (regnum == 0x0a)
@@ -648,7 +646,8 @@ inline u16 sega315_5313_device::vdp_get_word_from_68k_mem(u32 source)
return m_space68k->read_word(source);
else
{
- printf("DMA Read unmapped %06x\n", source);
+ // klaxp
+ logerror("DMA Read unmapped %06x\n", source);
return machine().rand();
}
}
@@ -1469,7 +1468,8 @@ void sega315_5313_device::render_spriteline_to_spritebuffer(int scanline)
if (pri == 1) pri = 0x80;
else pri = 0x40;
- /* todo: fix me, I'm sure this isn't right but sprite 0 + other sprite seem to do something..
+ // FIXME: Checkout this portion
+ /* I'm sure this isn't right but sprite 0 + other sprite seem to do something..
maybe spritemask |= 2 should be set for anything < 0x40 ?*/
if (xpos == 0x00) spritemask |= 1;
@@ -2252,6 +2252,7 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
{
if (!m_use_alt_timing) m_scanline_counter++;
// osd_printf_debug("scanline %d\n", get_scanline_counter());
+ // TODO: arbitrary timing
m_render_timer->adjust(attotime::from_usec(1));
if (get_scanline_counter() == m_irq6_scanline)
@@ -2266,11 +2267,11 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
// if (get_scanline_counter() == 0) m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
// m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
- if (get_scanline_counter()<=224)
+ if (get_scanline_counter() <= 224)
{
m_irq4counter--;
- if (m_irq4counter== - 1)
+ if (m_irq4counter == -1)
{
if (m_imode == 3) m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE * 2;
else m_irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
@@ -2279,9 +2280,12 @@ void sega315_5313_device::vdp_handle_scanline_callback(int scanline)
if (MEGADRIVE_REG0_IRQ4_ENABLE)
{
+ // TODO: arbitrary timing
m_irq4_on_timer->adjust(attotime::from_usec(1));
//osd_printf_debug("irq4 on scanline %d reload %d\n", get_scanline_counter(), MEGADRIVE_REG0A_HINT_VALUE);
}
+ else
+ m_irq4_on_timer->adjust(attotime::never);
}
}
else
@@ -2319,7 +2323,8 @@ void sega315_5313_device::vdp_handle_eof()
int scr_mul = 1;
m_vblank_flag = 0;
- //m_irq6_pending = 0; /* NO! (breaks warlock) */
+ // Not here, breaks warlock
+ //m_irq6_pending = 0;
/* Set it to -1 here, so it becomes 0 when the first timer kicks in */
if (!m_use_alt_timing) m_scanline_counter = -1;
diff --git a/src/mame/drivers/megadriv_acbl.cpp b/src/mame/drivers/megadriv_acbl.cpp
index 5c0250dd0b5..7299c40b9e4 100644
--- a/src/mame/drivers/megadriv_acbl.cpp
+++ b/src/mame/drivers/megadriv_acbl.cpp
@@ -367,13 +367,38 @@ uint16_t md_boot_state::barek2mb_r()
return 0x0000;
}
-uint16_t md_boot_state::sonic3mb_r()
+void md_sonic3bl_state::prot_w(u8 data)
{
- if (m_maincpu->pc() == 0x1688) return 0x0300; // TODO: should work but doesn't? debug: just put 0x0300 at 0xfffffc during the first startup check to succesfully boot. Coins are stored in the same location
+ m_prot_cmd = data;
+}
- // logerror("sonic3mb_r : %06x\n", m_maincpu->pc());
+// PIC simulation, it just handles coinage and DSWs
+uint16_t md_sonic3bl_state::prot_r()
+{
+ u16 res = 0;
+ switch (m_prot_cmd)
+ {
+ // POST, upper 8-bits part is fixed and needed for booting game,
+ // lower is DSW, cfr. PC=0x16c0/0x16c6 subroutines, lower 4 bits not actually handled by 68k side
+ case 0x33: res = 0x0300 | (m_in_mcu->read() & 0xff); break;
+ case 0x00:
+ // TODO: coinage
+ // lower 8-bits is adder for coins (i.e. with 0x202 will add 2 credits to the counter),
+ // bit 9 is coin state, active high
+ res = m_in_coin->read() & 0x88 ? 0x201 : 0;
+ break;
+ case 0x66:
+ // handshake or coin status after reading from commands 0x33 or 0x00,
+ // if bit 0 is high will tight loop until it's low
+ // we currently go the coin status route to not bother handling coin off manually.
+ res = m_in_coin->read() ? 1 : 0;
+ break;
+ default:
+ logerror("Unhandled %04x prot command\n", m_prot_cmd);
+ break;
+ }
- return 0x0000;
+ return res;
}
uint16_t md_boot_state::dsw_r(offs_t offset)
@@ -721,6 +746,26 @@ INPUT_PORTS_START( twinktmb )
PORT_BIT( 0xff00, IP_ACTIVE_HIGH, IPT_UNUSED )
INPUT_PORTS_END
+INPUT_PORTS_START( sonic3mb )
+ PORT_INCLUDE( twinktmb )
+
+ PORT_MODIFY("MCU")
+ // TODO: actual diplocations
+ // lower 4 bits is for coinage? Not read by 68k
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_DIPNAME( 0x30, 0x10, DEF_STR( Lives ) )
+ PORT_DIPSETTING( 0x30, "1" )
+ PORT_DIPSETTING( 0x20, "2" )
+ PORT_DIPSETTING( 0x10, "3" )
+ PORT_DIPSETTING( 0x00, "4" )
+ PORT_DIPNAME( 0xc0, 0x00, "Time Limit" )
+ PORT_DIPSETTING( 0xc0, "1:00" )
+ PORT_DIPSETTING( 0x80, "2:00" )
+ PORT_DIPSETTING( 0x40, "3:00" )
+ PORT_DIPSETTING( 0x00, "4:00" )
+INPUT_PORTS_END
+
+
// Verified from M68000 code
INPUT_PORTS_START( srmdb )
PORT_INCLUDE( md_common )
@@ -1331,10 +1376,10 @@ void md_boot_state::init_sonic2mb()
init_megadrij();
}
-void md_boot_state::init_sonic3mb()
+void md_sonic3bl_state::init_sonic3mb()
{
- // m_maincpu->space(AS_PROGRAM).install_write_handler(0x200000, 0x200001, write16smo_delegate(*this, FUNC(md_boot_state::sonic3mb_w))); // seems to write to PIC from here
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x300000, 0x300001, read16smo_delegate(*this, FUNC(md_boot_state::sonic3mb_r))); // reads from PIC from here
+ m_maincpu->space(AS_PROGRAM).install_write_handler(0x200000, 0x200000, write8smo_delegate(*this, FUNC(md_sonic3bl_state::prot_w)));
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0x300000, 0x300001, read16smo_delegate(*this, FUNC(md_sonic3bl_state::prot_r)));
init_megadrij();
}
@@ -1541,7 +1586,7 @@ GAME( 1993, srmdb, 0, megadrvb, srmdb, md_boot_state, init_srmdb, R
GAME( 1995, topshoot, 0, md_bootleg, topshoot, md_boot_state, init_topshoot, ROT0, "Sun Mixing", "Top Shooter", 0 )
GAME( 1996, sbubsm, 0, md_bootleg, sbubsm, md_boot_state, init_sbubsm, ROT0, "Sun Mixing", "Super Bubble Bobble (Sun Mixing, Mega Drive clone hardware)", 0 )
GAME( 1993, sonic2mb, 0, md_bootleg, sonic2mb, md_boot_state, init_sonic2mb, ROT0, "bootleg / Sega", "Sonic The Hedgehog 2 (bootleg of Mega Drive version)", 0 ) // Flying wires going through the empty PIC space aren't completely understood
-GAME( 1993, sonic3mb, 0, md_bootleg, twinktmb, md_boot_state, init_sonic3mb, ROT0, "bootleg / Sega", "Sonic The Hedgehog 3 (bootleg of Mega Drive version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // undumped PIC
+GAME( 1993, sonic3mb, 0, md_bootleg, sonic3mb, md_sonic3bl_state, init_sonic3mb, ROT0, "bootleg / Sega", "Sonic The Hedgehog 3 (bootleg of Mega Drive version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // undumped PIC
GAME( 1994, barek2mb, 0, md_bootleg, barek2, md_boot_state, init_barek2, ROT0, "bootleg / Sega", "Bare Knuckle II (bootleg of Mega Drive version)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // Needs PIC hook up
GAME( 1994, barek3mb, 0, megadrvb, barek3, md_boot_state, init_barek3, ROT0, "bootleg / Sega", "Bare Knuckle III (bootleg of Mega Drive version)", 0 )
GAME( 1994, bk3ssrmb, 0, megadrvb_6b, bk3ssrmb, md_boot_6button_state, init_bk3ssrmb, ROT0, "bootleg / Sega", "Bare Knuckle III / Sunset Riders (bootleg of Mega Drive versions)", MACHINE_NOT_WORKING ) // Currently boots as Bare Knuckle III, mechanism to switch game not found yet
diff --git a/src/mame/includes/megadriv_acbl.h b/src/mame/includes/megadriv_acbl.h
index 2f64b1ed890..49a296976e2 100644
--- a/src/mame/includes/megadriv_acbl.h
+++ b/src/mame/includes/megadriv_acbl.h
@@ -8,7 +8,7 @@ class md_boot_state : public md_base_state
{
public:
md_boot_state(const machine_config &mconfig, device_type type, const char *tag)
- : md_base_state(mconfig, type, tag) { m_protcount = 0;}
+ : md_base_state(mconfig, type, tag) { m_protcount = 0; }
void megadrvb(machine_config &config);
void md_bootleg(machine_config &config);
@@ -28,7 +28,6 @@ public:
void init_barekch();
void init_bk3ssrmb();
void init_sonic2mb();
- void init_sonic3mb();
void init_twinktmb();
void init_jparkmb();
void init_sbubsm();
@@ -40,7 +39,6 @@ private:
uint16_t aladmdb_r();
uint16_t barek2mb_r();
uint16_t jparkmb_r();
- uint16_t sonic3mb_r();
uint16_t twinktmb_r();
uint16_t dsw_r(offs_t offset);
uint16_t topshoot_200051_r();
@@ -60,6 +58,27 @@ private:
int m_protcount;
};
+class md_sonic3bl_state : public md_boot_state
+{
+public:
+ md_sonic3bl_state(const machine_config &mconfig, device_type type, const char *tag)
+ : md_boot_state(mconfig, type, tag)
+ , m_in_coin(*this, "COIN")
+ , m_in_mcu(*this, "MCU")
+ { }
+
+ void init_sonic3mb();
+
+private:
+ required_ioport m_in_coin;
+ required_ioport m_in_mcu;
+
+ void prot_w(u8 data);
+ uint16_t prot_r();
+
+ u8 m_prot_cmd = 0;
+};
+
class md_boot_6button_state : public md_boot_state
{
public:
diff --git a/src/mame/machine/megacd.cpp b/src/mame/machine/megacd.cpp
index a1b74c69cd7..6780593dcb7 100644
--- a/src/mame/machine/megacd.cpp
+++ b/src/mame/machine/megacd.cpp
@@ -16,26 +16,6 @@
#define DMA_PRG (0x0500)
#define DMA_WRAM (0x0700)
-// irq3 timer
-#define CHECK_SCD_LV3_INTERRUPT \
- if (m_lc89510_temp->get_segacd_irq_mask() & 0x08) \
- { \
- m_scdcpu->set_input_line(3, HOLD_LINE); \
- }
-// from master
-#define CHECK_SCD_LV2_INTERRUPT \
- if (m_lc89510_temp->get_segacd_irq_mask() & 0x04) \
- { \
- m_scdcpu->set_input_line(2, HOLD_LINE); \
- }
-
-// gfx convert
-#define CHECK_SCD_LV1_INTERRUPT \
- if (m_lc89510_temp->get_segacd_irq_mask() & 0x02) \
- { \
- m_scdcpu->set_input_line(1, HOLD_LINE); \
- }
-
#define SEGACD_IRQ3_TIMER_SPEED (attotime::from_nsec(m_irq3_timer_reg*30720))
@@ -60,16 +40,19 @@ IRQ_CALLBACK_MEMBER(sega_segacd_device::segacd_sub_int_callback)
TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::irq3_timer_callback )
{
- CHECK_SCD_LV3_INTERRUPT
+ if (m_lc89510_temp->get_segacd_irq_mask() & 0x08)
+ m_scdcpu->set_input_line(3, HOLD_LINE);
+
m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED);
}
-
+// GFX conversion
TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::stamp_timer_callback )
{
//printf("stamp_timer_callback\n");
- CHECK_SCD_LV1_INTERRUPT
+ if (m_lc89510_temp->get_segacd_irq_mask() & 0x02)
+ m_scdcpu->set_input_line(1, HOLD_LINE);
segacd_conversion_active = 0;
@@ -513,10 +496,9 @@ void sega_segacd_device::scd_a12000_halt_reset_w(offs_t offset, uint16_t data, u
if (ACCESSING_BITS_8_15)
{
- if (m_a12000_halt_reset_reg & 0x0100)
- {
- CHECK_SCD_LV2_INTERRUPT
- }
+ // from master CPU
+ if (m_a12000_halt_reset_reg & 0x0100 && m_lc89510_temp->get_segacd_irq_mask() & 0x04)
+ m_scdcpu->set_input_line(2, HOLD_LINE);
if (m_a12000_halt_reset_reg & 0x8000)
{
@@ -1802,13 +1784,13 @@ void sega_segacd_device::device_reset()
m_total_scanlines = 262;
- // HACK!!!! timegal, anettfut, roadaven end up with the SubCPU waiting in a loop for *something*
+ // HACK!!!! timegal, anettfut, roadaven/rbfx end up with the SubCPU waiting in a loop for *something*
// overclocking the CPU, even at the point where the game is hung, allows them to continue and boot
// I'm not sure what the source of this timing problem is, it's not using IRQ3 or StopWatch at the
// time. Changing the CDHock timer to 50hz from 75hz also stops the hang, but then the video is
// too slow and has bad sound. -- Investigate!
-
- m_scdcpu->set_clock_scale(1.5000f);
+ // Update: removed, otherwise megacdj and megacd2j will black screen with no cdrom inserted.
+ //m_scdcpu->set_clock_scale(1.5000f);
// initialize some stuff on reset
diff --git a/src/mame/machine/megadriv.cpp b/src/mame/machine/megadriv.cpp
index c0a76898b71..3f4d649db2c 100644
--- a/src/mame/machine/megadriv.cpp
+++ b/src/mame/machine/megadriv.cpp
@@ -27,22 +27,40 @@ Known Non-Issues (confirmed on Real Genesis)
#include "includes/megadriv.h"
#include "speaker.h"
+#define LOG_AUDIOBANK (1U << 1) // z80 to 68k space window access at $8000-$ffff
+#define LOG_AUDIOBUS (1U << 2) // z80 bus grants
+#define LOG_AUDIORESET (1U << 3) // z80 reset line
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGAUDIOBANK(...) LOGMASKED(LOG_AUDIOBANK, __VA_ARGS__)
+#define LOGAUDIOBUS(...) LOGMASKED(LOG_AUDIOBUS, __VA_ARGS__)
+#define LOGAUDIORESET(...) LOGMASKED(LOG_AUDIORESET, __VA_ARGS__)
+
void md_base_state::megadriv_z80_bank_w(uint16_t data)
{
+ // TODO: menghu crashes here
+ // Tries to setup a bank of 0xff0000 from z80 side (PC=1131) after you talk with the cashier twice.
+ // Without a guard over it game will trash 68k memory causing a crash, works on real HW with everdrive
+ // so not coming from a cart copy protection.
+ // Update: it breaks cfodder BGM on character select at least, therefore we current don't guard against it
+ // Apparently reading 68k RAM from z80 is not recommended by Sega, so *writing* isn't possible lacking bus grant?
m_genz80.z80_bank_addr = ((m_genz80.z80_bank_addr >> 1) | (data << 23)) & 0xff8000;
}
void md_base_state::megadriv_68k_z80_bank_write(uint16_t data)
{
- //logerror("%06x: 68k writing bit to bank register %01x\n", m_maincpu->pc(),data&0x01);
megadriv_z80_bank_w(data & 0x01);
}
void md_base_state::megadriv_z80_z80_bank_w(uint8_t data)
{
- //logerror("%04x: z80 writing bit to bank register %01x\n", m_maincpu->pc(),data&0x01);
+ LOGAUDIOBANK("%s: port $6000 write 0x%02x ", machine().describe_context(), data);
megadriv_z80_bank_w(data & 0x01);
+ LOGAUDIOBANK("Current bank %08x\n", m_genz80.z80_bank_addr);
}
uint8_t md_base_state::megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask)
@@ -54,7 +72,7 @@ uint8_t md_base_state::megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask)
}
else
{
- logerror("%s: 68000 attempting to access YM2612 (read) without bus\n", machine().describe_context());
+ LOG("%s: 68000 attempting to access YM2612 (read) without bus\n", machine().describe_context());
return 0;
}
@@ -72,7 +90,7 @@ void md_base_state::megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8
}
else
{
- logerror("%s: 68000 attempting to access YM2612 (write) without bus\n", machine().describe_context());
+ LOG("%s: 68000 attempting to access YM2612 (write) without bus\n", machine().describe_context());
}
}
@@ -309,8 +327,10 @@ uint16_t md_base_state::megadriv_68k_io_read(offs_t offset)
switch (offset)
{
case 0:
- logerror("%06x read version register\n", m_maincpu->pc());
- retdata = m_version_hi_nibble | 0x01; // Version number contained in bits 3-0
+ LOG("%06x read version register\n", m_maincpu->pc());
+ // Version number contained in bits 3-0
+ // TODO: non-TMSS BIOSes must return 0 here
+ retdata = m_version_hi_nibble | 0x01;
break;
/* Joystick Port Registers */
@@ -486,15 +506,13 @@ uint16_t md_base_state::megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_ma
}
else
{
- logerror("%06x: 68000 attempting to access Z80 (read) address space without bus\n", m_maincpu->pc());
+ LOG("%06x: 68000 attempting to access Z80 (read) address space without bus\n", m_maincpu->pc());
return machine().rand();
}
}
void md_base_state::megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- //logerror("write z80 ram\n");
-
if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0))
{
if (!ACCESSING_BITS_0_7) // byte (MSB) access
@@ -505,30 +523,33 @@ void md_base_state::megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uin
{
m_genz80.z80_prgram[(offset<<1)^1] = (data & 0x00ff);
}
- else // for WORD access only the MSB is used, LSB is ignored
+ else
{
+ // for WORD access only the MSB is used, LSB is ignored
m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8;
}
}
else
{
- logerror("%06x: 68000 attempting to access Z80 (write) address space without bus\n", m_maincpu->pc());
+ LOG("%06x: 68000 attempting to access Z80 (write) address space without bus\n", m_maincpu->pc());
}
}
-
+/*
+ * ddragon, beast, superoff, and timekill have buggy sound programs.
+ * They request the bus, then have a loop which waits for the bus
+ * to be unavailable, checking for a 0 value due to bad coding. The real hardware
+ * appears to return bits of the next instruction in the unused bits, thus meaning
+ * the value is never zero. Time Killers is the most fussy, and doesn't like the
+ * read_next_instruction function from system16, so I just return a random value
+ * in the unused bits
+ */
uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_mask)
{
uint16_t retvalue;
- /* Double Dragon, Shadow of the Beast, Super Off Road, and Time Killers have buggy
- sound programs. They request the bus, then have a loop which waits for the bus
- to be unavailable, checking for a 0 value due to bad coding. The real hardware
- appears to return bits of the next instruction in the unused bits, thus meaning
- the value is never zero. Time Killers is the most fussy, and doesn't like the
- read_next_instruction function from system16, so I just return a random value
- in the unused bits */
- uint16_t nextvalue = machine().rand();//read_next_instruction(space)&0xff00;
+
+ uint16_t nextvalue = machine().rand(); //read_next_instruction(space)&0xff00;
/* Check if the 68k has the z80 bus */
@@ -537,13 +558,13 @@ uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_m
if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100;
else retvalue = (nextvalue & 0xfeff);
- //logerror("%06x: 68000 check z80 Bus (byte MSB access) returning %04x mask %04x\n", m_maincpu->pc(),retvalue, mem_mask);
+ LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte MSB access) returning %04x mask %04x\n", m_maincpu->pc(),retvalue, mem_mask);
return retvalue;
}
else if (!ACCESSING_BITS_8_15) // is this valid?
{
- //logerror("%06x: 68000 check z80 Bus (byte LSB access) %04x\n", m_maincpu->pc(),mem_mask);
+ LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte LSB access) %04x\n", m_maincpu->pc(), mem_mask);
if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = 0x0001;
else retvalue = 0x0000;
@@ -551,7 +572,7 @@ uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_m
}
else
{
- //logerror("%06x: 68000 check z80 Bus (word access) %04x\n", m_maincpu->pc(),mem_mask);
+ LOGAUDIOBUS("%06x: 68000 check z80 Bus (word access) %04x\n", m_maincpu->pc(),mem_mask);
if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100;
else retvalue = (nextvalue & 0xfeff);
@@ -564,6 +585,7 @@ uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_m
TIMER_CALLBACK_MEMBER(md_base_state::megadriv_z80_run_state)
{
/* Is the z80 RESET line pulled? */
+ // TODO: Z80 /RESET
if (m_genz80.z80_is_reset)
{
m_z80snd->reset();
@@ -573,6 +595,7 @@ TIMER_CALLBACK_MEMBER(md_base_state::megadriv_z80_run_state)
else
{
/* Check if z80 has the bus */
+ // TODO: Z80 /BUSREQ
if (m_genz80.z80_has_bus)
m_z80snd->resume(SUSPEND_REASON_HALT);
else
@@ -588,12 +611,12 @@ void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint1
{
if (data & 0x0100)
{
- //logerror("%06x: 68000 request z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 0;
}
else
{
- //logerror("%06x: 68000 return z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 1;
}
}
@@ -601,12 +624,12 @@ void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint1
{
if (data & 0x0001)
{
- //logerror("%06x: 68000 request z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 0;
}
else
{
- //logerror("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 1;
}
}
@@ -614,12 +637,12 @@ void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint1
{
if (data & 0x0100)
{
- //logerror("%06x: 68000 request z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 request z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 0;
}
else
{
- //logerror("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_has_bus = 1;
}
}
@@ -635,12 +658,12 @@ void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uin
{
if (data & 0x0100)
{
- //logerror("%06x: 68000 clear z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 clear z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 0;
}
else
{
- //logerror("%06x: 68000 start z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 start z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 1;
}
}
@@ -648,12 +671,12 @@ void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uin
{
if (data & 0x0001)
{
- //logerror("%06x: 68000 clear z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 clear z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 0;
}
else
{
- //logerror("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 1;
}
}
@@ -661,12 +684,12 @@ void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uin
{
if (data & 0x0100)
{
- //logerror("%06x: 68000 clear z80 reset (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 clear z80 reset (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 0;
}
else
{
- //logerror("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
+ LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask);
m_genz80.z80_is_reset = 1;
}
}
@@ -756,7 +779,7 @@ void md_base_state::megadriv_z80_map(address_map &map)
void md_base_state::megadriv_z80_io_map(address_map &map)
{
map.global_mask(0xff);
- map(0x0000, 0xff).noprw();
+ map(0x00, 0xff).noprw();
}
uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)