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