diff options
Diffstat (limited to 'src/mame/machine/megadriv.cpp')
-rw-r--r-- | src/mame/machine/megadriv.cpp | 1103 |
1 files changed, 0 insertions, 1103 deletions
diff --git a/src/mame/machine/megadriv.cpp b/src/mame/machine/megadriv.cpp deleted file mode 100644 index 7c384e683e1..00000000000 --- a/src/mame/machine/megadriv.cpp +++ /dev/null @@ -1,1103 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/* - -Megadrive / Genesis support - -this could probably do with a complete rewrite at this point to take into -account all new information discovered since this was created, it's looking -rather old now. - - - -Cleanup / Rewrite notes: - - - -Known Non-Issues (confirmed on Real Genesis) - Castlevania - Bloodlines (U) [!] - Pause text is missing on upside down level - Blood Shot (E) (M4) [!] - corrupt texture in level 1 is correct... - - - -*/ - - -#include "emu.h" -#include "includes/megadriv.h" -#include "speaker.h" - - -void md_base_state::megadriv_z80_bank_w(uint16_t data) -{ - 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); - megadriv_z80_bank_w(data & 0x01); -} - -uint8_t md_base_state::megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask) -{ - //osd_printf_debug("megadriv_68k_YM2612_read %02x %04x\n",offset,mem_mask); - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - return m_ymsnd->read(offset); - } - else - { - logerror("%s: 68000 attempting to access YM2612 (read) without bus\n", machine().describe_context()); - return 0; - } - - // never executed - //return -1; -} - - -void md_base_state::megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask) -{ - //osd_printf_debug("megadriv_68k_YM2612_write %02x %04x %04x\n",offset,data,mem_mask); - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - m_ymsnd->write(offset, data); - } - else - { - logerror("%s: 68000 attempting to access YM2612 (write) without bus\n", machine().describe_context()); - } -} - -// this is used by 6 button pads and gets installed in machine_start for drivers requiring it -TIMER_CALLBACK_MEMBER(md_base_state::io_timeout_timer_callback) -{ - m_io_stage[(int)(uintptr_t)ptr] = -1; -} - - -/* - - A10001h = A0 Version register - - A10003h = 7F Data register for port A - A10005h = 7F Data register for port B - A10007h = 7F Data register for port C - - A10009h = 00 Ctrl register for port A - A1000Bh = 00 Ctrl register for port B - A1000Dh = 00 Ctrl register for port C - - A1000Fh = FF TxData register for port A - A10011h = 00 RxData register for port A - A10013h = 00 S-Ctrl register for port A - - A10015h = FF TxData register for port B - A10017h = 00 RxData register for port B - A10019h = 00 S-Ctrl register for port B - - A1001Bh = FF TxData register for port C - A1001Dh = 00 RxData register for port C - A1001Fh = 00 S-Ctrl register for port C - - - - - Bit 7 - (Not connected) - Bit 6 - TH - Bit 5 - TL - Bit 4 - TR - Bit 3 - RIGHT - Bit 2 - LEFT - Bit 1 - DOWN - Bit 0 - UP - - -*/ - -INPUT_PORTS_START( md_common ) - PORT_START("PAD1") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") // b - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") // c - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") // a - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 START") // start - - PORT_START("PAD2") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") // b - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") // c - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") // a - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 START") // start -INPUT_PORTS_END - - -INPUT_PORTS_START( megadriv ) - PORT_INCLUDE( md_common ) - - PORT_START("RESET") /* Buttons on Genesis Console */ - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) -INPUT_PORTS_END - -INPUT_PORTS_START( megadri6 ) - PORT_INCLUDE( megadriv ) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) PORT_NAME("P1 MODE") // mode - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("P2 MODE") // mode -INPUT_PORTS_END - -void md_base_state::megadrive_reset_io() -{ - int i; - - m_megadrive_io_data_regs[0] = 0x7f; - m_megadrive_io_data_regs[1] = 0x7f; - m_megadrive_io_data_regs[2] = 0x7f; - m_megadrive_io_ctrl_regs[0] = 0x00; - m_megadrive_io_ctrl_regs[1] = 0x00; - m_megadrive_io_ctrl_regs[2] = 0x00; - m_megadrive_io_tx_regs[0] = 0xff; - m_megadrive_io_tx_regs[1] = 0xff; - m_megadrive_io_tx_regs[2] = 0xff; - - for (i=0; i<3; i++) - { - m_io_stage[i] = -1; - } -} - -/************* 6 buttons version **************************/ -uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) -{ - int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from m_megadrive_io_data_regs - - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - if (m_io_stage[portnum] == 2) - { - /* here we read B, C & the additional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x30) | - ((m_io_pad_6b[portnum] ? m_io_pad_6b[portnum]->read() : 0) & 0x0f)) & ~helper); - } - else - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) & ~helper); - } - } - else - { - if (m_io_stage[portnum] == 1) - { - /* here we read ((Start & A) >> 2) | 0x00 */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) & ~helper); - } - else if (m_io_stage[portnum]==2) - { - /* here we read ((Start & A) >> 2) | 0x0f */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03)) & ~helper); - } - } - -// osd_printf_debug("read io data port stage %d port %d %02x\n",m_io_stage[portnum],portnum,retdata); - - return retdata | (retdata << 8); -} - - -/************* 3 buttons version **************************/ -uint8_t md_base_state::megadrive_io_read_data_port_3button(offs_t offset) -{ - int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from m_megadrive_io_data_regs - - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper); - } - - return retdata; -} - -uint8_t md_base_state::megadrive_io_read_ctrl_port(int portnum) -{ - uint8_t retdata; - retdata = m_megadrive_io_ctrl_regs[portnum]; - //osd_printf_debug("read io ctrl port %d %02x\n",portnum,retdata); - - return retdata | (retdata << 8); -} - -uint8_t md_base_state::megadrive_io_read_tx_port(int portnum) -{ - uint8_t retdata; - retdata = m_megadrive_io_tx_regs[portnum]; - return retdata | (retdata << 8); -} - -uint8_t md_base_state::megadrive_io_read_rx_port(int portnum) -{ - return 0x00; -} - -uint8_t md_base_state::megadrive_io_read_sctrl_port(int portnum) -{ - return 0x00; -} - - -uint16_t md_base_state::megadriv_68k_io_read(offs_t offset) -{ - uint8_t retdata; - - retdata = 0; - /* Charles MacDonald ( http://cgfm2.emuviews.com/ ) - D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan) - D6 : Video type is 1= PAL, 0= NTSC - D5 : Sega CD unit is 1= not present, 0= connected. - D4 : Unused (always returns zero) - D3 : Bit 3 of version number - D2 : Bit 2 of version number - D1 : Bit 1 of version number - D0 : Bit 0 of version number - */ - - //return (machine().rand()&0x0f0f)|0xf0f0;//0x0000; - 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 - break; - - /* Joystick Port Registers */ - - case 0x1: - case 0x2: - case 0x3: - retdata = m_megadrive_io_read_data_port_ptr(offset-1); - break; - - case 0x4: - case 0x5: - case 0x6: - retdata = megadrive_io_read_ctrl_port(offset-4); - break; - - /* Serial I/O Registers */ - - case 0x7: retdata = megadrive_io_read_tx_port(0); break; - case 0x8: retdata = megadrive_io_read_rx_port(0); break; - case 0x9: retdata = megadrive_io_read_sctrl_port(0); break; - - case 0xa: retdata = megadrive_io_read_tx_port(1); break; - case 0xb: retdata = megadrive_io_read_rx_port(1); break; - case 0xc: retdata = megadrive_io_read_sctrl_port(1); break; - - case 0xd: retdata = megadrive_io_read_tx_port(2); break; - case 0xe: retdata = megadrive_io_read_rx_port(2); break; - case 0xf: retdata = megadrive_io_read_sctrl_port(2); break; - - } - - return retdata | (retdata << 8); -} - - -void md_base_state::megadrive_io_write_data_port_3button(offs_t offset, uint16_t data) -{ - int portnum = offset; - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); - -} - - -/****************************** 6 buttons version*****************************/ - -void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t data) -{ - int portnum = offset; - if (m_megadrive_io_ctrl_regs[portnum]&0x40) - { - if (((m_megadrive_io_data_regs[portnum]&0x40)==0x00) && ((data&0x40) == 0x40)) - { - m_io_stage[portnum]++; - m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192)); - } - - } - - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); - -} - - -/*************************** 3 buttons version ****************************/ - -void md_base_state::megadrive_io_write_ctrl_port(int portnum, uint16_t data) -{ - m_megadrive_io_ctrl_regs[portnum] = data; -// osd_printf_debug("Setting IO Control Register #%d data %04x\n",portnum,data); -} - -void md_base_state::megadrive_io_write_tx_port(int portnum, uint16_t data) -{ - m_megadrive_io_tx_regs[portnum] = data; -} - -void md_base_state::megadrive_io_write_rx_port(int portnum, uint16_t data) -{ -} - -void md_base_state::megadrive_io_write_sctrl_port(int portnum, uint16_t data) -{ -} - - -void md_base_state::megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask) -{ -// osd_printf_debug("IO Write #%02x data %04x mem_mask %04x\n",offset,data,mem_mask); - - - switch (offset) - { - case 0x0: - osd_printf_debug("Write to Version Register?!\n"); - break; - - /* Joypad Port Registers */ - - case 0x1: - case 0x2: - case 0x3: - m_megadrive_io_write_data_port_ptr(offset-1,data); - break; - - case 0x4: - case 0x5: - case 0x6: - megadrive_io_write_ctrl_port(offset-4,data); - break; - - /* Serial I/O Registers */ - - case 0x7: megadrive_io_write_tx_port(0,data); break; - case 0x8: megadrive_io_write_rx_port(0,data); break; - case 0x9: megadrive_io_write_sctrl_port(0,data); break; - - case 0xa: megadrive_io_write_tx_port(1,data); break; - case 0xb: megadrive_io_write_rx_port(1,data); break; - case 0xc: megadrive_io_write_sctrl_port(1,data); break; - - case 0xd: megadrive_io_write_tx_port(2,data); break; - case 0xe: megadrive_io_write_rx_port(2,data); break; - case 0xf: megadrive_io_write_sctrl_port(2,data); break; - } -} - - - -void md_base_state::megadriv_map(address_map &map) -{ - map(0x000000, 0x3fffff).rom(); - /* (0x000000 - 0x3fffff) == GAME ROM (4Meg Max, Some games have special banking too) */ - - map(0xa00000, 0xa01fff).rw(FUNC(md_base_state::megadriv_68k_read_z80_ram), FUNC(md_base_state::megadriv_68k_write_z80_ram)); - map(0xa02000, 0xa03fff).w(FUNC(md_base_state::megadriv_68k_write_z80_ram)); - map(0xa04000, 0xa04003).rw(FUNC(md_base_state::megadriv_68k_YM2612_read), FUNC(md_base_state::megadriv_68k_YM2612_write)); - - map(0xa06000, 0xa06001).w(FUNC(md_base_state::megadriv_68k_z80_bank_write)); - - map(0xa10000, 0xa1001f).rw(FUNC(md_base_state::megadriv_68k_io_read), FUNC(md_base_state::megadriv_68k_io_write)); - - map(0xa11100, 0xa11101).rw(FUNC(md_base_state::megadriv_68k_check_z80_bus), FUNC(md_base_state::megadriv_68k_req_z80_bus)); - map(0xa11200, 0xa11201).w(FUNC(md_base_state::megadriv_68k_req_z80_reset)); - - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xd00000, 0xd0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); // the earth defend - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); -// map(0xff0000, 0xffffff).readonly(); - /* 0xe00000 - 0xffffff) == MAIN RAM (64kb, Mirrored, most games use ff0000 - ffffff) */ -} - - -void md_base_state::dcat16_megadriv_map(address_map &map) -{ - megadriv_map(map); - map(0x000000, 0x7fffff).rom(); -} - - -/* z80 sounds/sub CPU */ - - -uint16_t md_base_state::megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_mask) -{ - //osd_printf_debug("read z80 ram %04x\n",mem_mask); - - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - return m_genz80.z80_prgram[(offset<<1)^1] | (m_genz80.z80_prgram[(offset<<1)]<<8); - } - else - { - logerror("%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 - { - m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8; - } - else if (!ACCESSING_BITS_8_15) - { - m_genz80.z80_prgram[(offset<<1)^1] = (data & 0x00ff); - } - 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()); - } -} - - -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; - - - /* Check if the 68k has the z80 bus */ - if (!ACCESSING_BITS_0_7) // byte (MSB) access - { - 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); - 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); - if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = 0x0001; - else retvalue = 0x0000; - - return retvalue; - } - else - { - //logerror("%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); - - // osd_printf_debug("%06x: 68000 check z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),mem_mask, retvalue); - return retvalue; - } -} - - -TIMER_CALLBACK_MEMBER(md_base_state::megadriv_z80_run_state) -{ - /* Is the z80 RESET line pulled? */ - if (m_genz80.z80_is_reset) - { - m_z80snd->reset(); - m_z80snd->suspend(SUSPEND_REASON_HALT, 1); - m_ymsnd->reset(); - } - else - { - /* Check if z80 has the bus */ - if (m_genz80.z80_has_bus) - m_z80snd->resume(SUSPEND_REASON_HALT); - else - m_z80snd->suspend(SUSPEND_REASON_HALT, 1); - } -} - - -void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - /* Request the Z80 bus, allows 68k to read/write Z80 address space */ - if (!ACCESSING_BITS_0_7) // byte access - { - if (data & 0x0100) - { - //logerror("%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); - m_genz80.z80_has_bus = 1; - } - } - else if (!ACCESSING_BITS_8_15) // is this valid? - { - if (data & 0x0001) - { - //logerror("%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); - m_genz80.z80_has_bus = 1; - } - } - else // word access - { - if (data & 0x0100) - { - //logerror("%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); - m_genz80.z80_has_bus = 1; - } - } - - /* If the z80 is running, sync the z80 execution state */ - if (!m_genz80.z80_is_reset) - machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(md_base_state::megadriv_z80_run_state),this)); -} - -void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (!ACCESSING_BITS_0_7) // byte access - { - if (data & 0x0100) - { - //logerror("%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); - m_genz80.z80_is_reset = 1; - } - } - else if (!ACCESSING_BITS_8_15) // is this valid? - { - if (data & 0x0001) - { - //logerror("%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); - m_genz80.z80_is_reset = 1; - } - } - else // word access - { - if (data & 0x0100) - { - //logerror("%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); - m_genz80.z80_is_reset = 1; - } - } - machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(md_base_state::megadriv_z80_run_state),this)); -} - - -// just directly access the 68k space, this makes it easier to deal with -// add-on hardware which changes the cpu mapping like the 32x and SegaCD. -// - we might need to add exceptions for example, z80 reading / writing the -// z80 area of the 68k if games misbehave -uint8_t md_base_state::z80_read_68k_banked_data(offs_t offset) -{ - address_space &space68k = m_maincpu->space(); - uint8_t ret = space68k.read_byte(m_genz80.z80_bank_addr+offset); - return ret; -} - -void md_base_state::z80_write_68k_banked_data(offs_t offset, uint8_t data) -{ - address_space &space68k = m_maincpu->space(); - space68k.write_byte(m_genz80.z80_bank_addr+offset,data); -} - -void md_base_state::megadriv_z80_vdp_write(offs_t offset, uint8_t data) -{ - switch (offset) - { - case 0x11: - case 0x13: - case 0x15: - case 0x17: - // accessed by either segapsg_device or sn76496_device - m_vdp->vdp_w(offset >> 1, data, 0x00ff); - break; - - default: - osd_printf_debug("unhandled z80 vdp write %02x %02x\n",offset,data); - } -} - - -uint8_t md_base_state::megadriv_z80_vdp_read(offs_t offset) -{ - u8 ret = 0; - u8 shift = ((~offset & 1) << 3); - switch (offset & ~1) - { - case 0x04: // ctrl_port_r - case 0x06: - case 0x08: // H/V counter - case 0x0a: - case 0x0c: - case 0x0e: - ret = m_vdp->vdp_r(offset >> 1, 0xff << shift) >> shift; - break; - - default: - if (!machine().side_effects_disabled()) - osd_printf_debug("unhandled z80 vdp read %02x\n",offset); - ret = machine().rand(); - break; - } - return ret; -} - -uint8_t md_base_state::megadriv_z80_unmapped_read() -{ - return 0xff; -} - -void md_base_state::megadriv_z80_map(address_map &map) -{ - map(0x0000, 0x1fff).bankrw("bank1").mirror(0x2000); // RAM can be accessed by the 68k - map(0x4000, 0x4003).rw(m_ymsnd, FUNC(ym2612_device::read), FUNC(ym2612_device::write)); - - map(0x6000, 0x6000).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); - map(0x6001, 0x6001).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); // wacky races uses this address - - map(0x6100, 0x7eff).r(FUNC(md_base_state::megadriv_z80_unmapped_read)); - - map(0x7f00, 0x7fff).rw(FUNC(md_base_state::megadriv_z80_vdp_read), FUNC(md_base_state::megadriv_z80_vdp_write)); - - map(0x8000, 0xffff).rw(FUNC(md_base_state::z80_read_68k_banked_data), FUNC(md_base_state::z80_write_68k_banked_data)); // The Z80 can read the 68k address space this way -} - -void md_base_state::megadriv_z80_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x0000, 0xff).noprw(); -} - -uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* Copy our screen buffer here */ - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - uint32_t *const desty = &bitmap.pix(y, 0); - uint32_t const *srcy; - - if (!m_vdp->m_use_alt_timing) - srcy = &m_vdp->m_render_bitmap->pix(y, 0); - else - srcy = m_vdp->m_render_line.get(); - - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - desty[x] = srcy[x]; - } - } - - return 0; -} - - - -/*****************************************************************************************/ - -void md_base_state::video_start() -{ - // nothing? -} - -void md_base_state::machine_start() -{ - m_io_pad_3b[0] = ioport("PAD1"); - m_io_pad_3b[1] = ioport("PAD2"); - m_io_pad_3b[2] = ioport("IN0"); - m_io_pad_3b[3] = ioport("UNK"); - - save_item(NAME(m_io_stage)); - save_item(NAME(m_megadrive_io_data_regs)); - save_item(NAME(m_megadrive_io_ctrl_regs)); - save_item(NAME(m_megadrive_io_tx_regs)); -} - -void md_base_state::machine_reset() -{ - /* default state of z80 = reset, with bus */ - osd_printf_debug("Resetting Megadrive / Genesis\n"); - - if (m_z80snd) - { - m_genz80.z80_is_reset = 1; - m_genz80.z80_has_bus = 1; - m_genz80.z80_bank_addr = 0; - m_vdp->set_scanline_counter(-1); - machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(md_base_state::megadriv_z80_run_state),this)); - } - - megadrive_reset_io(); - - if (!m_vdp->m_use_alt_timing) - { - m_vdp->m_megadriv_scanline_timer = m_scan_timer; - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - } - - if (m_megadrive_ram) - memset(m_megadrive_ram, 0x00, 0x10000); - - m_vdp->device_reset_old(); -} - -void md_base_state::megadriv_stop_scanline_timer() -{ - if (!m_vdp->m_use_alt_timing) - m_vdp->m_megadriv_scanline_timer->reset(); -} - - - -// this comes from the VDP on lines 240 (on) 241 (off) and is connected to the z80 irq 0 -WRITE_LINE_MEMBER(md_base_state::vdp_sndirqline_callback_genesis_z80) -{ - if (m_z80snd) - { - if (state == ASSERT_LINE) - { - if ((m_genz80.z80_has_bus == 1) && (m_genz80.z80_is_reset == 0)) - m_z80snd->set_input_line(0, HOLD_LINE); - } - else if (state == CLEAR_LINE) - { - m_z80snd->set_input_line(0, CLEAR_LINE); - } - } -} - -// this comes from the vdp, and is connected to 68k irq level 6 (main vbl interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv6irqline_callback_genesis_68k) -{ - if (state == ASSERT_LINE) - m_maincpu->set_input_line(6, HOLD_LINE); - else - m_maincpu->set_input_line(6, CLEAR_LINE); -} - -// this comes from the vdp, and is connected to 68k irq level 4 (raster interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv4irqline_callback_genesis_68k) -{ - if (state == ASSERT_LINE) - m_maincpu->set_input_line(4, HOLD_LINE); - else - m_maincpu->set_input_line(4, CLEAR_LINE); -} - -/* Callback when the 68k takes an IRQ */ -IRQ_CALLBACK_MEMBER(md_base_state::genesis_int_callback) -{ - if (irqline==4) - { - m_vdp->vdp_clear_irq4_pending(); - } - - if (irqline==6) - { - m_vdp->vdp_clear_irq6_pending(); - } - - return (0x60+irqline*4)/4; // vector address -} - -void md_base_state::megadriv_timers(machine_config &config) -{ - TIMER(config, m_scan_timer).configure_generic("gen_vdp", FUNC(sega315_5313_device::megadriv_scanline_timer_callback)); -} - - -void md_base_state::md_ntsc(machine_config &config) -{ - M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); /* 7.67 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); - - /* IRQs are handled via the timers */ - - Z80(config, m_z80snd, MASTER_CLOCK_NTSC / 15); /* 3.58 MHz */ - m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); - m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); - /* IRQ handled via the timers */ - - megadriv_timers(config); - - SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu); - m_vdp->set_is_pal(false); - m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -void md_base_state::md2_ntsc(machine_config &config) -{ - md_ntsc(config); - - // Internalized YM3438 in VDP ASIC - YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -void md_cons_state::dcat16_megadriv_base(machine_config &config) -{ - md_ntsc(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::dcat16_megadriv_map); -} - -/************ PAL hardware has a different master clock *************/ - -void md_base_state::md_pal(machine_config &config) -{ - M68000(config, m_maincpu, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); - /* IRQs are handled via the timers */ - - Z80(config, m_z80snd, MASTER_CLOCK_PAL / 15); /* 3.58 MHz */ - m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); - m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); - /* IRQ handled via the timers */ - - megadriv_timers(config); - - SEGA315_5313(config, m_vdp, MASTER_CLOCK_PAL, m_maincpu); - m_vdp->set_is_pal(true); - m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - YM2612(config, m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -void md_base_state::md2_pal(machine_config &config) -{ - md_pal(config); - - // Internalized YM3438 in VDP ASIC - YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - - -void md_base_state::megadriv_tas_callback(offs_t offset, uint8_t data) -{ - // writeback not allowed -} - -void md_base_state::megadriv_init_common() -{ - /* Look to see if this system has the standard Sound Z80 */ - if (m_z80snd) - { - m_genz80.z80_prgram = std::make_unique<uint8_t[]>(0x2000); - membank("bank1")->set_base(m_genz80.z80_prgram.get()); - save_item(NAME(m_genz80.z80_is_reset)); - save_item(NAME(m_genz80.z80_has_bus)); - save_item(NAME(m_genz80.z80_bank_addr)); - save_pointer(NAME(m_genz80.z80_prgram), 0x2000); - } - - m_maincpu->set_tas_write_callback(*this, FUNC(md_base_state::megadriv_tas_callback)); - - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); -} - -void md_base_state::init_megadriv_c2() -{ - megadriv_init_common(); - - m_vdp->set_use_cram(0); // C2 uses its own palette ram - m_vdp->set_vdp_pal(false); - m_vdp->set_framerate(60); - m_vdp->set_total_scanlines(262); - - m_version_hi_nibble = 0x20; // JPN NTSC no-SCD -} - - - -void md_base_state::init_megadriv() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(false); - m_vdp->set_framerate(60); - m_vdp->set_total_scanlines(262); - - m_version_hi_nibble = 0xa0; // Export NTSC no-SCD -} - -void md_base_state::init_megadrij() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(false); - m_vdp->set_framerate(60); - m_vdp->set_total_scanlines(262); - - m_version_hi_nibble = 0x20; // JPN NTSC no-SCD -} - -void md_base_state::init_megadrie() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(true); - m_vdp->set_framerate(50); - m_vdp->set_total_scanlines(313); - - m_version_hi_nibble = 0xe0; // Export PAL no-SCD -} - -WRITE_LINE_MEMBER(md_base_state::screen_vblank_megadriv) -{ - if (m_io_reset.read_safe(0) & 0x01) - m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); - - // rising edge - if (state) - { - if (!m_vdp->m_use_alt_timing) - { - m_vdp->vdp_handle_eof(); - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - } - } -} |