1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 // thanks-to:Berger
4 /******************************************************************************
5
6 SciSys Kasparov Leonardo, Saitek Kasparov Galileo.
7
8 This is SciSys's answer to H+G Mephisto modular chesscomputers, but unlike the
9 Mephistos, these boards are actual chesscomputers and not an accessory.
10
11 They called the expansion capability "OSA", for "Open Systems Architecture".
12 One for a link port to a PC, and one for a module slot. The expansion modules
13 are basically entire chesscomputers, making the whole thing combined a
14 'dual brain' chesscomputer. The embedded chess engine is by Julio Kaplan
15 and Craig Barnes, same as the one in SciSys Turbo S-24K.
16
17 Hardware notes:
18
19 Leonardo (1986):
20 - 6301Y0 MCU @ 12MHz
21 - 32KB ROM(27C256)
22 - 8KB RAM(M5M5165P-15 or compatible)
23 - magnet sensors chessboard with 16 leds
24
25 The 6301Y0 was seen with internal maskrom serial A96 and B40. It appears to be
26 running in mode 1 (expanded mode): the internal ROM is disabled and the MCU can
27 be emulated as if it's a HD6303Y. It's not known what's on the internal ROM,
28 it could even be from another SciSys chesscomputer.
29
30 Galileo (1988):
31 - HD6303YP MCU @ 12MHz
32 - almost same as Leonardo
33
34 Galileo PCB is different, but essentially it's the same hardware as Leonardo.
35 The 1.4 ROM is identical to it too, even though it's a different MCU type.
36 And on the outside, the button panel was redesigned a bit.
37
38 Expansion modules released:
39 - Maestro (65C02, Kaplan/Barnes)
40 - Analyst (65C02, Kaplan/Barnes)
41 - Brute Force (H8, Frans Morsch)
42 - Sparc (SPARClite, Spracklen's)
43
44 TODO:
45 - OSA module support (softwarelist, devices/bus)
46 - OSA PC link (probably uses MCU serial interface)
47 - add nvram
48 - finish internal artwork
49
50 ******************************************************************************/
51
52 #include "emu.h"
53
54 #include "cpu/m6800/m6801.h"
55 #include "machine/sensorboard.h"
56 #include "sound/dac.h"
57 #include "video/pwm.h"
58
59 #include "speaker.h"
60
61 // internal artwork
62 #include "saitek_leonardo.lh" // clickable
63
64
65 namespace {
66
67 class leo_state : public driver_device
68 {
69 public:
leo_state(const machine_config & mconfig,device_type type,const char * tag)70 leo_state(const machine_config &mconfig, device_type type, const char *tag) :
71 driver_device(mconfig, type, tag),
72 m_maincpu(*this, "maincpu"),
73 m_board(*this, "board"),
74 m_display(*this, "display"),
75 m_dac(*this, "dac"),
76 m_inputs(*this, "IN.%u", 0)
77 { }
78
79 void leo(machine_config &config);
80 void leoa(machine_config &config);
81
82 protected:
83 virtual void machine_start() override;
84
85 private:
86 // devices/pointers
87 required_device<hd6303y_cpu_device> m_maincpu;
88 required_device<sensorboard_device> m_board;
89 required_device<pwm_display_device> m_display;
90 optional_device<dac_bit_interface> m_dac;
91 required_ioport_array<9> m_inputs;
92
93 void main_map(address_map &map);
94
95 void update_display();
96 void mux_w(u8 data);
97 void leds_w(u8 data);
98 u8 unk_r();
99 void unk_w(u8 data);
100
101 u8 p2_r();
102 void p2_w(u8 data);
103 u8 p6_r();
104 void p5_w(u8 data);
105 u8 p5_r();
106 void p6_w(u8 data);
107
108 u8 m_inp_mux = 0;
109 u8 m_led_data[2] = { 0, 0 };
110 };
111
machine_start()112 void leo_state::machine_start()
113 {
114 save_item(NAME(m_inp_mux));
115 save_item(NAME(m_led_data));
116 }
117
118
119
120 /******************************************************************************
121 I/O
122 ******************************************************************************/
123
124 // misc
125
update_display()126 void leo_state::update_display()
127 {
128 m_display->matrix_partial(0, 8, 1 << (m_inp_mux & 0xf), m_led_data[0], false);
129 m_display->matrix_partial(8, 2, 1 << BIT(m_inp_mux, 5), (~m_inp_mux << 2 & 0x300) | m_led_data[1], true);
130 }
131
mux_w(u8 data)132 void leo_state::mux_w(u8 data)
133 {
134 // d0-d3: input/chessboard led mux
135 // d5: button led select
136 // d6,d7: button led data
137 m_inp_mux = data;
138 update_display();
139
140 // d4: speaker out
141 m_dac->write(BIT(data, 4));
142 }
143
leds_w(u8 data)144 void leo_state::leds_w(u8 data)
145 {
146 // button led data
147 m_led_data[1] = ~data;
148 update_display();
149 }
150
unk_r()151 u8 leo_state::unk_r()
152 {
153 // ?
154 return 0xff;
155 }
156
unk_w(u8 data)157 void leo_state::unk_w(u8 data)
158 {
159 // ?
160 }
161
162
163 // MCU ports
164
p2_r()165 u8 leo_state::p2_r()
166 {
167 u8 data = 0;
168
169 // d0-d2: multiplexed inputs
170 u8 mux = (m_inp_mux & 8) ? 8 : (m_inp_mux & 7);
171 data = m_inputs[mux]->read();
172
173 // d3: ?
174
175 return ~data;
176 }
177
p2_w(u8 data)178 void leo_state::p2_w(u8 data)
179 {
180 // d5,d6: chessboard led column data
181 m_led_data[0] = (m_led_data[0] & ~3) | (~data >> 5 & 3);
182 update_display();
183
184 // other: ?
185 }
186
p5_r()187 u8 leo_state::p5_r()
188 {
189 // ?
190 return 0xff ^ 0x10;
191 }
192
p5_w(u8 data)193 void leo_state::p5_w(u8 data)
194 {
195 // d6,d7: chessboard led row data
196 m_led_data[0] = (m_led_data[0] & 3) | (~data >> 4 & 0xc);
197 update_display();
198
199 // d0: power-off
200 // other: ?
201 }
202
p6_r()203 u8 leo_state::p6_r()
204 {
205 // read chessboard sensors
206 return ~m_board->read_file(m_inp_mux & 0xf);
207 }
208
p6_w(u8 data)209 void leo_state::p6_w(u8 data)
210 {
211 // module data
212 }
213
214
215
216 /******************************************************************************
217 Address Maps
218 ******************************************************************************/
219
main_map(address_map & map)220 void leo_state::main_map(address_map &map)
221 {
222 map(0x0000, 0x0027).m(m_maincpu, FUNC(hd6303y_cpu_device::hd6301y_io));
223 map(0x0002, 0x0002).rw(FUNC(leo_state::unk_r), FUNC(leo_state::unk_w)); // external
224 map(0x0040, 0x013f).ram(); // internal
225 map(0x4000, 0x5fff).ram();
226 map(0x6000, 0x6000).w(FUNC(leo_state::mux_w));
227 map(0x7000, 0x7000).w(FUNC(leo_state::leds_w));
228 map(0x8000, 0xffff).rom();
229 }
230
231
232
233 /******************************************************************************
234 Input Ports
235 ******************************************************************************/
236
237 static INPUT_PORTS_START( leo )
238 PORT_START("IN.0")
PORT_CODE(KEYCODE_1)239 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) // king
240 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) // rook
241 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) // knight
242
243 PORT_START("IN.1")
244 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) // queen
245 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) // bishop
246 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) // pawn
247
248 PORT_START("IN.2")
249 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN)
250 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) // tab/color
251 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) // +
252
253 PORT_START("IN.3")
254 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM) // freq sel
255 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W) // function?
256 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) // sound
257
258 PORT_START("IN.4")
259 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) // freq sel
260 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) // stop?
261 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y) // library?
262
263 PORT_START("IN.5")
264 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U) // info
265 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I) // play?
266 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_O) // level
267
268 PORT_START("IN.6")
269 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A) // -
270 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) // normal?
271 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D) // analysis?
272
273 PORT_START("IN.7")
274 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN)
275 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G) // new game
276 PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) // setup?
277
278 PORT_START("IN.8")
279 PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN)
280 PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN)
281 PORT_CONFNAME( 0x04, 0x04, "Battery Status" )
282 PORT_CONFSETTING( 0x00, "Low" )
283 PORT_CONFSETTING( 0x04, DEF_STR( Normal ) )
284 INPUT_PORTS_END
285
286
287
288 /******************************************************************************
289 Machine Configs
290 ******************************************************************************/
291
292 void leo_state::leo(machine_config &config)
293 {
294 /* basic machine hardware */
295 HD6303Y(config, m_maincpu, 12_MHz_XTAL);
296 m_maincpu->set_addrmap(AS_PROGRAM, &leo_state::main_map);
297 m_maincpu->in_p2_cb().set(FUNC(leo_state::p2_r));
298 m_maincpu->out_p2_cb().set(FUNC(leo_state::p2_w));
299 m_maincpu->in_p5_cb().set(FUNC(leo_state::p5_r));
300 m_maincpu->out_p5_cb().set(FUNC(leo_state::p5_w));
301 m_maincpu->in_p6_cb().set(FUNC(leo_state::p6_r));
302 m_maincpu->out_p6_cb().set(FUNC(leo_state::p6_w));
303
304 SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
305 m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
306 m_board->set_delay(attotime::from_msec(150));
307
308 /* video hardware */
309 PWM_DISPLAY(config, m_display).set_size(8+2, 8+2);
310 config.set_default_layout(layout_saitek_leonardo);
311
312 /* sound hardware */
313 SPEAKER(config, "speaker").front_center();
314 DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
315 }
316
leoa(machine_config & config)317 void leo_state::leoa(machine_config &config)
318 {
319 leo(config);
320
321 // slower chessboard response?
322 m_board->set_delay(attotime::from_msec(250));
323 }
324
325
326
327 /******************************************************************************
328 ROM Definitions
329 ******************************************************************************/
330
331 ROM_START( leonardo )
332 ROM_REGION( 0x10000, "maincpu", 0 )
333 ROM_LOAD("sw6.1_osa1.4_510.u9", 0x8000, 0x8000, CRC(e39676b2) SHA1(288c5f2608277cb4c3ca71cb2e642a6a62c01dca) ) // D27C256AD-12
334 ROM_END
335
336 ROM_START( leonardoa )
337 ROM_REGION( 0x10000, "maincpu", 0 )
338 ROM_LOAD("sx6_617l_osa1.2.u9", 0x8000, 0x8000, CRC(4620f827) SHA1(4ae566646d032dd5bcca48316dd90a11e06772f1) ) // D27C256AD-12
339 ROM_END
340
341 ROM_START( galileo )
342 ROM_REGION( 0x10000, "maincpu", 0 )
343 ROM_LOAD("sw6.1_osa1.4_510.u9", 0x8000, 0x8000, CRC(e39676b2) SHA1(288c5f2608277cb4c3ca71cb2e642a6a62c01dca) ) // MBM27C256H-10
344 ROM_END
345
346 } // anonymous namespace
347
348
349
350 /******************************************************************************
351 Drivers
352 ******************************************************************************/
353
354 // YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
355 CONS( 1986, leonardo, 0, 0, leo, leo, leo_state, empty_init, "SciSys", "Kasparov Leonardo (set 1)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_NOT_WORKING )
356 CONS( 1986, leonardoa, leonardo, 0, leoa, leo, leo_state, empty_init, "SciSys", "Kasparov Leonardo (set 2)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_NOT_WORKING )
357
358 CONS( 1988, galileo, 0, 0, leo, leo, leo_state, empty_init, "Saitek", "Kasparov Galileo", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_NOT_WORKING )
359