1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /**********************************************************************
4 
5     Nintendo Family Computer Hori Twin (and 4P?) adapters
6 
7     Emulation of the 4Players adapter is quite pointless: if 2P mode
8     (default mode) it behaves like a Hori Twin adapter, in 4P mode
9     it has P1 and P2 inputs overwriting the inputs coming from the
10     main controllers (possibly creating a bit of confusion, since
11     you get 6 sets of inputs with only 4 acknowledged by the running
12     system).
13     For the moment we keep it available for documentation purposes.
14 
15     TODO: find out confirmation whether in 2P mode, inputs from joypads
16     connected to the 4players adapter are really seen as P3 and P4 inputs.
17     it seems the most reasonable setup (so that users with only 2
18     external pads can use the adapter in 4P games), but one never knows...
19 
20 **********************************************************************/
21 
22 #include "emu.h"
23 #include "hori.h"
24 #include "joypad.h"
25 
26 //**************************************************************************
27 //  DEVICE DEFINITIONS
28 //**************************************************************************
29 
30 DEFINE_DEVICE_TYPE(NES_HORITWIN, nes_horitwin_device, "nes_horitwin", "FC Hori Twin Adapter")
31 DEFINE_DEVICE_TYPE(NES_HORI4P,   nes_hori4p_device,   "nes_hori4p",   "FC Hori 4P Adapter")
32 
33 
INPUT_PORTS_START(nes_hori4p)34 static INPUT_PORTS_START( nes_hori4p )
35 	PORT_START("CONFIG")
36 	PORT_CONFNAME( 0x01, 0x00, "4 Players / 2 Players")
37 	PORT_CONFSETTING(  0x00, "2 Players" )
38 	PORT_CONFSETTING(  0x01, "4 Players" )
39 INPUT_PORTS_END
40 
41 
42 //-------------------------------------------------
43 //  input_ports - device-specific input ports
44 //-------------------------------------------------
45 
46 ioport_constructor nes_hori4p_device::device_input_ports() const
47 {
48 	return INPUT_PORTS_NAME( nes_hori4p );
49 }
50 
51 
hori_adapter(device_slot_interface & device)52 static void hori_adapter(device_slot_interface &device)
53 {
54 	device.option_add("joypad", NES_JOYPAD);
55 }
56 
57 
58 //-------------------------------------------------
59 //  device_add_mconfig - add device configuration
60 //-------------------------------------------------
61 
device_add_mconfig(machine_config & config)62 void nes_horitwin_device::device_add_mconfig(machine_config &config)
63 {
64 	NES_CONTROL_PORT(config, m_port1, hori_adapter, "joypad");
65 	NES_CONTROL_PORT(config, m_port2, hori_adapter, "joypad");
66 	if (m_port != nullptr)
67 	{
68 		m_port1->set_screen_tag(m_port->m_screen);
69 		m_port2->set_screen_tag(m_port->m_screen);
70 	}
71 }
72 
device_add_mconfig(machine_config & config)73 void nes_hori4p_device::device_add_mconfig(machine_config &config)
74 {
75 	NES_CONTROL_PORT(config, m_port1, hori_adapter, "joypad");
76 	NES_CONTROL_PORT(config, m_port2, hori_adapter, "joypad");
77 	NES_CONTROL_PORT(config, m_port3, hori_adapter, "joypad");
78 	NES_CONTROL_PORT(config, m_port4, hori_adapter, "joypad");
79 	if (m_port != nullptr)
80 	{
81 		m_port1->set_screen_tag(m_port->m_screen);
82 		m_port2->set_screen_tag(m_port->m_screen);
83 		m_port3->set_screen_tag(m_port->m_screen);
84 		m_port4->set_screen_tag(m_port->m_screen);
85 	}
86 }
87 
88 
89 //**************************************************************************
90 //  LIVE DEVICE
91 //**************************************************************************
92 
93 //-------------------------------------------------
94 //  nes_horitwin_device - constructor
95 //-------------------------------------------------
96 
nes_horitwin_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)97 nes_horitwin_device::nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
98 	device_t(mconfig, NES_HORITWIN, tag, owner, clock),
99 	device_nes_control_port_interface(mconfig, *this),
100 	m_port1(*this, "port1"),
101 	m_port2(*this, "port2")
102 {
103 }
104 
nes_hori4p_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)105 nes_hori4p_device::nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
106 	device_t(mconfig, NES_HORI4P, tag, owner, clock),
107 	device_nes_control_port_interface(mconfig, *this),
108 	m_port1(*this, "port1"),
109 	m_port2(*this, "port2"),
110 	m_port3(*this, "port3"),
111 	m_port4(*this, "port4"),
112 	m_cfg(*this, "CONFIG")
113 {
114 }
115 
116 
117 //-------------------------------------------------
118 //  read
119 //-------------------------------------------------
120 
read_exp(offs_t offset)121 uint8_t nes_horitwin_device::read_exp(offs_t offset)
122 {
123 	uint8_t ret = 0;
124 	if (offset == 0)    //$4016
125 		ret |= (m_port1->read_bit0() << 1);
126 	else    //$4017
127 		ret |= (m_port2->read_bit0() << 1);
128 	return ret;
129 }
130 
read_exp(offs_t offset)131 uint8_t nes_hori4p_device::read_exp(offs_t offset)
132 {
133 	uint8_t ret = 0;
134 	if (m_cfg->read() == 0) // 2P
135 	{
136 		if (offset == 0)    //$4016
137 			ret |= (m_port1->read_bit0() << 1);
138 		else    //$4017
139 			ret |= (m_port2->read_bit0() << 1);
140 	}
141 	else    // 4P
142 	{
143 		if (offset == 0)    //$4016
144 		{
145 			ret |= (m_port1->read_bit0() << 0);
146 			ret |= (m_port3->read_bit0() << 1);
147 		}
148 		else    //$4017
149 		{
150 			ret |= (m_port2->read_bit0() << 0);
151 			ret |= (m_port4->read_bit0() << 1);
152 		}
153 	}
154 	return ret;
155 }
156 
157 //-------------------------------------------------
158 //  write
159 //-------------------------------------------------
160 
write(uint8_t data)161 void nes_horitwin_device::write(uint8_t data)
162 {
163 	m_port1->write(data);
164 	m_port2->write(data);
165 }
166 
write(uint8_t data)167 void nes_hori4p_device::write(uint8_t data)
168 {
169 	m_port1->write(data);
170 	m_port2->write(data);
171 	m_port3->write(data);
172 	m_port4->write(data);
173 }
174