1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 // thanks-to:Sean Riddle
4 /******************************************************************************
5 
6 Fidelity Mini Sensory Chess Challenger (model MSC, 1981 version)
7 
8 Two versions exist, both of them are model MSC. The 1981 version has a Z8 MCU,
9 the 1982 version has an I8049. They can also be distinguished from the button
10 panel design, the 2nd version has rectangular buttons. See fidel_sc6.cpp for
11 the 2nd version.
12 
13 Hardware notes:
14 - Zilog Z8 MCU(custom label, probably Z8601), 8MHz XTAL
15 - buzzer, 18 leds, 8*8 chessboard buttons, module slot
16 
17 released modules, * denotes not dumped yet:
18 - CAC: Challenger Advanced Chess
19 - CBO: Challenger Book Openings
20 - *CGG: Challenger Greatest Games
21 
22 As noted in the hash file: The modules have 2 programs in them, one for Z8
23 and one for MCS48. A12 is forced high or low to select the bank.
24 
25 ******************************************************************************/
26 
27 #include "emu.h"
28 
29 #include "cpu/z8/z8.h"
30 #include "machine/sensorboard.h"
31 #include "sound/dac.h"
32 #include "video/pwm.h"
33 #include "bus/generic/slot.h"
34 #include "bus/generic/carts.h"
35 
36 #include "softlist.h"
37 #include "speaker.h"
38 
39 // internal artwork
40 #include "fidel_msc_v1.lh" // clickable
41 
42 
43 namespace {
44 
45 class msc_state : public driver_device
46 {
47 public:
msc_state(const machine_config & mconfig,device_type type,const char * tag)48 	msc_state(const machine_config &mconfig, device_type type, const char *tag) :
49 		driver_device(mconfig, type, tag),
50 		m_maincpu(*this, "maincpu"),
51 		m_board(*this, "board"),
52 		m_display(*this, "display"),
53 		m_dac(*this, "dac"),
54 		m_inputs(*this, "IN.0")
55 	{ }
56 
57 	// machine configs
58 	void msc(machine_config &config);
59 
60 protected:
61 	virtual void machine_start() override;
62 
63 private:
64 	// devices/pointers
65 	required_device<z8_device> m_maincpu;
66 	required_device<sensorboard_device> m_board;
67 	required_device<pwm_display_device> m_display;
68 	required_device<dac_bit_interface> m_dac;
69 	required_ioport m_inputs;
70 
71 	// address maps
72 	void main_map(address_map &map);
73 
74 	// I/O handlers
75 	void update_display();
76 	void mux_w(u8 data);
77 	void control_w(u8 data);
78 	u8 rom_r(offs_t offset);
79 
80 	u8 read_inputs();
81 	u8 input_hi_r();
82 	u8 input_lo_r();
83 
84 	u8 m_led_select = 0;
85 	u16 m_inp_mux = 0;
86 };
87 
machine_start()88 void msc_state::machine_start()
89 {
90 	// register for savestates
91 	save_item(NAME(m_led_select));
92 	save_item(NAME(m_inp_mux));
93 }
94 
95 
96 
97 /******************************************************************************
98     I/O
99 ******************************************************************************/
100 
101 // MCU ports/generic
102 
update_display()103 void msc_state::update_display()
104 {
105 	m_display->matrix(m_led_select, m_inp_mux);
106 }
107 
mux_w(u8 data)108 void msc_state::mux_w(u8 data)
109 {
110 	// P20-P27: input mux, led data
111 	m_inp_mux = (m_inp_mux & 0x100) | data;
112 	update_display();
113 }
114 
control_w(u8 data)115 void msc_state::control_w(u8 data)
116 {
117 	// P37: input mux highest bit
118 	// P35,P36: led select
119 	m_inp_mux = (m_inp_mux & 0xff) | (data << 1 & 0x100);
120 	m_led_select = ~data >> 5 & 3;
121 	update_display();
122 
123 	// P34: speaker out
124 	m_dac->write(BIT(~data, 4));
125 }
126 
read_inputs()127 u8 msc_state::read_inputs()
128 {
129 	u8 data = 0;
130 
131 	// read chessboard sensors
132 	for (int i = 0; i < 8; i++)
133 		if (BIT(m_inp_mux, i))
134 			data |= m_board->read_file(i);
135 
136 	// read button panel
137 	if (m_inp_mux & 0x100)
138 		data |= m_inputs->read();
139 
140 	return bitswap<8>(~data,0,1,2,3,4,5,6,7);
141 }
142 
input_hi_r()143 u8 msc_state::input_hi_r()
144 {
145 	// P04-P07: multiplexed inputs high
146 	return read_inputs() | 0x0f;
147 }
148 
input_lo_r()149 u8 msc_state::input_lo_r()
150 {
151 	// P30-P33: multiplexed inputs low
152 	return read_inputs() | 0xf0;
153 }
154 
155 
156 
157 /******************************************************************************
158     Address Maps
159 ******************************************************************************/
160 
main_map(address_map & map)161 void msc_state::main_map(address_map &map)
162 {
163 	map(0x0000, 0x0fff).mirror(0xf000).r("cartslot", FUNC(generic_slot_device::read_rom));
164 }
165 
166 
167 
168 /******************************************************************************
169     Input Ports
170 ******************************************************************************/
171 
172 static INPUT_PORTS_START( msc )
173 	PORT_START("IN.0")
PORT_CODE(KEYCODE_1)174 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("RV / Pawn")
175 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("DM / Knight")
176 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Speaker / Bishop")
177 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("LV / Rook")
178 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("PV / Queen")
179 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("PB / King")
180 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("CL")
181 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("RE")
182 INPUT_PORTS_END
183 
184 
185 
186 /******************************************************************************
187     Machine Configs
188 ******************************************************************************/
189 
190 void msc_state::msc(machine_config &config)
191 {
192 	/* basic machine hardware */
193 	Z8601(config, m_maincpu, 8_MHz_XTAL);
194 	m_maincpu->set_addrmap(AS_PROGRAM, &msc_state::main_map);
195 	m_maincpu->p0_in_cb().set(FUNC(msc_state::input_hi_r));
196 	m_maincpu->p2_out_cb().set(FUNC(msc_state::mux_w));
197 	m_maincpu->p3_in_cb().set(FUNC(msc_state::input_lo_r));
198 	m_maincpu->p3_out_cb().set(FUNC(msc_state::control_w));
199 
200 	SENSORBOARD(config, m_board).set_type(sensorboard_device::BUTTONS);
201 	m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
202 	m_board->set_delay(attotime::from_msec(150));
203 
204 	/* video hardware */
205 	PWM_DISPLAY(config, m_display).set_size(2, 9);
206 	config.set_default_layout(layout_fidel_msc_v1);
207 
208 	/* sound hardware */
209 	SPEAKER(config, "speaker").front_center();
210 	DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
211 
212 	/* cartridge */
213 	GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "fidel_msc");
214 	SOFTWARE_LIST(config, "cart_list").set_original("fidel_msc");
215 }
216 
217 
218 
219 /******************************************************************************
220     ROM Definitions
221 ******************************************************************************/
222 
223 ROM_START( miniscco )
224 	ROM_REGION( 0x0800, "maincpu", 0 )
225 	ROM_LOAD("sr0016_1001011a01", 0x0000, 0x0800, CRC(c8cd9bf1) SHA1(4ba165555b8419b03b2ef355da0ed9675315e18b) ) // internal ROM
226 ROM_END
227 
228 } // anonymous namespace
229 
230 
231 
232 /******************************************************************************
233     Drivers
234 ******************************************************************************/
235 
236 //    YEAR  NAME      PARENT  CMP MACHINE  INPUT  CLASS      INIT        COMPANY, FULLNAME, FLAGS
237 CONS( 1981, miniscco, miniscc, 0, msc,     msc,   msc_state, empty_init, "Fidelity Electronics", "Mini Sensory Chess Challenger (1981 version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
238