1 // license:GPL-2.0+
2 // copyright-holders:Raphael Nabet
3 /*
4     Experimental Tomy Tutor driver
5 
6     This computer is known as Tomy Tutor in US, and as Grandstand Tutor in UK.
7     It was initially released in Japan in 1982 or 1983 under the name of Pyuuta
8     (Pi-yu-u-ta, with a Kanji for the "ta").  The Japanese versions are
9     different from the English-language versions, as they have different ROMs
10     with Japanese messages and support for the katakana syllabus.  There are at
11     least 4 versions:
12     * original Pyuuta (1982 or 1983) with title screens in Japanese but no
13       Basic
14     * Pyuuta Jr. (1983?) which is a console with a simplified keyboard
15     * Tomy/Grandstand Tutor (circa October 1983?) with title screens in English
16       and integrated Basic
17     * Pyuuta Mk. 2 (1984?) with a better-looking keyboard and integrated Basic
18 
19     The Tomy Tutor features a TMS9995 CPU @10.7MHz (which includes a
20     timer/counter and 256 bytes of 16-bit RAM), 48kb of ROM (32kb on early
21     models that did not have the BASIC interpreter), a tms9918a/9929a VDP (or
22     equivalent?) with 16kb of VRAM, and a sn76489an sound generator.
23     There is a tape interface, a 56-key keyboard, an interface for two
24     joysticks, a cartridge port and an extension port.  The OS design does not
25     seem to be particularly expandable (I don't see any hook for additional
26     DSRs), but there were prototypes for a parallel port (emulated)
27     and a speech synthesizer unit (not emulated).
28 
29 
30     The Tutor appears to be related to Texas Instruments' TI99 series.
31 
32     The general architecture is relatively close to the ti99/4(a): arguably,
33     the Tutor does not include any GROM (it uses regular CPU ROMs for GPL
34     code), and its memory map is quite different due to the fact it was
35     designed with a tms9995 in mind (vs. a tms9985 for ti99/4), but, apart from
36     that, it has a similar architecture with only 256 bytes of CPU RAM and 16kb
37     of VRAM.
38 
39     While the OS is not derived directly from the TI99/4(a) OS, there are
40     disturbing similarities: the Japanese title screen is virtually identical
41     to the TI-99 title screen.  Moreover, the Tutor BASIC seems to be be
42     derived from TI Extended BASIC, as both BASIC uses similar tokens and
43     syntax, and are partially written in GPL (there is therefore a GPL
44     interpreter in Tutor ROMs, although the Tutor GPL is incompatible with TI
45     GPL, does not seem to be used by any program other than Tutor Basic, and it
46     seems unlikely that the original Pyuuta had this GPL interpreter in ROMs).
47 
48     It appears that TI has sold the licence of the TI BASIC to Tomy, probably
49     after it terminated its TI99 series.  It is not impossible that the entire
50     Tutor concept is derived from a TI project under licence: this machine
51     looks like a crossbreed of the TI99/2 and the TI99/4 (or /4a, /4b, /5), and
52     it could either have been an early version of the TI99/2 project with a
53     tms9918a/99289a VDP instead of the DMA video controller, or a "TI99/3" that
54     would have closed the gap between the extremely low-end TI99/2 and the
55     relatively mid-range TI99/5.
56 
57 
58     Raphael Nabet, 2003
59 
60 
61 TODO :
62     * debug the tape interface (Saved tapes sound OK, both Verify and Load
63       recognize the tape as a Tomy tape, but the data seems to be corrupted and
64       we end with a read error.)
65     * guess which device is located at the >e600 base
66     * find info about other Tutor variants
67 
68 
69     Interrupts:
70 
71     Interrupt levels 1 (external interrupt 1) and 2 (error interrupt) do not
72     seem to be used: triggering these seems to cause a soft reset.  XOPs are
73     not used at all: the ROM area where these vectors should be defined is used
74     by a ROM branch table.
75 
76 
77 Memory Map found at http://www.floodgap.com/retrobits/tomy/mmap.html
78 
79                    *** $0000-$7FFF is the 32K BIOS ***
80  it is also possible to replace the BIOS with an external ROM (see $E000 range)
81 
82 0000
83                                 reset vector (level 0)
84                                 0000-0001: WP   0002-0003: PC (%)
85 0004
86                                 level 1 and 2 IRQ vectors (%)
87                                 idem. These just seem to reset the system.
88 000C
89                                 additional vectors
90 0040
91                                 XOP vectors (%)
92                 The BIOS doesn't seem to use these for XOPs.
93                 Instead, this is a branch table.
94 0080
95                 BIOS code
96                 (CRU only: $1EE0-FE: 9995 flag register;
97                     $1FDA: MID flag)
98 4000
99                 GBASIC
100                 (on the American v2.3 firmware, the GPL
101                     interpreter and VDP RAMLUT co-exist
102                     with GBASIC in this range)
103 
104               *** $8000-$BFFF is the 16K option ROM area ***
105 
106 8000
107                 BASIC (Tutor only) and/or cartridge ROM
108                     (controlled by $E100)
109                 To be recognized, a cartridge must have a
110                 $55, $66 or $aa header sequence.
111 
112                          *** end ROM ***
113 C000
114                 unmapped (possible use in 24K cartridges)
115 E000
116                 I/O range
117                 ---------
118                 9918A VDP data/register ports: $E000, E002
119                 "MMU" banking controls: $E100-E1FF
120                     $E100 write: enable cartridge, disable
121                         BIOS at $0000 (???) -- magic
122                         required at $E110 for this
123                     $E108 write: enable BASIC ROM, disable
124                         cartridge at $8000
125                     $E10C write: enable cartridge, disable
126                         BASIC ROM at $8000
127                     $E110 must be $42 to enable $E100
128                         and to replace the BIOS with
129                         an installed cartridge ROM.
130                         BLWP assumed at $0000 (??).
131                 SN76489AN sound data port: $E200
132                 Device handshaking: $E600
133                     Unknown purpose, disk drive maybe?
134                 Printer handshaking: $E800
135                 This is a standard Centronics port.
136                     $E810 write: parallel data bus
137                     $E820 read: parallel port busy
138                     $E840 write: port handshake output
139                 Keyboard lines: $EC00-$EC7E (*CRU*)
140                     (CRU physical address $7600-$763F)
141                 Cassette lines: $ED00-$EEFF
142                     $ED00 (*CRU*): input level
143                         (physical address $7680)
144                     $EE00 write: tape output zero
145                     $EE20 write: tape output one
146                     $EE40 write: tape IRQ on
147                     $EE60 write: tape IRQ off
148                     $EE80, A0, C0, E0: ???
149 
150 F000
151                                 TMS9995 RAM (*)
152 F0FC
153                                 ??
154 FFFA
155                                 decrementer (*)
156 FFFC
157                                 NMI vector (*)
158 FFFF
159 
160 
161 
162 PYUUTAJR
163 ********
164 
165 This is a handheld unit with 12 'chiclet' buttons. The keyboard has E800, EA00, EC00, EE00 scanned,
166 although 2 of these rows have no keys. TUTOR carts will run, however since most of them ask for
167 A=AMA, P=PRO, these keys don't exist, and so the games cannot be played.
168 
169 *********************************************************************************************************/
170 
171 #include "emu.h"
172 
173 #include "cpu/tms9900/tms9995.h"
174 #include "imagedev/cassette.h"
175 #include "sound/sn76496.h"
176 #include "video/tms9928a.h"
177 
178 #include "bus/centronics/ctronics.h"
179 #include "bus/generic/carts.h"
180 #include "bus/generic/slot.h"
181 
182 #include "softlist.h"
183 #include "speaker.h"
184 
185 
186 class tutor_state : public driver_device
187 {
188 public:
tutor_state(const machine_config & mconfig,device_type type,const char * tag)189 	tutor_state(const machine_config &mconfig, device_type type, const char *tag)
190 		: driver_device(mconfig, type, tag),
191 		m_maincpu(*this, "maincpu"),
192 		m_cart(*this, "cartslot"),
193 		m_cass(*this, "cassette"),
194 		m_centronics(*this, "centronics"),
195 		m_cent_data_out(*this, "cent_data_out"),
196 		m_bank1(*this, "bank1"),
197 		m_bank2(*this, "bank2"),
198 		m_bank1_switching(0)
199 	{
200 	}
201 
202 	void pyuutajr(machine_config &config);
203 	void tutor(machine_config &config);
204 
205 private:
206 	required_device<tms9995_device> m_maincpu;
207 	required_device<generic_slot_device> m_cart;
208 	optional_device<cassette_image_device> m_cass;
209 	optional_device<centronics_device> m_centronics;
210 	optional_device<output_latch_device> m_cent_data_out;
211 	required_memory_bank m_bank1;
212 	required_memory_bank m_bank2;
213 	memory_region *m_cart_rom;
214 
215 	int m_bank1_switching;
216 	uint8_t key_r(offs_t offset);
217 	uint8_t tutor_mapper_r(offs_t offset);
218 	void tutor_mapper_w(offs_t offset, uint8_t data);
219 	uint8_t tutor_cassette_r();
220 	void tutor_cassette_w(offs_t offset, uint8_t data);
221 	uint8_t tutor_printer_r(offs_t offset);
222 	void tutor_printer_w(offs_t offset, uint8_t data);
223 
224 	uint8_t tutor_highmem_r(offs_t offset);
225 	int m_tape_interrupt_enable;
226 	emu_timer *m_tape_interrupt_timer;
227 	virtual void machine_start() override;
228 	virtual void machine_reset() override;
229 	TIMER_CALLBACK_MEMBER(tape_interrupt_handler);
230 
231 	int m_centronics_busy;
232 	DECLARE_WRITE_LINE_MEMBER(write_centronics_busy);
233 	void pyuutajr_mem(address_map &map);
234 	void tutor_io(address_map &map);
235 	void tutor_memmap(address_map &map);
236 };
237 
238 
machine_start()239 void tutor_state::machine_start()
240 {
241 	std::string region_tag;
242 	m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG));
243 
244 	m_tape_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tutor_state::tape_interrupt_handler),this));
245 
246 	m_bank1->configure_entry(0, memregion("maincpu")->base() + 0x4000);
247 	m_bank1->set_entry(0);
248 	m_bank2->configure_entry(0, memregion("maincpu")->base() + 0x8000);
249 	m_bank2->set_entry(0);
250 
251 	if (m_cart_rom)
252 	{
253 		if (m_cart_rom->bytes() > 0x4000)
254 		{
255 			m_bank1_switching = 1;
256 			m_bank1->configure_entry(1, m_cart_rom->base());
257 			m_bank1->set_entry(1);
258 			m_bank2->configure_entry(1, m_cart_rom->base() + 0x4000);
259 			m_bank2->set_entry(1);
260 		}
261 		else
262 		{
263 			m_bank2->configure_entry(1, m_cart_rom->base());
264 			m_bank2->set_entry(1);
265 		}
266 	}
267 }
268 
machine_reset()269 void tutor_state::machine_reset()
270 {
271 	m_tape_interrupt_enable = 0;
272 	m_centronics_busy = 0;
273 
274 	// Disable auto wait states; with enabled wait states, cassette loading fails
275 	m_maincpu->ready_line(ASSERT_LINE);
276 	m_maincpu->reset_line(ASSERT_LINE);
277 	m_maincpu->hold_line(CLEAR_LINE);
278 }
279 
280 /*
281     Keyboard:
282 
283     Keyboard ports are located at CRU logical address >ec00->ec7e (CRU physical
284     address >7600->763f).  There is one bit per key (bit >00 for keycode >00,
285     bit >01 for keycode >01, etc.), each bit is set to one when the key is
286     down.
287 
288     Joystick:
289 
290     Joystick ports seem to overlap keyboard ports, i.e. some CRU bits are
291     mapped to both a keyboard key and a joystick switch.
292 */
293 
key_r(offs_t offset)294 uint8_t tutor_state::key_r(offs_t offset)
295 {
296 	char port[12];
297 	uint8_t value;
298 
299 	snprintf(port, ARRAY_LENGTH(port), "LINE%d", (offset & 0x007e) >> 3);
300 	value = ioport(port)->read();
301 
302 	/* hack for ports overlapping with joystick */
303 	if (offset >= 32 && offset < 48)
304 	{
305 		snprintf(port, ARRAY_LENGTH(port), "LINE%d_alt", (offset & 0x007e) >> 3);
306 		value |= ioport(port)->read();
307 	}
308 
309 	return BIT(value, offset & 7);
310 }
311 
312 
313 /*
314     Cartridge mapping:
315 
316     Cartridges share the >8000 address base with BASIC.  A write to @>e10c
317     disables the BASIC ROM and enable the cartridge.  A write to @>e108
318     disables the cartridge and enables the BASIC ROM.
319 
320     In order to be recognized by the system ROM, a cartridge should start with
321     >55, >66 or >aa.  This may may correspond to three different ROM header
322     versions (I am not sure).
323 
324     Cartridge may also define a boot ROM at base >0000 (see below).
325 */
326 
tutor_mapper_r(offs_t offset)327 uint8_t tutor_state::tutor_mapper_r(offs_t offset)
328 {
329 	int reply;
330 
331 	switch (offset)
332 	{
333 	case 0x10:
334 		/* return 0x42 if we have a cartridge with an alternate boot ROM */
335 		reply = 0;
336 		break;
337 
338 	default:
339 		logerror("unknown port in %s %d\n", __FILE__, __LINE__);
340 		reply = 0;
341 		break;
342 	}
343 
344 	return reply;
345 }
346 
tutor_mapper_w(offs_t offset,uint8_t data)347 void tutor_state::tutor_mapper_w(offs_t offset, uint8_t data)
348 {
349 	switch (offset)
350 	{
351 	case 0x00:
352 		/* disable system ROM, enable alternate boot ROM in cartridge */
353 		break;
354 
355 	case 0x08:
356 		/* disable cartridge ROM, enable BASIC ROM at base >8000 */
357 		m_bank1->set_entry(0);
358 		m_bank2->set_entry(0);
359 		break;
360 
361 	case 0x0c:
362 		/* enable cartridge ROM, disable BASIC ROM at base >8000 */
363 		if (m_cart_rom)
364 		{
365 			if (m_bank1_switching)
366 				m_bank1->set_entry(1);
367 			m_bank2->set_entry(1);
368 		}
369 		break;
370 
371 	default:
372 		if (!(offset & 1))
373 			logerror("unknown port in %s %d\n", __FILE__, __LINE__);
374 		break;
375 	}
376 }
377 
378 /*
379     This is only called from the debugger; the on-chip memory is handled
380     within the CPU itself.
381 */
tutor_highmem_r(offs_t offset)382 uint8_t tutor_state::tutor_highmem_r(offs_t offset)
383 {
384 	if (m_maincpu->is_onchip(offset | 0xf000)) return m_maincpu->debug_read_onchip_memory(offset&0xff);
385 	return 0;
386 }
387 
388 /*
389     Cassette interface:
390 
391     The cassette interface uses several ports in the >e000 range.
392 
393     Writing to *CPU* address @>ee00 will set the tape output to 0.  Writing to
394     *CPU* address @>ee20 will set the tape output to 1.
395 
396     Tape input level can be read from *CRU* logical address >ed00 (CRU physical
397     address >7680).
398 
399     Writing to @>ee40 enables tape interrupts; writing to @>ee60 disables tape
400     interrupts.  Tape interrupts are level-4 interrupt that occur when the tape
401     input level is high(?).
402 
403     There are other output ports: @>ee80, @>eea0, @>eec0 & @>eee0.  I don't
404     know their exact meaning.
405 */
406 
TIMER_CALLBACK_MEMBER(tutor_state::tape_interrupt_handler)407 TIMER_CALLBACK_MEMBER(tutor_state::tape_interrupt_handler)
408 {
409 	//assert(m_tape_interrupt_enable);
410 	m_maincpu->set_input_line(INT_9995_INT4, (m_cass->input() > 0.0) ? ASSERT_LINE : CLEAR_LINE);
411 }
412 
413 /* CRU handler */
tutor_cassette_r()414 uint8_t tutor_state::tutor_cassette_r()
415 {
416 	return (m_cass->input() > 0.0) ? 1 : 0;
417 }
418 
419 /* memory handler */
tutor_cassette_w(offs_t offset,uint8_t data)420 void tutor_state::tutor_cassette_w(offs_t offset, uint8_t data)
421 {
422 	if (offset & /*0x1f*/0x1e)
423 		logerror("unknown port in %s %d\n", __FILE__, __LINE__);
424 
425 	if ((offset & 0x1f) == 0)
426 	{
427 		data = BIT(offset, 5);
428 
429 		switch ((offset >> 6) & 3)
430 		{
431 		case 0:
432 			/* data out */
433 			m_cass->output((data) ? +1.0 : -1.0);
434 			break;
435 		case 1:
436 			/* interrupt control??? */
437 			//logerror("ignoring write of %d to cassette port 1\n", data);
438 			if (m_tape_interrupt_enable != data)
439 			{
440 				m_tape_interrupt_enable = data;
441 				if (!m_tape_interrupt_enable)
442 					m_tape_interrupt_timer->adjust(/*attotime::from_hz(44100)*/attotime::zero, 0, attotime::from_hz(44100));
443 				else
444 				{
445 					m_tape_interrupt_timer->adjust(attotime::never);
446 					m_maincpu->set_input_line(INT_9995_INT4, CLEAR_LINE);
447 				}
448 			}
449 			break;
450 		case 2:
451 			/* ??? */
452 			logerror("ignoring write of %d to cassette port 2\n", data);
453 			break;
454 		case 3:
455 			/* ??? */
456 			logerror("ignoring write of %d to cassette port 3\n", data);
457 			break;
458 		}
459 	}
460 }
461 
WRITE_LINE_MEMBER(tutor_state::write_centronics_busy)462 WRITE_LINE_MEMBER( tutor_state::write_centronics_busy )
463 {
464 	m_centronics_busy = state;
465 }
466 
467 /* memory handlers */
tutor_printer_r(offs_t offset)468 uint8_t tutor_state::tutor_printer_r(offs_t offset)
469 {
470 	int reply;
471 
472 	switch (offset)
473 	{
474 	case 0x20:
475 		/* busy */
476 		reply = m_centronics_busy ? 0x00 : 0xff;
477 		break;
478 
479 	default:
480 		if (! (offset & 1))
481 			logerror("unknown port in %s %d\n", __FILE__, __LINE__);
482 		reply = 0;
483 		break;
484 	}
485 
486 	return reply;
487 }
488 
tutor_printer_w(offs_t offset,uint8_t data)489 void tutor_state::tutor_printer_w(offs_t offset, uint8_t data)
490 {
491 	switch (offset)
492 	{
493 	case 0x10:
494 		/* data */
495 		m_cent_data_out->write(data);
496 		break;
497 
498 	case 0x40:
499 		/* strobe */
500 		m_centronics->write_strobe(BIT(data, 7));
501 		break;
502 
503 	default:
504 		if (! (offset & 1))
505 			logerror("unknown port in %s %d\n", __FILE__, __LINE__);
506 		break;
507 	}
508 }
509 
510 /*
511     Memory map summary:
512 
513     @>0000-@>7fff: system ROM (can be paged out, see above).
514     @>8000-@>bfff: basic ROM (can be paged out, see above).
515     @>c000-@>dfff: free for future expansion? Used by 24kb cartridges?
516 
517     @>e000(r/w): VDP data
518     @>e002(r/w): VDP register
519 
520     @>e100(w): enable cart and disable system ROM at base >0000??? (the system will only link to such a ROM if @>e110 is >42???)
521     @>e108(w): disable cart and enable BASIC ROM at base >8000?
522     @>e10c(w): enable cart and disable BASIC ROM at base >8000?
523     @>e110(r): cartridges should return >42 if they have a ROM at base >0000 and they want the Tutor to boot from this ROM (with a blwp@>0000)???
524 
525     @>e200(w): sound write
526 
527     @>e600(r): handshake in from whatever device???
528     @>e610(w): ???
529     @>e620(w): ???
530     @>e680(w): handshake out to this device???
531 
532     @>e810(w): parallel port data bus
533     @>e820(r): parallel port busy input
534     @>e840(w): parallel port strobe output
535 
536     @>ee00-@>eee0(w): tape interface (see above)
537 
538     @>f000-@>f0fb: tms9995 internal RAM 1
539     @>fffa-@>fffb: tms9995 internal decrementer
540     @>f000-@>f0fb: tms9995 internal RAM 2
541 */
542 
543 #ifdef UNUSED_FUNCTION
test_w(offs_t offset,uint8_t data)544 void tutor_state::test_w(offs_t offset, uint8_t data)
545 {
546 	switch (offset)
547 	{
548 	default:
549 		logerror("unmapped write %d %d\n", offset, data);
550 		break;
551 	}
552 }
553 #endif
554 
tutor_memmap(address_map & map)555 void tutor_state::tutor_memmap(address_map &map)
556 {
557 	map(0x0000, 0x3fff).rom();
558 	map(0x4000, 0x7fff).bankr("bank1").nopw();
559 	map(0x8000, 0xbfff).bankr("bank2").nopw();
560 	map(0xc000, 0xdfff).noprw(); /*free for expansion, or cartridge ROM?*/
561 
562 	map(0xe000, 0xe000).rw("tms9928a", FUNC(tms9928a_device::vram_read), FUNC(tms9928a_device::vram_write));    /*VDP data*/
563 	map(0xe002, 0xe002).rw("tms9928a", FUNC(tms9928a_device::register_read), FUNC(tms9928a_device::register_write));/*VDP status*/
564 	map(0xe100, 0xe1ff).rw(FUNC(tutor_state::tutor_mapper_r), FUNC(tutor_state::tutor_mapper_w));   /*cartridge mapper*/
565 	map(0xe200, 0xe200).w("sn76489a", FUNC(sn76489a_device::write));    /*sound chip*/
566 	map(0xe800, 0xe8ff).rw(FUNC(tutor_state::tutor_printer_r), FUNC(tutor_state::tutor_printer_w)); /*printer*/
567 	map(0xee00, 0xeeff).nopr().w(FUNC(tutor_state::tutor_cassette_w));     /*cassette interface*/
568 
569 	map(0xf000, 0xffff).r(FUNC(tutor_state::tutor_highmem_r)).nopw(); /*free for expansion (and internal processor RAM)*/
570 }
571 
pyuutajr_mem(address_map & map)572 void tutor_state::pyuutajr_mem(address_map &map)
573 {
574 	map(0x0000, 0x3fff).rom();
575 	map(0x4000, 0x7fff).bankr("bank1").nopw();
576 	map(0x8000, 0xbfff).bankr("bank2").nopw();
577 	map(0xc000, 0xdfff).noprw(); /*free for expansion, or cartridge ROM?*/
578 
579 	map(0xe000, 0xe000).rw("tms9928a", FUNC(tms9928a_device::vram_read), FUNC(tms9928a_device::vram_write));    /*VDP data*/
580 	map(0xe002, 0xe002).rw("tms9928a", FUNC(tms9928a_device::register_read), FUNC(tms9928a_device::register_write));/*VDP status*/
581 	map(0xe100, 0xe1ff).rw(FUNC(tutor_state::tutor_mapper_r), FUNC(tutor_state::tutor_mapper_w));   /*cartridge mapper*/
582 	map(0xe200, 0xe200).w("sn76489a", FUNC(sn76489a_device::write));    /*sound chip*/
583 	map(0xe800, 0xe800).portr("LINE0");
584 	map(0xea00, 0xea00).portr("LINE1");
585 	map(0xec00, 0xec00).portr("LINE2");
586 	map(0xee00, 0xee00).portr("LINE3");
587 
588 	map(0xf000, 0xffff).r(FUNC(tutor_state::tutor_highmem_r)).nopw(); /*free for expansion (and internal processor RAM)*/
589 }
590 
591 /*
592     CRU map summary:
593 
594     >1ee0->1efe: tms9995 flag register
595     >1fda: tms9995 MID flag
596 
597     >ec00->ec7e(r): keyboard interface
598     >ed00(r): tape input
599 */
600 
tutor_io(address_map & map)601 void tutor_state::tutor_io(address_map &map)
602 {
603 	map(0xec00, 0xec7f).r(FUNC(tutor_state::key_r));               /*keyboard interface*/
604 	map(0xed00, 0xed01).r(FUNC(tutor_state::tutor_cassette_r));        /*cassette interface*/
605 }
606 
607 /* tutor keyboard: 56 keys
608 
609 2008-05 FP:
610 Small note about natural keyboard support: currently,
611 - "MON" is mapped to 'F1'
612 - "MOD" is mapped to 'F2'
613 - A, S, D, F, G, R seem to have problems in natural mode
614 */
615 
616 static INPUT_PORTS_START(tutor)
617 	PORT_START("LINE0")
PORT_CODE(KEYCODE_1)618 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)               PORT_CHAR('1') PORT_CHAR('!')
619 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)               PORT_CHAR('2') PORT_CHAR('"')
620 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q)               PORT_CHAR('Q')
621 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W)               PORT_CHAR('W')
622 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A)               PORT_CHAR('A')
623 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S)               PORT_CHAR('S')
624 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z)               PORT_CHAR('Z')
625 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X)               PORT_CHAR('X')
626 
627 	PORT_START("LINE1")
628 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)               PORT_CHAR('3') PORT_CHAR('#')
629 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)               PORT_CHAR('4') PORT_CHAR('$')
630 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E)               PORT_CHAR('E')
631 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R)               PORT_CHAR('R')
632 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D)               PORT_CHAR('D')
633 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F)               PORT_CHAR('F')
634 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C)               PORT_CHAR('C')
635 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V)               PORT_CHAR('V')
636 
637 	PORT_START("LINE2")
638 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)               PORT_CHAR('5') PORT_CHAR('%')
639 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)               PORT_CHAR('6') PORT_CHAR('&')
640 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T)               PORT_CHAR('T')
641 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y)               PORT_CHAR('Y')
642 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G)               PORT_CHAR('G')
643 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H)               PORT_CHAR('H')
644 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B)               PORT_CHAR('B')
645 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N)               PORT_CHAR('N')
646 
647 	PORT_START("LINE3")
648 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)               PORT_CHAR('7') PORT_CHAR('\'')
649 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)               PORT_CHAR('8') PORT_CHAR('(')
650 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)               PORT_CHAR('9') PORT_CHAR(')')
651 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U)               PORT_CHAR('U')
652 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I)               PORT_CHAR('I')
653 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J)               PORT_CHAR('J')
654 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K)               PORT_CHAR('K')
655 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M)               PORT_CHAR('M')
656 
657 	PORT_START("LINE4")
658 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0)               PORT_CHAR('0') PORT_CHAR('=')
659 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("-  b") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
660 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O)               PORT_CHAR('O')
661 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P)               PORT_CHAR('P')
662 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L)               PORT_CHAR('L')
663 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON)           PORT_CHAR(';') PORT_CHAR('+')
664 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA)           PORT_CHAR(',') PORT_CHAR('<')
665 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP)            PORT_CHAR('.') PORT_CHAR('>')
666 
667 	PORT_START("LINE4_alt")
668 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1)
669 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1)
670 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(1) PORT_CODE(KEYCODE_2_PAD)
671 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(1) PORT_CODE(KEYCODE_4_PAD)
672 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(1) PORT_CODE(KEYCODE_8_PAD)
673 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1) PORT_CODE(KEYCODE_6_PAD)
674 
675 	PORT_START("LINE5")
676 		/* Unused? */
677 		PORT_BIT(0x03, IP_ACTIVE_HIGH, IPT_UNUSED)
678 
679 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("o  ^") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(186) PORT_CHAR('^')
680 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE)       PORT_CHAR('_') PORT_CHAR('@')
681 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE)           PORT_CHAR(':') PORT_CHAR('*')
682 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH)       PORT_CHAR('[') PORT_CHAR('{')
683 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH)           PORT_CHAR('/') PORT_CHAR('?')
684 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE)      PORT_CHAR(']') PORT_CHAR('}') // this one is 4th line, 4th key after 'M'
685 
686 	PORT_START("LINE5_alt")
687 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2)
688 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(2)
689 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(2)
690 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(2)
691 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(2)
692 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2)
693 
694 	PORT_START("LINE6")
695 		/* Unused? */
696 		PORT_BIT(0x21, IP_ACTIVE_HIGH, IPT_UNUSED)
697 
698 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
699 		/* only one shift key located on the left, but we support both for emulation to be friendlier */
700 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
701 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Mon") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
702 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RT") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
703 
704 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Mod") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
705 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE)           PORT_CHAR(' ')
706 
707 	PORT_START("LINE7")
708 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
709 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
710 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
711 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
712 
713 		/* Unused? */
714 		PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
715 INPUT_PORTS_END
716 
717 // Unit only has 12 buttons. LINE0 & 3 are scanned with the others, but have nothing connected?
718 static INPUT_PORTS_START(pyuutajr)
719 	PORT_START("LINE0")
720 		PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED)
721 
722 	PORT_START("LINE1")
723 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
724 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
725 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER)
726 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PALLET") PORT_CODE(KEYCODE_P)
727 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MODE") PORT_CODE(KEYCODE_M)
728 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MONITOR") PORT_CODE(KEYCODE_Q)
729 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)
730 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)
731 
732 	PORT_START("LINE2")
733 		PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
734 		PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
735 		PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_COMMA)
736 		PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_STOP)
737 		PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT)
738 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP)
739 		PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN)
740 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT)
741 
742 	PORT_START("LINE3")
743 		PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED)
744 INPUT_PORTS_END
745 
746 void tutor_state::tutor(machine_config &config)
747 {
748 	// basic machine hardware
749 	// TMS9995 CPU @ 10.7 MHz
750 	// No lines connected yet
751 	TMS9995(config, m_maincpu, XTAL(10'738'635));
752 	m_maincpu->set_addrmap(AS_PROGRAM, &tutor_state::tutor_memmap);
753 	m_maincpu->set_addrmap(AS_IO, &tutor_state::tutor_io);
754 
755 	// video hardware
756 	tms9928a_device &vdp(TMS9928A(config, "tms9928a", XTAL(10'738'635)));
757 	vdp.set_screen("screen");
758 	vdp.set_vram_size(0x4000);
759 	SCREEN(config, "screen", SCREEN_TYPE_RASTER);
760 
761 	// Sound
762 	SPEAKER(config, "sound_out").front_center();
763 	SN76489A(config, "sn76489a", 3579545).add_route(ALL_OUTPUTS, "sound_out", 0.75);
764 
765 	CENTRONICS(config, m_centronics, centronics_devices, "printer").busy_handler().set(FUNC(tutor_state::write_centronics_busy));
766 
767 	OUTPUT_LATCH(config, m_cent_data_out);
768 	m_centronics->set_output_latch(*m_cent_data_out);
769 
770 	// Cassette
771 	SPEAKER(config, "cass_out").front_center();
772 	CASSETTE(config, "cassette", 0).add_route(ALL_OUTPUTS, "cass_out", 0.25);
773 
774 	// Cartridge slot
775 	GENERIC_CARTSLOT(config, "cartslot", generic_linear_slot, "tutor_cart", "bin");
776 
777 	// software lists
778 	SOFTWARE_LIST(config, "cart_list").set_original("tutor");
779 
780 }
781 
pyuutajr(machine_config & config)782 void tutor_state::pyuutajr(machine_config &config)
783 {
784 	tutor(config);
785 	m_maincpu->set_addrmap(AS_PROGRAM, &tutor_state::pyuutajr_mem);
786 	//config.device_remove("centronics");
787 	//config.device_remove("cassette");
788 }
789 
790 /*
791   ROM loading
792 */
793 
794 ROM_START(tutor)
795 	ROM_REGION(0x10000, "maincpu", 0)
796 	ROM_LOAD("tutor1.bin", 0x0000, 0x8000, CRC(702c38ba) SHA1(ce60607c3038895e31915d41bb5cf71cb8522d7a))      /* system ROM */
797 	ROM_LOAD("tutor2.bin", 0x8000, 0x4000, CRC(05f228f5) SHA1(46a14a45f6f9e2c30663a2b87ce60c42768a78d0))      /* BASIC ROM */
798 ROM_END
799 
800 
801 ROM_START(pyuuta)
802 	ROM_REGION(0x10000, "maincpu", 0)
803 	ROM_LOAD("tomy29.7", 0x0000, 0x8000, CRC(7553bb6a) SHA1(fa41c45cb6d3daf7435f2a82f77dfa286003255e))      /* system ROM */
804 ROM_END
805 
806 ROM_START(pyuutajr)
807 	ROM_REGION(0x10000, "maincpu", 0)
808 	ROM_LOAD( "ipl.rom", 0x0000, 0x4000, CRC(2ca37e62) SHA1(eebdc5c37d3b532edd5e5ca65eb785269ebd1ac0))      /* system ROM */
809 ROM_END
810 
811 //    YEAR   NAME      PARENT  COMPAT  MACHINE   INPUT     CLASS        INIT        COMPANY   FULLNAME           FLAGS
812 COMP( 1983?, tutor,    0,      0,      tutor,    tutor,    tutor_state, empty_init, "Tomy",   "Tomy Tutor" ,     0)
813 COMP( 1982,  pyuuta,   tutor,  0,      tutor,    tutor,    tutor_state, empty_init, "Tomy",   "Tomy Pyuuta" ,    0)
814 COMP( 1983,  pyuutajr, tutor,  0,      pyuutajr, pyuutajr, tutor_state, empty_init, "Tomy",   "Tomy Pyuuta Jr.", 0)
815