1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /**********************************************************************
4
5 Mattel Intellivision Hand Controllers
6
7 **********************************************************************/
8
9 #include "emu.h"
10 #include "handctrl.h"
11
12 //**************************************************************************
13 // DEVICE DEFINITIONS
14 //**************************************************************************
15
16 DEFINE_DEVICE_TYPE(INTV_HANDCTRL, intv_handctrl_device, "intv_handctrl", "Mattel Intellivision Hand Controller")
17
18
INPUT_PORTS_START(intv_handctrl)19 static INPUT_PORTS_START( intv_handctrl )
20 PORT_START("KEYPAD")
21 PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("1") PORT_CODE(KEYCODE_1_PAD)
22 PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("2") PORT_CODE(KEYCODE_2_PAD)
23 PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("3") PORT_CODE(KEYCODE_3_PAD)
24 PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("4") PORT_CODE(KEYCODE_4_PAD)
25 PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("5") PORT_CODE(KEYCODE_5_PAD)
26 PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("6") PORT_CODE(KEYCODE_6_PAD)
27 PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("7") PORT_CODE(KEYCODE_7_PAD)
28 PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("8") PORT_CODE(KEYCODE_8_PAD)
29 PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("9") PORT_CODE(KEYCODE_9_PAD)
30 PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Clear") PORT_CODE(KEYCODE_DEL_PAD)
31 PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("0") PORT_CODE(KEYCODE_0_PAD)
32 PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER_PAD)
33 PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Upper") PORT_PLAYER(1)
34 PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Lower-Left") PORT_PLAYER(1)
35 PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Lower-Right") PORT_PLAYER(1)
36 PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
37
38 PORT_START("DISC_DG")
39 PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Up") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
40 PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
41 PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
42 PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
43 PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
44 PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
45 PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
46 PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
47 PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Down") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
48 PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
49 PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
50 PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
51 PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
52 PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
53 PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
54 PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
55
56 PORT_START("DISC_AN_X")
57 PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
58
59 PORT_START("DISC_AN_Y")
60 PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
61
62
63 PORT_START("OPTIONS")
64 PORT_CONFNAME( 0x01, 0x01, "Controller Disc Emulation" )
65 PORT_CONFSETTING( 0x00, "Digital" )
66 PORT_CONFSETTING( 0x01, "Analog" )
67 INPUT_PORTS_END
68
69
70 //-------------------------------------------------
71 // input_ports - device-specific input ports
72 //-------------------------------------------------
73
74 ioport_constructor intv_handctrl_device::device_input_ports() const
75 {
76 return INPUT_PORTS_NAME( intv_handctrl );
77 }
78
79
80
81 //**************************************************************************
82 // LIVE DEVICE
83 //**************************************************************************
84
85 //-------------------------------------------------
86 // intv_handctrl_device - constructor
87 //-------------------------------------------------
88
intv_handctrl_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)89 intv_handctrl_device::intv_handctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
90 device_t(mconfig, INTV_HANDCTRL, tag, owner, clock),
91 device_intv_control_port_interface(mconfig, *this),
92 m_cfg(*this, "OPTIONS"),
93 m_keypad(*this, "KEYPAD"),
94 m_disc_dig(*this, "DISC_DG"),
95 m_disc_anx(*this, "DISC_AN_X"),
96 m_disc_any(*this, "DISC_AN_Y")
97 {
98 }
99
100
101 //-------------------------------------------------
102 // device_start - device-specific startup
103 //-------------------------------------------------
104
device_start()105 void intv_handctrl_device::device_start()
106 {
107 }
108
109
110 //-------------------------------------------------
111 // device_reset - device-specific reset
112 //-------------------------------------------------
113
device_reset()114 void intv_handctrl_device::device_reset()
115 {
116 }
117
118
119 //-------------------------------------------------
120 // read_ctrl
121 //-------------------------------------------------
122
read_ctrl()123 uint8_t intv_handctrl_device::read_ctrl()
124 {
125 static const uint8_t keypad_table[] =
126 {
127 0xff, 0x3f, 0x9f, 0x5f, 0xd7, 0xb7, 0x77, 0xdb,
128 0xbb, 0x7b, 0xdd, 0xbd, 0x7d, 0xde, 0xbe, 0x7e
129 };
130
131 static const uint8_t disc_table[] =
132 {
133 0xf3, 0xe3, 0xe7, 0xf7, 0xf6, 0xe6, 0xee, 0xfe,
134 0xfc, 0xec, 0xed, 0xfd, 0xf9, 0xe9, 0xeb, 0xfb
135 };
136
137 static const uint8_t discyx_table[5][5] =
138 {
139 { 0xe3, 0xf3, 0xfb, 0xeb, 0xe9 },
140 { 0xe7, 0xe3, 0xfb, 0xe9, 0xf9 },
141 { 0xf7, 0xf7, 0xff, 0xfd, 0xfd },
142 { 0xf6, 0xe6, 0xfe, 0xec, 0xed },
143 { 0xe6, 0xee, 0xfe, 0xfc, 0xec }
144 };
145
146 int x, y;
147 uint8_t res = 0xff;
148
149 /* keypad */
150 x = m_keypad->read();
151 for (int i = 0; i < 16; i++)
152 {
153 if (BIT(x, i))
154 res &= keypad_table[i];
155 }
156
157 switch (m_cfg->read() & 1)
158 {
159 /* disc == digital */
160 case 0:
161 default:
162 x = m_disc_dig->read();
163 for (int i = 0; i < 16; i++)
164 {
165 if (BIT(x, i))
166 res &= disc_table[i];
167 }
168 break;
169
170 /* disc == _fake_ analog */
171 case 1:
172 x = m_disc_anx->read();
173 y = m_disc_any->read();
174 res &= discyx_table[y / 32][x / 32];
175 break;
176 }
177
178 return res;
179 }
180