trunk/src/mess/machine/pc9801_118.c
| r0 | r19639 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | NEC PC-9801-118 sound card |
| 4 | |
| 5 | YMF288 + some extra ports |
| 6 | |
| 7 | TODO: |
| 8 | - preliminary, presumably needs CS-4231 too |
| 9 | |
| 10 | ***************************************************************************/ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | #include "machine/pc9801_118.h" |
| 14 | #include "machine/pic8259.h" |
| 15 | #include "sound/2608intf.h" |
| 16 | |
| 17 | #define MAIN_CLOCK_X1 XTAL_1_9968MHz |
| 18 | |
| 19 | //************************************************************************** |
| 20 | // GLOBAL VARIABLES |
| 21 | //************************************************************************** |
| 22 | |
| 23 | // device type definition |
| 24 | const device_type PC9801_118 = &device_creator<pc9801_118_device>; |
| 25 | |
| 26 | |
| 27 | READ8_MEMBER(pc9801_118_device::opn_porta_r) |
| 28 | { |
| 29 | if(m_joy_sel == 0x80) |
| 30 | return ioport("OPNA_PA1")->read(); |
| 31 | |
| 32 | if(m_joy_sel == 0xc0) |
| 33 | return ioport("OPNA_PA2")->read(); |
| 34 | |
| 35 | // 0x81? |
| 36 | // printf("%02x\n",m_joy_sel); |
| 37 | return 0xff; |
| 38 | } |
| 39 | |
| 40 | WRITE8_MEMBER(pc9801_118_device::opn_portb_w){ m_joy_sel = data; } |
| 41 | |
| 42 | static void pc9801_sound_irq( device_t *device, int irq ) |
| 43 | { |
| 44 | // pc9801_state *state = device->machine().driver_data<pc9801_state>(); |
| 45 | |
| 46 | /* TODO: seems to die very often */ |
| 47 | pic8259_ir4_w(device->machine().device("pic8259_slave"), irq); |
| 48 | } |
| 49 | |
| 50 | static const ym2608_interface pc98_ym2608_intf = |
| 51 | { |
| 52 | { |
| 53 | AY8910_LEGACY_OUTPUT, |
| 54 | AY8910_DEFAULT_LOADS, |
| 55 | DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, pc9801_118_device,opn_porta_r), |
| 56 | DEVCB_NULL,//(pc9801_state,opn_portb_r), |
| 57 | DEVCB_NULL,//(pc9801_state,opn_porta_w), |
| 58 | DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, pc9801_118_device,opn_portb_w), |
| 59 | }, |
| 60 | pc9801_sound_irq |
| 61 | }; |
| 62 | |
| 63 | static MACHINE_CONFIG_FRAGMENT( pc9801_118_config ) |
| 64 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 65 | MCFG_SOUND_ADD("opn3", YM2608, MAIN_CLOCK_X1*4) // actually YMF288, unknown clock / divider |
| 66 | MCFG_SOUND_CONFIG(pc98_ym2608_intf) |
| 67 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) |
| 68 | MACHINE_CONFIG_END |
| 69 | |
| 70 | //------------------------------------------------- |
| 71 | // machine_config_additions - device-specific |
| 72 | // machine configurations |
| 73 | //------------------------------------------------- |
| 74 | |
| 75 | machine_config_constructor pc9801_118_device::device_mconfig_additions() const |
| 76 | { |
| 77 | return MACHINE_CONFIG_NAME( pc9801_118_config ); |
| 78 | } |
| 79 | |
| 80 | |
| 81 | //------------------------------------------------- |
| 82 | // input_ports - device-specific input ports |
| 83 | //------------------------------------------------- |
| 84 | |
| 85 | static INPUT_PORTS_START( pc9801_118 ) |
| 86 | PORT_START("OPNA_PA1") |
| 87 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Up") |
| 88 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Down") |
| 89 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Left") |
| 90 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Right") |
| 91 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 1") |
| 92 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 2") |
| 93 | PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 94 | |
| 95 | PORT_START("OPNA_PA2") |
| 96 | PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Up") |
| 97 | PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Down") |
| 98 | PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Left") |
| 99 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Right") |
| 100 | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 Joystick Button 1") |
| 101 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 Joystick Button 2") |
| 102 | PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 103 | INPUT_PORTS_END |
| 104 | |
| 105 | ioport_constructor pc9801_118_device::device_input_ports() const |
| 106 | { |
| 107 | return INPUT_PORTS_NAME( pc9801_118 ); |
| 108 | } |
| 109 | |
| 110 | //************************************************************************** |
| 111 | // LIVE DEVICE |
| 112 | //************************************************************************** |
| 113 | |
| 114 | //------------------------------------------------- |
| 115 | // pc9801_118_device - constructor |
| 116 | //------------------------------------------------- |
| 117 | |
| 118 | pc9801_118_device::pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 119 | : device_t(mconfig, PC9801_118, "pc9801_118", tag, owner, clock), |
| 120 | // m_maincpu(*owner, "maincpu"), |
| 121 | m_opn3(*this, "opn3") |
| 122 | { |
| 123 | |
| 124 | } |
| 125 | |
| 126 | |
| 127 | //------------------------------------------------- |
| 128 | // device_validity_check - perform validity checks |
| 129 | // on this device |
| 130 | //------------------------------------------------- |
| 131 | |
| 132 | void pc9801_118_device::device_validity_check(validity_checker &valid) const |
| 133 | { |
| 134 | } |
| 135 | |
| 136 | //------------------------------------------------- |
| 137 | // device_start - device-specific startup |
| 138 | //------------------------------------------------- |
| 139 | |
| 140 | void pc9801_118_device::install_device(offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_delegate rhandler, write8_delegate whandler) |
| 141 | { |
| 142 | int buswidth = machine().firstcpu->space_config(AS_IO)->m_databus_width; |
| 143 | switch(buswidth) |
| 144 | { |
| 145 | case 8: |
| 146 | machine().firstcpu->space(AS_IO).install_readwrite_handler(start, end, mask, mirror, rhandler, whandler, 0); |
| 147 | break; |
| 148 | case 16: |
| 149 | machine().firstcpu->space(AS_IO).install_readwrite_handler(start, end, mask, mirror, rhandler, whandler, 0xffff); |
| 150 | break; |
| 151 | case 32: |
| 152 | machine().firstcpu->space(AS_IO).install_readwrite_handler(start, end, mask, mirror, rhandler, whandler, 0xffffffff); |
| 153 | break; |
| 154 | default: |
| 155 | fatalerror("PC-9801-118: Bus width %d not supported\n", buswidth); |
| 156 | break; |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | |
| 161 | void pc9801_118_device::device_start() |
| 162 | { |
| 163 | install_device(0x0188, 0x018f, 0, 0, read8_delegate(FUNC(pc9801_118_device::pc9801_118_r), this), write8_delegate(FUNC(pc9801_118_device::pc9801_118_w), this) ); |
| 164 | install_device(0xa460, 0xa463, 0, 0, read8_delegate(FUNC(pc9801_118_device::pc9801_118_ext_r), this), write8_delegate(FUNC(pc9801_118_device::pc9801_118_ext_w), this) ); |
| 165 | } |
| 166 | |
| 167 | |
| 168 | //------------------------------------------------- |
| 169 | // device_reset - device-specific reset |
| 170 | //------------------------------------------------- |
| 171 | |
| 172 | void pc9801_118_device::device_reset() |
| 173 | { |
| 174 | m_ext_reg = 1; // TODO: enabled or disabled? |
| 175 | } |
| 176 | |
| 177 | |
| 178 | //************************************************************************** |
| 179 | // READ/WRITE HANDLERS |
| 180 | //************************************************************************** |
| 181 | |
| 182 | |
| 183 | READ8_MEMBER(pc9801_118_device::pc9801_118_r) |
| 184 | { |
| 185 | if(((offset & 5) == 0) || m_ext_reg) |
| 186 | return ym2608_r(m_opn3, space, offset >> 1); |
| 187 | else // odd |
| 188 | { |
| 189 | //printf("PC9801-118: Read to undefined port [%02x]\n",offset+0x188); |
| 190 | return 0xff; |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | |
| 195 | WRITE8_MEMBER(pc9801_118_device::pc9801_118_w) |
| 196 | { |
| 197 | if(((offset & 5) == 0) || m_ext_reg) |
| 198 | ym2608_w(m_opn3,space, offset >> 1,data); |
| 199 | //else // odd |
| 200 | // printf("PC9801-118: Write to undefined port [%02x] %02x\n",offset+0x188,data); |
| 201 | } |
| 202 | |
| 203 | READ8_MEMBER( pc9801_118_device::pc9801_118_ext_r ) |
| 204 | { |
| 205 | if(offset == 0) |
| 206 | { |
| 207 | printf("OPN3 EXT read ID [%02x]\n",offset); |
| 208 | return 0x80 | (m_ext_reg & 1); |
| 209 | } |
| 210 | |
| 211 | printf("OPN3 EXT read unk [%02x]\n",offset); |
| 212 | return 0xff; |
| 213 | } |
| 214 | |
| 215 | WRITE8_MEMBER( pc9801_118_device::pc9801_118_ext_w ) |
| 216 | { |
| 217 | if(offset == 0) |
| 218 | { |
| 219 | m_ext_reg = data & 1; |
| 220 | /* TODO: apparently writing a 1 doubles the available channels (and presumably enables CS-4231 too) */ |
| 221 | if(data) |
| 222 | printf("PC-9801-118: extended register %02x write\n",data); |
| 223 | return; |
| 224 | } |
| 225 | |
| 226 | printf("OPN3 EXT write unk %02x -> [%02x]\n",data,offset); |
| 227 | } |
trunk/src/mess/machine/pc9801_118.h
| r0 | r19639 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | NEC PC-9801-118 |
| 4 | |
| 5 | ***************************************************************************/ |
| 6 | |
| 7 | |
| 8 | #pragma once |
| 9 | |
| 10 | #ifndef __PC9801_118DEV_H__ |
| 11 | #define __PC9801_118DEV_H__ |
| 12 | |
| 13 | #include "machine/pic8259.h" |
| 14 | #include "sound/2608intf.h" |
| 15 | |
| 16 | |
| 17 | //************************************************************************** |
| 18 | // TYPE DEFINITIONS |
| 19 | //************************************************************************** |
| 20 | |
| 21 | // ======================> pc9801_118_device |
| 22 | |
| 23 | class pc9801_118_device : public device_t |
| 24 | { |
| 25 | public: |
| 26 | // construction/destruction |
| 27 | pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 28 | |
| 29 | // optional information overrides |
| 30 | virtual machine_config_constructor device_mconfig_additions() const; |
| 31 | virtual ioport_constructor device_input_ports() const; |
| 32 | |
| 33 | DECLARE_READ8_MEMBER(opn_porta_r); |
| 34 | DECLARE_WRITE8_MEMBER(opn_portb_w); |
| 35 | DECLARE_READ8_MEMBER(pc9801_118_r); |
| 36 | DECLARE_WRITE8_MEMBER(pc9801_118_w); |
| 37 | DECLARE_READ8_MEMBER(pc9801_118_ext_r); |
| 38 | DECLARE_WRITE8_MEMBER(pc9801_118_ext_w); |
| 39 | |
| 40 | // required_device<cpu_device> m_maincpu; |
| 41 | required_device<ym2608_device> m_opn3; |
| 42 | protected: |
| 43 | // device-level overrides |
| 44 | virtual void device_validity_check(validity_checker &valid) const; |
| 45 | virtual void device_start(); |
| 46 | virtual void device_reset(); |
| 47 | virtual void device_config_complete() { m_shortname = "pc9801_118"; } |
| 48 | void install_device(offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_delegate rhandler, write8_delegate whandler); |
| 49 | |
| 50 | private: |
| 51 | UINT8 m_joy_sel; |
| 52 | UINT8 m_ext_reg; |
| 53 | }; |
| 54 | |
| 55 | |
| 56 | // device type definition |
| 57 | extern const device_type PC9801_118; |
| 58 | |
| 59 | |
| 60 | |
| 61 | //************************************************************************** |
| 62 | // GLOBAL VARIABLES |
| 63 | //************************************************************************** |
| 64 | |
| 65 | |
| 66 | |
| 67 | #endif |