diff options
author | 2022-05-23 15:53:17 +0200 | |
---|---|---|
committer | 2022-05-23 15:53:17 +0200 | |
commit | 641c55693bbbe35b8044d960ad5b65d65e322c23 (patch) | |
tree | 067352d2e775e223e9e32f4987fcac1b08994c65 /src | |
parent | 0c98b7e1d2fa884cf0d75e6283ae03d5e63dcc3f (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.cpp | 33 | ||||
-rw-r--r-- | src/devices/video/315_5313.cpp | 53 | ||||
-rw-r--r-- | src/mame/drivers/megadriv_acbl.cpp | 61 | ||||
-rw-r--r-- | src/mame/includes/megadriv_acbl.h | 25 | ||||
-rw-r--r-- | src/mame/machine/megacd.cpp | 42 | ||||
-rw-r--r-- | src/mame/machine/megadriv.cpp | 95 |
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) |