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