/* MESS Driver for TI-99/8 Computer. Raphael Nabet, 2003. */ /* TI-99/8 preliminary info: Name: Texas Instruments Computer TI-99/8 (no "Home") References: * machine room * TI99/8 user manual * TI99/8 schematics * TI99/8 ROM source code * Message on TI99 yahoo group for CPU info General: * a few dozen units were built in 1983, never released * CPU is a custom variant of tms9995 (part code MP9537): the 16-bit RAM and (presumably) the on-chip decrementer are disabled * 220kb(?) of ROM, including monitor, GPL interpreter, TI-extended basic II, and a P-code interpreter with a few utilities. More specifically: - 32kb system ROM with GPL interpreter, TI-extended basic II and a few utilities (no dump, but 90% of source code is available and has been compiled) - 18kb system GROMs, with monitor and TI-extended basic II (no dump, but source code is available and has been compiled) - 4(???)kb DSR ROM for hexbus (no dump) - 32(?)kb speech ROM: contents are slightly different from the 99/4(a) speech ROMs, due to the use of a tms5220 speech synthesizer instead of the older tms0285 (no dump, but 99/4(a) speech ROMs should work mostly OK) - 12(???)kb ROM with PCode interpreter (no dump) - 2(3???)*48kb of GROMs with PCode data files (no dump) * 2kb SRAM (16 bytes of which are hidden), 64kb DRAM (expandable to almost 16MBytes), 16kb vdp RAM * tms9118 vdp (similar to tms9918a, slightly different bus interface and timings) * I/O - 50-key keyboard, plus 2 optional joysticks - sound and speech (both ti99/4(a)-like) - Hex-Bus - Cassette * cartridge port on the top * 50-pin(?) expansion port on the back * Programs can enable/disable the ROM and memory mapped register areas. Mapper: Mapper has 4kb page size (-> 16 pages per map file), 32 bits per page entry. Address bits A0-A3 are the page index, whereas bits A4-A15 are the offset in the page. Physical address space is 16Mbytes. All pages are 4 kBytes in lenght, and they can start anywhere in the 24-bit physical address space. The mapper can load any of 4 map files from SRAM by DMA. Map file 0 is used by BIOS, file 1 by memory XOPs(?), file 2 by P-code interpreter(???). Format of map table entry: * bit 0: WTPROT: page is write protected if 1 * bit 1: XPROT: page is execute protected if 1 * bit 2: RDPROT: page is read protected if 1 * bit 3: reserved, value is ignored * bits 4-7: reserved, always forced to 0 * bits 8-23: page base address in 24-bit virtual address space Format of mapper control register: * bit 0-4: unused??? * bit 5-6: map file to load/save (0 for file 0, 1 for file 1, etc.) * bit 7: 0 -> load map file from RAM, 1 -> save map file to RAM Format of mapper status register (cleared by read): * bit 0: WPE - Write-Protect Error * bit 1: XCE - eXeCute Error * bit 2: RPE - Read-Protect Error * bits 3-7: unused??? Memory error interrupts are enabled by setting WTPROT/XPROT/RDPROT. When an error occurs, the tms9901 INT1* pin is pulled low (active). The pin remains low until the mapper status register is read. 24-bit address map: * >000000->00ffff: console RAM * >010000->feffff: expansion? * >ff0000->ff0fff: empty??? * >ff1000->ff3fff: unused??? * >ff4000->ff5fff: DSR space * >ff6000->ff7fff: cartridge space * >ff8000->ff9fff(???): >4000 ROM (normally enabled with a write to CRU >2700) * >ffa000->ffbfff(?): >2000 ROM * >ffc000->ffdfff(?): >6000 ROM CRU map: Since the tms9995 supports full 15-bit CRU addresses, the >1000->17ff (>2000->2fff) range was assigned to support up to 16 extra expansion slot. The good thing with using >1000->17ff is the fact that older expansion cards that only decode 12 address bits will think that addresses >1000->17ff refer to internal TI99 peripherals (>000->7ff range), which suppresses any risk of bus contention. * >0000->001f (>0000->003e): tms9901 - P4: 1 -> MMD (Memory Mapped Devices?) at >8000, ROM enabled - P5: 1 -> no P-CODE GROMs * >0800->17ff (>1000->2ffe): Peripheral CRU space * >1380->13ff (>2700->27fe): Internal DSR, with two output bits: - >2700: Internal DSR select (parts of Basic and various utilities) - >2702: SBO -> hardware reset Memory map (TMS9901 P4 == 1): When TMS9901 P4 output is set, locations >8000->9fff are ignored by mapper. * >8000->83ff: SRAM (>8000->80ff is used by the mapper DMA controller to hold four map files) (r/w) * >8400: sound port (w) * >8410->87ff: SRAM (r/w) * >8800: VDP data read port (r) * >8802: VDP status read port (r) * >8810: memory mapper status and control registers (r/w) * >8c00: VDP data write port (w) * >8c02: VDP address and register write port (w) * >9000: speech synthesizer read port (r) * >9400: speech synthesizer write port (w) * >9800 GPL data read port (r) * >9802 GPL address read port (r) * >9c00 GPL data write port -- unused (w) * >9c02 GPL address write port (w) Memory map (TMS9901 P5 == 0): When TMS9901 P5 output is cleared, locations >f840->f8ff(?) are ignored by mapper. * >f840: data port for P-code grom library 0 (r?) * >f880: data port for P-code grom library 1 (r?) * >f8c0: data port for P-code grom library 2 (r?) * >f842: address port for P-code grom library 0 (r/w?) * >f882: address port for P-code grom library 1 (r/w?) * >f8c2: address port for P-code grom library 2 (r/w?) Cassette interface: Identical to ti99/4(a), except that the CS2 unit is not implemented. Keyboard interface: The keyboard interface uses the console tms9901 PSI, but the pin assignment and key matrix are different from both 99/4 and 99/4a. - P0-P3: column select - INT6*-INT11*: row inputs (int6* is only used for joystick fire) */ #include "driver.h" #include "inputx.h" #include "video/tms9928a.h" #include "machine/ti99_4x.h" #include "machine/tms9901.h" #include "audio/spchroms.h" #include "machine/99_peb.h" #include "machine/994x_ser.h" #include "machine/99_dsk.h" #include "machine/99_ide.h" #include "cpu/tms9900/tms9900.h" #include "devices/mflopimg.h" #include "devices/cassette.h" #include "machine/smartmed.h" #include "sound/5220intf.h" #include "devices/harddriv.h" /* Memory map - see description above */ static ADDRESS_MAP_START(ti99_8_memmap, ADDRESS_SPACE_PROGRAM, 8) AM_RANGE(0x0000, 0xffff) AM_READWRITE(ti99_8_r, ti99_8_w) ADDRESS_MAP_END /* CRU map - see description above */ static ADDRESS_MAP_START(ti99_8_writecru, ADDRESS_SPACE_IO, 8) AM_RANGE(0x0000, 0x07ff) AM_WRITE(tms9901_0_cru_w) AM_RANGE(0x0800, 0x17ff) AM_WRITE(ti99_8_peb_cru_w) ADDRESS_MAP_END static ADDRESS_MAP_START(ti99_8_readcru, ADDRESS_SPACE_IO, 8) AM_RANGE(0x0000, 0x00ff) AM_READ(tms9901_0_cru_r) AM_RANGE(0x0100, 0x02ff) AM_READ(ti99_8_peb_cru_r) ADDRESS_MAP_END /* ti99/8 : 54-key keyboard */ INPUT_PORTS_START(ti99_8) /* 1 port for config */ PORT_START /* config */ PORT_BIT( config_fdc_mask << config_fdc_bit, /*fdc_kind_hfdc << config_fdc_bit*/0, IPT_DIPSWITCH_NAME) PORT_NAME("Floppy disk controller") PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) ) PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" ) #if HAS_99CCFDC PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" ) #endif PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" ) PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" ) PORT_BIT( config_ide_mask << config_ide_bit, /*1 << config_ide_bit*/0, IPT_DIPSWITCH_NAME) PORT_NAME("Nouspickel's IDE card") PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) ) PORT_BIT( config_rs232_mask << config_rs232_bit, /*1 << config_rs232_bit*/0, IPT_DIPSWITCH_NAME) PORT_NAME("TI RS232 card") PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) ) PORT_BIT( config_hsgpl_mask << config_hsgpl_bit, 0/*1 << config_hsgpl_bit*/, IPT_DIPSWITCH_NAME) PORT_NAME("SNUG HSGPL card") PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 1 << config_hsgpl_bit, DEF_STR( On ) ) PORT_BIT( config_mecmouse_mask << config_mecmouse_bit, 0, IPT_DIPSWITCH_NAME) PORT_NAME("Mechatronics Mouse") PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 1 << config_mecmouse_bit, DEF_STR( On ) ) PORT_BIT( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, IPT_DIPSWITCH_NAME) PORT_NAME("Nouspickel's USB-SM card") PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) ) /* 3 ports for mouse */ PORT_START /* Mouse - X AXIS */ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_START /* Mouse - Y AXIS */ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_START /* Mouse - buttons */ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1) PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1) /* 16 ports for keyboard and joystick */ PORT_START /* col 0 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ALPHA LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FCTN") PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LSHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 1 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 ! DEL") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("q Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("a A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("z Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 2 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @ INS") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("w W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("s S (LEFT)") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("x X (DOWN)") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 3 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("e E (UP)") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("d D (RIGHT)") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("c C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 4 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $ CLEAR") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("r R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("f F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("v V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 5 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 % BEGIN") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("t T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("g G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("b B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 6 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^ PROC'D") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("y Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("h H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("n N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 7 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 & AID") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("u U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("j J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("m M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 8 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 * REDO") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("i I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 9 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 ( BACK") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("o O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("l L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 10 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("p P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 11 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= + QUIT") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RSHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 12 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(SPACE)") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 13 */ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('`') PORT_CHAR('~') PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START /* col 14: "wired handset 1" (= joystick 1) */ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN/*, "(1DOWN)", CODE_NONE, OSD_JOY_DOWN, 0*/) PORT_PLAYER(1) PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT/*, "(1RIGHT)", CODE_NONE, OSD_JOY_RIGHT, 0*/) PORT_PLAYER(1) PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT/*, "(1LEFT)", CODE_NONE, OSD_JOY_LEFT, 0*/) PORT_PLAYER(1) PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP/*, "(1UP)", CODE_NONE, OSD_JOY_UP*/) PORT_PLAYER(1) PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON1/*, "(1FIRE)", CODE_NONE, OSD_JOY_FIRE, 0*/) PORT_PLAYER(1) PORT_START /* col 15: "wired handset 2" (= joystick 2) */ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN/*, "(2UP)", CODE_NONE, OSD_JOY2_UP, 0*/) PORT_PLAYER(2) PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT/*, "(2DOWN)", CODE_NONE, OSD_JOY2_DOWN, 0*/) PORT_PLAYER(2) PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT/*, "(2RIGHT)", CODE_NONE, OSD_JOY2_RIGHT, 0*/) PORT_PLAYER(2) PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP/*, "(2LEFT)", CODE_NONE, OSD_JOY2_LEFT, 0*/) PORT_PLAYER(2) PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON1/*, "(2FIRE)", CODE_NONE, OSD_JOY2_FIRE, 0*/) PORT_PLAYER(2) INPUT_PORTS_END /* TMS5220 speech synthesizer */ static struct TMS5220interface tms5220interface = { NULL, /* no IRQ callback */ spchroms_read, /* speech ROM read handler */ spchroms_load_address, /* speech ROM load address handler */ spchroms_read_and_branch /* speech ROM read and branch handler */ }; static const TMS9928a_interface tms9118_interface = { TMS99x8A, 0x4000, 0, 0, tms9901_set_int2 }; static MACHINE_START(ti99_8_60hz) { TMS9928A_configure(&tms9118_interface); } static const TMS9928a_interface tms9129_interface = { TMS9929A, 0x4000, 0, 0, tms9901_set_int2 }; static MACHINE_START(ti99_8_50hz) { TMS9928A_configure(&tms9129_interface); } static struct tms9995reset_param ti99_8_processor_config = { 1, /* enable automatic wait state generation */ /* (in January 83 99/8 schematics sheet 9: the delay logic seems to keep READY low for one cycle when RESET* is asserted, but the timings are completely wrong this way) */ 0, /* no IDLE callback */ 1 /* MP9537 mask */ }; static MACHINE_DRIVER_START(ti99_8_60hz) /* basic machine hardware */ /* TMS9995-MP9537 CPU @ 10.7 MHz */ MDRV_CPU_ADD(TMS9995, 10738635) MDRV_CPU_CONFIG(ti99_8_processor_config) MDRV_CPU_PROGRAM_MAP(ti99_8_memmap, 0) MDRV_CPU_IO_MAP(ti99_8_readcru, ti99_8_writecru) MDRV_CPU_VBLANK_INT(ti99_vblank_interrupt, 1) /*MDRV_CPU_PERIODIC_INT(func, rate)*/ MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) /*MDRV_INTERLEAVE(interleave)*/ MDRV_MACHINE_START( ti99_8_60hz ) MDRV_MACHINE_RESET( ti99 ) /* video hardware */ MDRV_IMPORT_FROM(tms9928a) /* sound hardware */ MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD(WAVE, 0) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20) MDRV_SOUND_ADD(SN76496, 3579545) /* 3.579545 MHz */ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) MDRV_SOUND_ADD(TMS5220, 680000L) MDRV_SOUND_CONFIG(tms5220interface) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_DRIVER_END static MACHINE_DRIVER_START(ti99_8_50hz) /* basic machine hardware */ /* TMS9995-MP9537 CPU @ 10.7 MHz */ MDRV_CPU_ADD(TMS9995, 10738635) MDRV_CPU_CONFIG(ti99_8_processor_config) MDRV_CPU_PROGRAM_MAP(ti99_8_memmap, 0) MDRV_CPU_IO_MAP(ti99_8_readcru, ti99_8_writecru) MDRV_CPU_VBLANK_INT(ti99_vblank_interrupt, 1) /*MDRV_CPU_PERIODIC_INT(func, rate)*/ MDRV_SCREEN_REFRESH_RATE(50) MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) /*MDRV_INTERLEAVE(interleave)*/ MDRV_MACHINE_START( ti99_8_50hz ) MDRV_MACHINE_RESET( ti99 ) /* video hardware */ MDRV_IMPORT_FROM(tms9928a) /* sound hardware */ MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD(SN76496, 3579545) /* 3.579545 MHz */ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) MDRV_SOUND_ADD(TMS5220, 680000L) MDRV_SOUND_CONFIG(tms5220interface) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MDRV_SOUND_ADD(WAVE, 0) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20) MACHINE_DRIVER_END /* ROM loading */ ROM_START(ti99_8) /*CPU memory space*/ ROM_REGION(region_cpu1_len_8,REGION_CPU1,0) ROM_LOAD("998rom.bin", 0x0000, 0x8000, NO_DUMP) /* system ROMs */ /*GROM memory space*/ ROM_REGION(0x10000, region_grom, 0) ROM_LOAD("998grom.bin", 0x0000, 0x6000, NO_DUMP) /* system GROMs */ /*DSR ROM space*/ ROM_REGION(region_dsr_len, region_dsr, 0) ROM_LOAD_OPTIONAL("disk.bin", offset_fdc_dsr, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */ #if HAS_99CCFDC ROM_LOAD_OPTIONAL("ccfdc.bin", offset_ccfdc_dsr, 0x4000, BAD_DUMP CRC(f69cc69d)) /* CorComp disk DSR ROM */ #endif ROM_LOAD_OPTIONAL("bwg.bin", offset_bwg_dsr, 0x8000, CRC(06f1ec89) SHA1(6ad77033ed268f986d9a5439e65f7d391c4b7651)) /* BwG disk DSR ROM */ ROM_LOAD_OPTIONAL("hfdc.bin", offset_hfdc_dsr, 0x4000, CRC(66fbe0ed) SHA1(11df2ecef51de6f543e4eaf8b2529d3e65d0bd59)) /* HFDC disk DSR ROM */ ROM_LOAD_OPTIONAL("rs232.bin", offset_rs232_dsr, 0x1000, CRC(eab382fb) SHA1(ee609a18a21f1a3ddab334e8798d5f2a0fcefa91)) /* TI rs232 DSR ROM */ /* HSGPL memory space */ ROM_REGION(region_hsgpl_len, region_hsgpl, 0) /*TMS5220 ROM space*/ ROM_REGION(0x8000, region_speech_rom, 0) ROM_LOAD_OPTIONAL("spchrom.bin", 0x0000, 0x8000, BAD_DUMP CRC(58b155f7) SHA1(382292295c00dff348d7e17c5ce4da12a1d87763)) /* system speech ROM */ ROM_END #define rom_ti99_8e rom_ti99_8 static void ti99_8_cassette_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* cassette */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_COUNT: info->i = 1; break; default: cassette_device_getinfo(devclass, state, info); break; } } static void ti99_8_cartslot_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* cartslot */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_CARTSLOT; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 0; break; case DEVINFO_INT_CREATABLE: info->i = 0; break; case DEVINFO_INT_COUNT: info->i = 3; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_LOAD: info->load = device_load_ti99_cart; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti99_cart; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), "bin,c,d,g,m,crom,drom,grom,mrom"); break; } } static void ti99_8_floppy_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* floppy */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_COUNT: info->i = 4; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_FLOPPY_OPTIONS: info->p = (void *) floppyoptions_ti99; break; default: floppy_device_getinfo(devclass, state, info); break; } } static void ti99_8_harddisk_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* harddisk */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_HARDDISK; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 1; break; case DEVINFO_INT_CREATABLE: info->i = 0; break; case DEVINFO_INT_COUNT: info->i = 3; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_INIT: info->init = device_init_mess_hd; break; case DEVINFO_PTR_LOAD: info->load = device_load_ti99_hd; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti99_hd; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), "hd"); break; case DEVINFO_STR_DEV_TAG: strcpy(info->s = device_temp_str(), "ti99_8_hd"); break; } } static void ti99_8_parallel_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* parallel */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_PARALLEL; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 1; break; case DEVINFO_INT_CREATABLE: info->i = 1; break; case DEVINFO_INT_COUNT: info->i = 1; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_LOAD: info->load = device_load_ti99_4_pio; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti99_4_pio; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), ""); break; } } static void ti99_8_serial_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* serial */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_SERIAL; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 1; break; case DEVINFO_INT_CREATABLE: info->i = 1; break; case DEVINFO_INT_COUNT: info->i = 1; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_LOAD: info->load = device_load_ti99_4_rs232; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti99_4_rs232; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), ""); break; } } #if 0 static void ti99_8_quickload_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* quickload */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_QUICKLOAD; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 1; break; case DEVINFO_INT_CREATABLE: info->i = 1; break; case DEVINFO_INT_COUNT: info->i = 1; break; case DEVINFO_INT_RESET_ON_LOAD: info->i = 1; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_LOAD: info->load = device_load_ti99_hsgpl; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti99_hsgpl; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), ""); break; } } #endif static void ti99_8_memcard_getinfo(const device_class *devclass, UINT32 state, union devinfo *info) { /* memcard */ switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case DEVINFO_INT_TYPE: info->i = IO_MEMCARD; break; case DEVINFO_INT_READABLE: info->i = 1; break; case DEVINFO_INT_WRITEABLE: info->i = 1; break; case DEVINFO_INT_CREATABLE: info->i = 0; break; case DEVINFO_INT_COUNT: info->i = 1; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_INIT: info->init = device_init_smartmedia; break; case DEVINFO_PTR_LOAD: info->load = device_load_smartmedia; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_smartmedia; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), ""); break; } } SYSTEM_CONFIG_START(ti99_8) /* one cartridge port */ /* one cassette unit port */ /* Hex-bus disk controller: supports up to 4 floppy disk drives */ /* expansion port (similar to 99/4(a) - yet slightly different) */ CONFIG_DEVICE(ti99_8_cassette_getinfo) CONFIG_DEVICE(ti99_8_cartslot_getinfo) #if 1 CONFIG_DEVICE(ti99_8_floppy_getinfo) CONFIG_DEVICE(ti99_8_harddisk_getinfo) CONFIG_DEVICE(ti99_ide_harddisk_getinfo) CONFIG_DEVICE(ti99_8_parallel_getinfo) CONFIG_DEVICE(ti99_8_serial_getinfo) /*CONFIG_DEVICE(ti99_8_quickload_getinfo)*/ CONFIG_DEVICE(ti99_8_memcard_getinfo) #endif SYSTEM_CONFIG_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME */ COMP( 1983, ti99_8, 0, 0, ti99_8_60hz,ti99_8, ti99_8, ti99_8, "Texas Instruments", "TI-99/8 Computer (US)" , 0) COMP( 1983, ti99_8e, ti99_8, 0, ti99_8_50hz,ti99_8, ti99_8, ti99_8, "Texas Instruments", "TI-99/8 Computer (Europe)" , 0)