diff options
Diffstat (limited to 'src/mame/machine/pce.c')
-rw-r--r-- | src/mame/machine/pce.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/src/mame/machine/pce.c b/src/mame/machine/pce.c new file mode 100644 index 00000000000..6aeba853933 --- /dev/null +++ b/src/mame/machine/pce.c @@ -0,0 +1,250 @@ +// license:BSD-3-Clause +// copyright-holders:Charles MacDonald, Wilbert Pol, Angelo Salese +/************************************************************ + +PC Engine CD HW notes: + +TODO: +- Dragon Ball Z: ADPCM dies after the first upload; +- Dragon Slayer - The Legend of Heroes: black screen; +- Mirai Shonen Conan: dies at new game selection; +- Snatcher: black screen after Konami logo, tries set up CD-DA + while transferring data? +- Steam Heart's: needs transfer ready irq to get past the + gameplay hang, don't know exactly when it should fire +- Steam Heart's: bad ADPCM irq, dialogue is cutted due of it; + +============================================================= + +CD Interface Register 0x00 - CDC status +x--- ---- busy signal +-x-- ---- request signal +---x ---- cd signal +---- x--- i/o signal + +CD Interface Register 0x03 - BRAM lock / CD status +-x-- ---- acknowledge signal +--x- ---- done signal +---x ---- bram signal +---- x--- ADPCM 2 +---- -x-- ADPCM 1 +---- --x- CDDA left/right speaker select + +CD Interface Register 0x05 - CD-DA Volume low 8-bit port + +CD Interface Register 0x06 - CD-DA Volume high 8-bit port + +CD Interface Register 0x07 - BRAM unlock / CD status +x--- ---- Enables BRAM + +CD Interface Register 0x0c - ADPCM status +x--- ---- ADPCM is reading data +---- x--- ADPCM playback (0) stopped (1) currently playing +---- -x-- pending ADPCM data write +---- ---x ADPCM playback (1) stopped (0) currently playing + +CD Interface Register 0x0d - ADPCM address control +x--- ---- ADPCM reset +-x-- ---- ADPCM play +--x- ---- ADPCM repeat +---x ---- ADPCM set length +---- x--- ADPCM set read address +---- --xx ADPCM set write address +(note: some games reads bit 5 and wants it to be low otherwise they hangs, surely NOT an ADPCM repeat flag read because it doesn't make sense) + +CD Interface Register 0x0e - ADPCM playback rate + +CD Interface Register 0x0f - ADPCM fade in/out register +---- xxxx command setting: +0x00 ADPCM/CD-DA Fade-in +0x01 CD-DA fade-in +0x08 CD-DA fade-out (short) ADPCM fade-in +0x09 CD-DA fade-out (long) +0x0a ADPCM fade-out (long) +0x0c CD-DA fade-out (short) ADPCM fade-in +0x0d CD-DA fade-out (short) +0x0e ADPCM fade-out (short) + +*************************************************************/ + +#include "emu.h" +#include "cpu/h6280/h6280.h" +#include "includes/pce.h" + + +/* joystick related data*/ + +#define JOY_CLOCK 0x01 +#define JOY_RESET 0x02 + + + +DRIVER_INIT_MEMBER(pce_state,mess_pce) +{ + m_io_port_options = PCE_JOY_SIG | CONST_SIG; +} + +DRIVER_INIT_MEMBER(pce_state,tg16) +{ + m_io_port_options = TG_16_JOY_SIG | CONST_SIG; +} + +DRIVER_INIT_MEMBER(pce_state,sgx) +{ + m_io_port_options = PCE_JOY_SIG | CONST_SIG; +} + +MACHINE_START_MEMBER(pce_state,pce) +{ + if (m_cd) + m_cd->late_setup(); + + // saving is only partially supported: it should be fine with cart games + // OTOH CD states are saved but not correctly restored! + save_item(NAME(m_io_port_options)); + save_item(NAME(m_acard)); + save_item(NAME(m_joystick_port_select)); + save_item(NAME(m_joystick_data_select)); + save_item(NAME(m_joy_6b_packet)); +} + +MACHINE_RESET_MEMBER(pce_state,mess_pce) +{ + for (int joy_i = 0; joy_i < 5; joy_i++) + m_joy_6b_packet[joy_i] = 0; + + /* Note: Arcade Card BIOS contents are the same as System 3, only internal HW differs. + We use a category to select between modes (some games can be run in either S-CD or A-CD modes) */ + m_acard = m_a_card->read() & 1; + + if (m_cartslot->get_type() == PCE_CDSYS3J) + { + m_sys3_card = 1; + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x080000, 0x087fff, read8_delegate(FUNC(pce_state::pce_cd_acard_wram_r),this),write8_delegate(FUNC(pce_state::pce_cd_acard_wram_w),this)); + } + + if (m_cartslot->get_type() == PCE_CDSYS3U) + { + m_sys3_card = 3; + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x080000, 0x087fff, read8_delegate(FUNC(pce_state::pce_cd_acard_wram_r),this),write8_delegate(FUNC(pce_state::pce_cd_acard_wram_w),this)); + } +} + +/* todo: how many input ports does the PCE have? */ +WRITE8_MEMBER(pce_state::mess_pce_joystick_w) +{ + int joy_i; + UINT8 joy_type = m_joy_type->read(); + + m_maincpu->io_set_buffer(data); + + /* bump counter on a low-to-high transition of bit 1 */ + if ((!m_joystick_data_select) && (data & JOY_CLOCK)) + { + m_joystick_port_select = (m_joystick_port_select + 1) & 0x07; + } + + /* do we want buttons or direction? */ + m_joystick_data_select = data & JOY_CLOCK; + + /* clear counter if bit 2 is set */ + if (data & JOY_RESET) + { + m_joystick_port_select = 0; + + for (joy_i = 0; joy_i < 5; joy_i++) + { + if (((joy_type >> (joy_i*2)) & 3) == 2) + m_joy_6b_packet[joy_i] ^= 1; + } + } +} + +READ8_MEMBER(pce_state::mess_pce_joystick_r) +{ + UINT8 joy_type = m_joy_type->read(); + UINT8 ret, data; + + if (m_joystick_port_select <= 4) + { + switch ((joy_type >> (m_joystick_port_select*2)) & 3) + { + case 0: //2-buttons pad + data = m_joy[m_joystick_port_select]->read(); + break; + case 2: //6-buttons pad + /* + Two packets: + 1st packet: directions + I, II, Run, Select + 2nd packet: 6 buttons "header" (high 4 bits active low) + III, IV, V, VI + Note that six buttons pad just doesn't work with (almost?) every single 2-button-only games, it's really just an after-thought and it is like this + on real HW. + */ + data = m_joy6b[m_joystick_port_select]->read() >> (m_joy_6b_packet[m_joystick_port_select]*8); + break; + default: + data = 0xff; + break; + } + } + else + data = 0xff; + + + if (m_joystick_data_select) + data >>= 4; + + ret = (data & 0x0f) | m_io_port_options; +#ifdef UNIFIED_PCE + ret &= ~0x40; +#endif + + return (ret); +} + + +WRITE8_MEMBER(pce_state::pce_cd_intf_w) +{ + m_cd->update(); + + if (offset & 0x200 && m_sys3_card && m_acard) // route Arcade Card handling ports + return m_cd->acard_w(space, offset, data); + + m_cd->intf_w(space, offset, data); + + m_cd->update(); +} + +READ8_MEMBER(pce_state::pce_cd_intf_r) +{ + m_cd->update(); + + if (offset & 0x200 && m_sys3_card && m_acard) // route Arcade Card handling ports + return m_cd->acard_r(space, offset); + + if ((offset & 0xc0) == 0xc0 && m_sys3_card) //System 3 Card header handling + { + switch (offset & 0xcf) + { + case 0xc1: return 0xaa; + case 0xc2: return 0x55; + case 0xc3: return 0x00; + case 0xc5: return (m_sys3_card & 2) ? 0x55 : 0xaa; + case 0xc6: return (m_sys3_card & 2) ? 0xaa : 0x55; + case 0xc7: return 0x03; + } + } + + return m_cd->intf_r(space, offset); +} + + +READ8_MEMBER(pce_state::pce_cd_acard_wram_r) +{ + return pce_cd_intf_r(space, 0x200 | (offset & 0x6000) >> 9); +} + +WRITE8_MEMBER(pce_state::pce_cd_acard_wram_w) +{ + pce_cd_intf_w(space, 0x200 | (offset & 0x6000) >> 9, data); +} |