summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes_ctrl/fcmat.cpp
blob: 35669e37cab203de6f27d40abd1433f50b09ef94 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// license:BSD-3-Clause
// copyright-holders:kmg, Fabio Priuli
/**********************************************************************

    Here we emulate two distinct mat controllers which share a common
    read/write interface with the hardware:

    Nintendo Family Computer - Bandai Family Trainer Mat
    Nintendo Family Computer - IGS Tap-tap Mat

**********************************************************************/

#include "emu.h"
#include "fcmat.h"

//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(NES_FTRAINER,  nes_ftrainer_device,  "nes_famtrain",  "Bandai Family Trainer")
DEFINE_DEVICE_TYPE(NES_TAPTAPMAT, nes_taptapmat_device, "nes_taptapmat", "IGS Tap-tap Mat")


static INPUT_PORTS_START( nes_ftrainer )
	PORT_START("LAYOUT")
	PORT_CONFNAME( 0x01, 0x00, "Family Trainer Button Layout")
	PORT_CONFSETTING(    0x00, "Side A" )
	PORT_CONFSETTING(    0x01, "Side B" )

	// difference between the two sides is that we mirror the key mapping to match the real pad layout!
	PORT_START("MAT_COL.0")
	// side A layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )                                                          PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 )  PORT_NAME("Family Trainer Mid1")  PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )                                                          PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	// side B layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_NAME("Family Trainer 12")    PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 )  PORT_NAME("Family Trainer 8")     PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 )  PORT_NAME("Family Trainer 4")     PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)

	PORT_START("MAT_COL.1")
	// side A layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Family Trainer Low1")  PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 )  PORT_NAME("Family Trainer Mid2")  PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 )  PORT_NAME("Family Trainer Top1")  PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	// side B layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Family Trainer 11")    PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 )  PORT_NAME("Family Trainer 7")     PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 )  PORT_NAME("Family Trainer 3")     PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)

	PORT_START("MAT_COL.2")
	// side A layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Family Trainer Low2")  PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 )  PORT_NAME("Family Trainer Mid3")  PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 )  PORT_NAME("Family Trainer Top2")  PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	// side B layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Family Trainer 10")    PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 )  PORT_NAME("Family Trainer 6")     PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 )  PORT_NAME("Family Trainer 2")     PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)

	PORT_START("MAT_COL.3")
	// side A layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )                                                          PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 )  PORT_NAME("Family Trainer Mid4")  PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )                                                          PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
	// side B layout
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON9 )  PORT_NAME("Family Trainer 9")     PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 )  PORT_NAME("Family Trainer 5")     PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 )  PORT_NAME("Family Trainer 1")     PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
INPUT_PORTS_END


static INPUT_PORTS_START( nes_taptapmat )
	PORT_START("MAT_COL.0")
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_NAME("Bottom Left (Frankenstein)")    PORT_CODE(KEYCODE_V)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 )  PORT_NAME("Middle Left (Bang!)")           PORT_CODE(KEYCODE_F)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 )  PORT_NAME("Top Left (Antlion)")            PORT_CODE(KEYCODE_R)

	PORT_START("MAT_COL.1")
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Bottom Mid-Left (Bang!)")       PORT_CODE(KEYCODE_B)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 )  PORT_NAME("Middle Mid-Left (Caveman)")     PORT_CODE(KEYCODE_G)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 )  PORT_NAME("Top Mid-Left (Bang!)")          PORT_CODE(KEYCODE_T)

	PORT_START("MAT_COL.2")
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Bottom Mid-Right (Shark)")      PORT_CODE(KEYCODE_N)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 )  PORT_NAME("Middle Mid-Right (Bang!)")      PORT_CODE(KEYCODE_H)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 )  PORT_NAME("Top Mid-Right (Dinosaur)")      PORT_CODE(KEYCODE_Y)

	PORT_START("MAT_COL.3")
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON9 )  PORT_NAME("Bottom Right (Bang!)")          PORT_CODE(KEYCODE_M)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 )  PORT_NAME("Middle Right (Mole)")           PORT_CODE(KEYCODE_J)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 )  PORT_NAME("Top Right (Bang!)")             PORT_CODE(KEYCODE_U)
INPUT_PORTS_END


//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor nes_ftrainer_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( nes_ftrainer );
}

ioport_constructor nes_taptapmat_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( nes_taptapmat );
}



//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  constructor
//-------------------------------------------------

nes_fcmat_device::nes_fcmat_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock)
	: device_t(mconfig, type, tag, owner, clock)
	, device_nes_control_port_interface(mconfig, *this)
	, m_mat(*this, "MAT_COL.%u", 0)
	, m_row_scan(0)
{
}

nes_ftrainer_device::nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock)
	: nes_fcmat_device(mconfig, NES_FTRAINER, tag, owner, clock)
{
}

nes_taptapmat_device::nes_taptapmat_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock)
	: nes_fcmat_device(mconfig, NES_TAPTAPMAT, tag, owner, clock)
{
}


//-------------------------------------------------
//  device_start
//-------------------------------------------------

void nes_fcmat_device::device_start()
{
	save_item(NAME(m_row_scan));
}


//-------------------------------------------------
//  read
//-------------------------------------------------

u8 nes_fcmat_device::read_exp(offs_t offset)
{
	u8 ret = 0;

	if (offset == 1)    // $4017
	{
		for (int row = 0; row < 3; row++)  // bottom row first (buttons 9,10,11,12 on Family Trainer)
			if (!BIT(m_row_scan, row))
				for (int col = 0; col < 4; col++)  // left column first (Family Trainer side A and Tap-tap Mat)
					ret |= BIT(m_mat[col]->read(), row) << (col + 1);
		ret = ~ret & 0x1e;  // 0: pressed, 1: not pressed
	}

	return ret;
}

//-------------------------------------------------
//  write
//-------------------------------------------------

void nes_fcmat_device::write(u8 data)
{
	// select row to scan
	m_row_scan = data & 0x07;
}