trunk/src/mess/drivers/tispeak.c
| r242799 | r242800 | |
| 7 | 7 | (still need to write notes here..) |
| 8 | 8 | |
| 9 | 9 | Other stuff on similar hardware: |
| 10 | | - Language Tutor/Translator |
| 11 | 10 | - Touch & Tell, but it runs on a TMS1100! |
| 12 | 11 | - Speak & Spell Compact, Speak & Write (UK version), TMS1100? TMS0980? |
| 13 | 12 | - Speak & Read |
| r242799 | r242800 | |
| 21 | 20 | #include "bus/generic/slot.h" |
| 22 | 21 | #include "bus/generic/carts.h" |
| 23 | 22 | |
| 23 | #include "lantutor.lh" |
| 24 | 24 | #include "tispeak.lh" |
| 25 | 25 | |
| 26 | 26 | // The master clock is a single stage RC oscillator into TMS5100 RCOSC: |
| r242799 | r242800 | |
| 57 | 57 | int m_filament_on; |
| 58 | 58 | int m_power_on; |
| 59 | 59 | |
| 60 | | UINT16 m_digit_state[9]; |
| 60 | UINT16 m_digit_state[0x10]; |
| 61 | 61 | void display_update(); |
| 62 | 62 | TIMER_DEVICE_CALLBACK_MEMBER(delayed_filament_off); |
| 63 | 63 | |
| 64 | UINT32 m_cart_max_size; |
| 65 | UINT8* m_cart_base; |
| 66 | DECLARE_DEVICE_IMAGE_LOAD_MEMBER(tispeak_cartridge); |
| 67 | DECLARE_DRIVER_INIT(snspell); |
| 68 | DECLARE_DRIVER_INIT(lantutor); |
| 69 | |
| 64 | 70 | DECLARE_READ8_MEMBER(snspell_read_k); |
| 65 | 71 | DECLARE_WRITE16_MEMBER(snmath_write_o); |
| 66 | 72 | DECLARE_WRITE16_MEMBER(snspell_write_o); |
| 67 | 73 | DECLARE_WRITE16_MEMBER(snspell_write_r); |
| 74 | DECLARE_WRITE16_MEMBER(lantutor_write_r); |
| 68 | 75 | |
| 69 | 76 | DECLARE_INPUT_CHANGED_MEMBER(power_button); |
| 70 | | DECLARE_WRITE_LINE_MEMBER(auto_power_off); |
| 71 | 77 | void power_off(); |
| 72 | 78 | |
| 73 | | DECLARE_DEVICE_IMAGE_LOAD_MEMBER(tispeak_cartridge); |
| 74 | 79 | virtual void machine_reset(); |
| 75 | 80 | virtual void machine_start(); |
| 76 | 81 | }; |
| r242799 | r242800 | |
| 87 | 92 | { |
| 88 | 93 | UINT32 size = m_cart->common_get_size("rom"); |
| 89 | 94 | |
| 90 | | // max size is 16KB |
| 91 | | if (size > 0x4000) |
| 95 | if (size > m_cart_max_size) |
| 92 | 96 | { |
| 93 | 97 | image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid file size"); |
| 94 | 98 | return IMAGE_INIT_FAIL; |
| r242799 | r242800 | |
| 101 | 105 | } |
| 102 | 106 | |
| 103 | 107 | |
| 108 | DRIVER_INIT_MEMBER(tispeak_state, snspell) |
| 109 | { |
| 110 | m_cart_max_size = 0x4000; |
| 111 | m_cart_base = memregion("tms6100")->base() + 0x8000; |
| 112 | } |
| 104 | 113 | |
| 114 | DRIVER_INIT_MEMBER(tispeak_state, lantutor) |
| 115 | { |
| 116 | m_cart_max_size = 0x10000; |
| 117 | m_cart_base = memregion("tms6100")->base(); |
| 118 | } |
| 119 | |
| 120 | |
| 121 | |
| 105 | 122 | /*************************************************************************** |
| 106 | 123 | |
| 107 | 124 | VFD Display |
| r242799 | r242800 | |
| 136 | 153 | } |
| 137 | 154 | |
| 138 | 155 | // update digit state |
| 139 | | for (int i = 0; i < 9; i++) |
| 156 | for (int i = 0; i < 0x10; i++) |
| 140 | 157 | if (m_r >> i & 1) |
| 141 | 158 | m_digit_state[i] = m_o; |
| 142 | 159 | |
| 143 | 160 | // send to output |
| 144 | | for (int i = 0; i < 9; i++) |
| 161 | for (int i = 0; i < 0x10; i++) |
| 145 | 162 | { |
| 146 | 163 | // standard led14seg |
| 147 | 164 | output_set_digit_value(i, m_filament_on ? m_digit_state[i] & 0x3fff : 0); |
| r242799 | r242800 | |
| 178 | 195 | WRITE16_MEMBER(tispeak_state::snspell_write_r) |
| 179 | 196 | { |
| 180 | 197 | // R0-R7: input mux and select digit (+R8 if the device has 9 digits) |
| 181 | | // R15: filament on |
| 198 | // R15: filament on (handled in display_update) |
| 199 | // R13: power-off request, on falling edge |
| 200 | if ((m_r >> 13 & 1) && !(data >> 13 & 1)) |
| 201 | power_off(); |
| 202 | |
| 182 | 203 | // other bits: MCU internal use |
| 183 | 204 | m_r = data; |
| 184 | 205 | display_update(); |
| r242799 | r242800 | |
| 203 | 224 | m_power_on = 0; |
| 204 | 225 | } |
| 205 | 226 | |
| 206 | | WRITE_LINE_MEMBER(tispeak_state::auto_power_off) |
| 207 | | { |
| 208 | | // power-off request from the MCU, when [OFF] is pressed, also typically after a couple of minutes of idling |
| 209 | | if (state) |
| 210 | | power_off(); |
| 211 | | } |
| 212 | 227 | |
| 213 | | |
| 214 | 228 | // snmath specific |
| 215 | 229 | |
| 216 | 230 | WRITE16_MEMBER(tispeak_state::snmath_write_o) |
| r242799 | r242800 | |
| 223 | 237 | } |
| 224 | 238 | |
| 225 | 239 | |
| 240 | // lantutor specific |
| 226 | 241 | |
| 242 | WRITE16_MEMBER(tispeak_state::lantutor_write_r) |
| 243 | { |
| 244 | // same as default, except R13 is used for an extra digit |
| 245 | m_r = data; |
| 246 | display_update(); |
| 247 | } |
| 248 | |
| 249 | |
| 250 | |
| 227 | 251 | /*************************************************************************** |
| 228 | 252 | |
| 229 | 253 | Inputs |
| r242799 | r242800 | |
| 363 | 387 | INPUT_PORTS_END |
| 364 | 388 | |
| 365 | 389 | |
| 390 | static INPUT_PORTS_START( lantutor ) |
| 391 | PORT_INCLUDE( snspell ) |
| 366 | 392 | |
| 393 | PORT_MODIFY("IN.5") // R5 |
| 394 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_NAME("Diacritical") |
| 395 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_NAME("Space") |
| 396 | |
| 397 | PORT_MODIFY("IN.6") // R6 |
| 398 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_NAME("1") |
| 399 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_NAME("2") |
| 400 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_NAME("3") |
| 401 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_NAME("4") |
| 402 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_NAME("5") |
| 403 | |
| 404 | PORT_MODIFY("IN.7") // R7 |
| 405 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_NAME("6") |
| 406 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_NAME("7") |
| 407 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_NAME("8") |
| 408 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_NAME("9") |
| 409 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_NAME("0") |
| 410 | |
| 411 | PORT_MODIFY("IN.8") // Vss! |
| 412 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_NAME("Translate") |
| 413 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_NAME("Learn") |
| 414 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("Phrase") |
| 415 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("Link") |
| 416 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_NAME("Repeat") |
| 417 | INPUT_PORTS_END |
| 418 | |
| 419 | |
| 420 | |
| 367 | 421 | /*************************************************************************** |
| 368 | 422 | |
| 369 | 423 | Machine Config |
| r242799 | r242800 | |
| 398 | 452 | astring region_tag; |
| 399 | 453 | memory_region *src = memregion(region_tag.cpy(m_cart->tag()).cat(GENERIC_ROM_REGION_TAG)); |
| 400 | 454 | if (src) |
| 401 | | { |
| 402 | | UINT8 *dest_ptr = memregion("tms6100")->base() + 0x8000; |
| 403 | | memcpy(dest_ptr, src->base(), src->bytes()); |
| 404 | | } |
| 455 | memcpy(m_cart_base, src->base(), src->bytes()); |
| 405 | 456 | } |
| 406 | 457 | } |
| 407 | 458 | |
| r242799 | r242800 | |
| 413 | 464 | MCFG_TMS1XXX_READ_K_CB(READ8(tispeak_state, snspell_read_k)) |
| 414 | 465 | MCFG_TMS1XXX_WRITE_O_CB(WRITE16(tispeak_state, snmath_write_o)) |
| 415 | 466 | MCFG_TMS1XXX_WRITE_R_CB(WRITE16(tispeak_state, snspell_write_r)) |
| 416 | | MCFG_TMS1XXX_POWER_OFF_CB(WRITELINE(tispeak_state, auto_power_off)) |
| 417 | 467 | |
| 418 | 468 | MCFG_TMS0270_READ_CTL_CB(DEVREAD8("tms5100", tms5100_device, ctl_r)) |
| 419 | 469 | MCFG_TMS0270_WRITE_CTL_CB(DEVWRITE8("tms5100", tms5100_device, ctl_w)) |
| r242799 | r242800 | |
| 451 | 501 | MCFG_SOFTWARE_LIST_ADD("cart_list", "snspell") |
| 452 | 502 | MACHINE_CONFIG_END |
| 453 | 503 | |
| 504 | static MACHINE_CONFIG_DERIVED( lantutor, snmath ) |
| 454 | 505 | |
| 506 | /* basic machine hardware */ |
| 507 | MCFG_CPU_MODIFY("maincpu") |
| 508 | MCFG_TMS1XXX_WRITE_O_CB(WRITE16(tispeak_state, snspell_write_o)) |
| 509 | MCFG_TMS1XXX_WRITE_R_CB(WRITE16(tispeak_state, lantutor_write_r)) |
| 455 | 510 | |
| 511 | MCFG_DEFAULT_LAYOUT(layout_lantutor) |
| 512 | |
| 513 | /* cartridge */ |
| 514 | MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "lantutor") |
| 515 | MCFG_GENERIC_MANDATORY |
| 516 | MCFG_GENERIC_EXTENSIONS("vsm,bin") |
| 517 | MCFG_GENERIC_LOAD(tispeak_state, tispeak_cartridge) |
| 518 | |
| 519 | MCFG_SOFTWARE_LIST_ADD("cart_list", "lantutor") |
| 520 | MACHINE_CONFIG_END |
| 521 | |
| 522 | |
| 523 | |
| 456 | 524 | /*************************************************************************** |
| 457 | 525 | |
| 458 | 526 | Game driver(s) |
| r242799 | r242800 | |
| 553 | 621 | ROM_END |
| 554 | 622 | |
| 555 | 623 | |
| 556 | | |
| 557 | 624 | ROM_START( snmath ) |
| 558 | 625 | ROM_REGION( 0x1000, "maincpu", 0 ) |
| 559 | | // typed in from patent 4946391, verified with source code (mark BAD_DUMP just to be unsure) |
| 626 | // typed in from patent 4946391, verified with source code |
| 560 | 627 | // BTANB note: Mix It does not work at all, this is an original bug in the prototype. There are probably other minor bugs too. |
| 561 | | ROM_LOAD( "us4946391_t2074", 0x0000, 0x1000, BAD_DUMP CRC(011f0c2d) SHA1(d2e14d72e03ca864abd51da78ffb71a9da82f624) ) |
| 628 | ROM_LOAD( "us4946391_t2074", 0x0000, 0x1000, CRC(011f0c2d) SHA1(d2e14d72e03ca864abd51da78ffb71a9da82f624) ) |
| 562 | 629 | |
| 563 | 630 | ROM_REGION( 1246, "maincpu:ipla", 0 ) |
| 564 | 631 | ROM_LOAD( "tms0980_default_ipla.pla", 0, 1246, CRC(42db9a38) SHA1(2d127d98028ec8ec6ea10c179c25e447b14ba4d0) ) |
| r242799 | r242800 | |
| 592 | 659 | ROM_END |
| 593 | 660 | |
| 594 | 661 | |
| 662 | ROM_START( lantutor ) |
| 663 | ROM_REGION( 0x1000, "maincpu", 0 ) |
| 664 | ROM_LOAD( "us4631748_tmc0275", 0x0000, 0x1000, CRC(22818845) SHA1(1a84f15fb18ca66b1f2bf7491d76fbc56068984d) ) // extracted visually from patent 4631748, verified with source code |
| 595 | 665 | |
| 596 | | COMP( 1978, snspell, 0, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "Speak & Spell (US prototype)", GAME_IMPERFECT_SOUND ) // also US set 1 |
| 597 | | COMP( 1980, snspella, snspell, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "Speak & Spell (US set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 598 | | COMP( 1978, snspelluk, snspell, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "Speak & Spell (UK set 1)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 599 | | COMP( 1981, snspelluka, snspell, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "Speak & Spell (UK set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) // different voice actor |
| 600 | | COMP( 1979, snspelljp, snspell, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "Speak & Spell (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 601 | | COMP( 1980, ladictee, snspell, 0, snspell, snspell, driver_device, 0, "Texas Instruments", "La Dictee Magique (France)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) // doesn't work due to missing CD2702 MCU dump, German version has CD2702 too |
| 666 | ROM_REGION( 1246, "maincpu:ipla", 0 ) |
| 667 | ROM_LOAD( "tms0980_default_ipla.pla", 0, 1246, CRC(42db9a38) SHA1(2d127d98028ec8ec6ea10c179c25e447b14ba4d0) ) |
| 668 | ROM_REGION( 2127, "maincpu:mpla", 0 ) |
| 669 | ROM_LOAD( "tms0270_cd2708_mpla.pla", 0, 2127, BAD_DUMP CRC(504b96bb) SHA1(67b691e7c0b97239410587e50e5182bf46475b43) ) // taken from cd2708, need to verify if it's same as tmc0275 |
| 670 | ROM_REGION( 1246, "maincpu:opla", 0 ) |
| 671 | ROM_LOAD( "tms0270_tmc0271_opla.pla", 0, 1246, BAD_DUMP CRC(9ebe12ab) SHA1(acb4e07ba26f2daca5f1c234885ac0371c7ce87f) ) // taken from snspell, mostly looks correct |
| 602 | 672 | |
| 603 | | COMP( 1980, snmath, 0, 0, snmath, snmath, driver_device, 0, "Texas Instruments", "Speak & Math (US prototype)", GAME_IMPERFECT_SOUND ) // also US set 1 |
| 604 | | COMP( 1986, snmatha, snmath, 0, snmath, snmath, driver_device, 0, "Texas Instruments", "Speak & Math (US set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 673 | ROM_REGION( 0x10000, "tms6100", ROMREGION_ERASEFF ) // cartridge area |
| 674 | ROM_END |
| 675 | |
| 676 | |
| 677 | |
| 678 | COMP( 1978, snspell, 0, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "Speak & Spell (US prototype)", GAME_IMPERFECT_SOUND ) // also US set 1 |
| 679 | COMP( 1980, snspella, snspell, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "Speak & Spell (US set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 680 | COMP( 1978, snspelluk, snspell, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "Speak & Spell (UK set 1)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 681 | COMP( 1981, snspelluka, snspell, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "Speak & Spell (UK set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) // different voice actor |
| 682 | COMP( 1979, snspelljp, snspell, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "Speak & Spell (Japan)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 683 | COMP( 1980, ladictee, snspell, 0, snspell, snspell, tispeak_state, snspell, "Texas Instruments", "La Dictee Magique (France)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) // doesn't work due to missing CD2702 MCU dump, German version has CD2702 too |
| 684 | |
| 685 | COMP( 1980, snmath, 0, 0, snmath, snmath, driver_device, 0, "Texas Instruments", "Speak & Math (US prototype)", GAME_IMPERFECT_SOUND ) // also US set 1 |
| 686 | COMP( 1986, snmatha, snmath, 0, snmath, snmath, driver_device, 0, "Texas Instruments", "Speak & Math (US set 2)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |
| 687 | |
| 688 | COMP( 1979, lantutor, 0, 0, lantutor, lantutor, tispeak_state, lantutor, "Texas Instruments", "Language Tutor (prototype)", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND ) |