/* TI990/10 driver This driver boots the DX10 build tape and build a bootable system disk. I have been able to run a few programs (including most games from the "fun and games" tape), but I have been unable to perform system generation and install BASIC/COBOL/PASCAL. TODO : * programmer panel * emulate TILINE fully: timings, tiline timeout, possibly memory error * finish tape emulation (write support) * add additional devices as need appears (931 VDT, FD800, card reader, ASR/KSR, printer) * emulate 990/10A and 990/12 CPUs? * find out why the computer locks when executing ALGS and BASIC/COBOL/PASCAL installation */ /* CRU map: 990/10 CPU board: 1fa0-1fbe: map file CRU interface 1fc0-1fde: error interrupt register 1fe0-1ffe: control panel optional hardware (default configuration): 0000-001e: 733 ASR 0020-003e: PROM programmer 0040-005e: card reader 0060-007e: line printer 0080-00be: FD800 floppy disc 00c0-00ee: 913 VDT, or 911 VDT 0100-013e: 913 VDT #2, or 911 VDT 0140-017e: 913 VDT #3, or 911 VDT 1700-177e (0b00-0b7e, 0f00-0f7e): CI402 serial controller #0 (#1, #2) (for 931/940 VDT) (note that CRU base 1700 is used by the integrated serial controller in newer S300, S300A, 990/10A (and 990/5?) systems) 1f00-1f1e: CRU expander #1 interrupt register 1f20-1f3e: CRU expander #2 interrupt register 1f40-1f5e: TILINE coupler interrupt control #1-8 TPCS map: 1ff800: disk controller #1 (system disk) 1ff810->1ff870: extra disk controllers #2 through #8 1ff880 (1ff890): tape controller #1 (#2) 1ff900->1ff950: communication controllers #1 through #6 1ff980 (1ff990, 1ff9A0): CI403/404 serial controller #1 (#2, #3) (for 931/940 VDT) 1ffb00, 1ffb04, etc: ECC memory controller #1, #2, etc, diagnostic 1ffb10, 1ffb14, etc: cache memory controller #1, #2, etc, diagnostic interrupt map (default configuration): 0,1,2: CPU board 3: free 4: card reader 5: line clock 6: 733 ASR/KSR 7: FD800 floppy (or FD1000 floppy) 8: free 9: 913 VDT #3 10: 913 VDT #2 11: 913 VDT 12: free 13: hard disk 14 line printer 15: PROM programmer (actually not used) */ #include "driver.h" #include "cpu/tms9900/tms9900.h" #include "machine/ti990.h" #include "machine/990_hd.h" #include "machine/990_tap.h" #include "video/911_vdt.h" static MACHINE_RESET( ti990_10 ) { ti990_hold_load(); ti990_reset_int(); ti990_tpc_init(ti990_set_int9); ti990_hdc_init(ti990_set_int13); } static void ti990_10_line_interrupt(void) { vdt911_keyboard(0); ti990_line_interrupt(); } /*static void idle_callback(int state) { }*/ static void rset_callback(void) { ti990_cpuboard_reset(); vdt911_reset(); /* ... */ /* clear controller panel and smi fault LEDs */ } static void lrex_callback(void) { /* right??? */ ti990_hold_load(); } /* TI990/10 video emulation. We emulate a single VDT911 CRT terminal. */ static VIDEO_START( ti990_10 ) { const vdt911_init_params_t params = { char_1920, vdt911_model_US/*vdt911_model_UK*//*vdt911_model_French*//*vdt911_model_French*/ /*vdt911_model_German*//*vdt911_model_Swedish*//*vdt911_model_Norwegian*/ /*vdt911_model_Japanese*//*vdt911_model_Arabic*//*vdt911_model_FrenchWP*/, ti990_set_int10 }; vdt911_init_term(0, & params); } static VIDEO_UPDATE( ti990_10 ) { vdt911_refresh(bitmap, 0, 0, 0); return 0; } /* Memory map - see description above */ static ADDRESS_MAP_START(ti990_10_memmap, ADDRESS_SPACE_PROGRAM, 16) AM_RANGE(0x000000, 0x0fffff) AM_READWRITE(MRA16_RAM, MWA16_RAM) /* let's say we have 1MB of RAM */ AM_RANGE(0x100000, 0x1ff7ff) AM_READWRITE(MRA16_NOP, MWA16_NOP) /* free TILINE space */ AM_RANGE(0x1ff800, 0x1ff81f) AM_READWRITE(ti990_hdc_r, ti990_hdc_w) /* disk controller TPCS */ AM_RANGE(0x1ff820, 0x1ff87f) AM_READWRITE(MRA16_NOP, MWA16_NOP) /* free TPCS */ AM_RANGE(0x1ff880, 0x1ff89f) AM_READWRITE(ti990_tpc_r, ti990_tpc_w) /* tape controller TPCS */ AM_RANGE(0x1ff8a0, 0x1ffbff) AM_READWRITE(MRA16_NOP, MWA16_NOP) /* free TPCS */ AM_RANGE(0x1ffc00, 0x1fffff) AM_READWRITE(MRA16_ROM, MWA16_ROM) /* LOAD ROM */ ADDRESS_MAP_END /* CRU map */ static ADDRESS_MAP_START(ti990_10_writecru, ADDRESS_SPACE_IO, 8) AM_RANGE(0x80, 0x8f) AM_WRITE(vdt911_0_cru_w) AM_RANGE(0xfd0, 0xfdf) AM_WRITE(ti990_10_mapper_cru_w) AM_RANGE(0xfe0, 0xfef) AM_WRITE(ti990_10_eir_cru_w) AM_RANGE(0xff0, 0xfff) AM_WRITE(ti990_panel_write) ADDRESS_MAP_END static ADDRESS_MAP_START(ti990_10_readcru, ADDRESS_SPACE_IO, 8) AM_RANGE(0x10, 0x11) AM_READ(vdt911_0_cru_r) AM_RANGE(0x1fa, 0x1fb) AM_READ(ti990_10_mapper_cru_r) AM_RANGE(0x1fc, 0x1fd) AM_READ(ti990_10_eir_cru_r) AM_RANGE(0x1fe, 0x1ff) AM_READ(ti990_panel_read) ADDRESS_MAP_END static ti990_10reset_param reset_params = { /*idle_callback*/NULL, rset_callback, lrex_callback, ti990_ckon_ckof_callback, ti990_set_int2 }; static MACHINE_DRIVER_START(ti990_10) /* basic machine hardware */ /* TI990/10 CPU @ 4.0(???) MHz */ MDRV_CPU_ADD(TI990_10, 4000000) MDRV_CPU_CONFIG(reset_params) MDRV_CPU_PROGRAM_MAP(ti990_10_memmap, 0) MDRV_CPU_IO_MAP(ti990_10_readcru, ti990_10_writecru) /*MDRV_CPU_VBLANK_INT(NULL, 0)*/ MDRV_CPU_PERIODIC_INT(ti990_10_line_interrupt, 120/*or 100 in Europe*/) /* video hardware - we emulate a single 911 vdt display */ MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) /*MDRV_INTERLEAVE(interleave)*/ MDRV_MACHINE_RESET( ti990_10 ) /*MDRV_NVRAM_HANDLER( NULL )*/ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) /*MDRV_ASPECT_RATIO(num, den)*/ MDRV_SCREEN_SIZE(560, 280) MDRV_SCREEN_VISIBLE_AREA(0, 560-1, 0, /*250*/280-1) MDRV_GFXDECODE(vdt911_gfxdecodeinfo) MDRV_PALETTE_LENGTH(vdt911_palette_size) MDRV_COLORTABLE_LENGTH(vdt911_colortable_size) MDRV_PALETTE_INIT(vdt911) MDRV_VIDEO_START(ti990_10) /*MDRV_VIDEO_EOF(name)*/ MDRV_VIDEO_UPDATE(ti990_10) /* 911 VDT has a beep tone generator */ MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD(BEEP, 0) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_DRIVER_END /* ROM loading */ ROM_START(ti990_10) /*CPU memory space*/ #if 0 ROM_REGION16_BE(0x200000, REGION_CPU1,0) /* TI990/10 : older boot ROMs for floppy-disk */ ROM_LOAD16_BYTE("975383.31", 0x1FFC00, 0x100, CRC(64fcd040)) ROM_LOAD16_BYTE("975383.32", 0x1FFC01, 0x100, CRC(64277276)) ROM_LOAD16_BYTE("975383.29", 0x1FFE00, 0x100, CRC(af92e7bf)) ROM_LOAD16_BYTE("975383.30", 0x1FFE01, 0x100, CRC(b7b40cdc)) #elif 1 ROM_REGION16_BE(0x200000, REGION_CPU1,0) /* TI990/10 : newer "universal" boot ROMs */ ROM_LOAD16_BYTE("975383.45", 0x1FFC00, 0x100, CRC(391943c7) SHA1(bbd4da60b221d146542a6b547ae1570024e41b8a)) ROM_LOAD16_BYTE("975383.46", 0x1FFC01, 0x100, CRC(f40f7c18) SHA1(03613bbf2263a4335c25dfc63cf2878c06bfe280)) ROM_LOAD16_BYTE("975383.47", 0x1FFE00, 0x100, CRC(1ba571d8) SHA1(adaa18f149b643cc842fea8d7107ee868d6ffaf4)) ROM_LOAD16_BYTE("975383.48", 0x1FFE01, 0x100, CRC(8852b09e) SHA1(f0df2abb438716832c16ab111e475da3ae612673)) #else ROM_REGION16_BE(0x202000, REGION_CPU1,0) /* TI990/12 ROMs - actually incompatible with TI990/10, but I just wanted to disassemble them. */ ROM_LOAD16_BYTE("ti2025-7", 0x1FFC00, 0x1000, CRC(4824f89c)) ROM_LOAD16_BYTE("ti2025-8", 0x1FFC01, 0x1000, CRC(51fef543)) /* the other half of this ROM is not loaded - it makes no sense as TI990/12 machine code, as it is microcode... */ #endif /* VDT911 character definitions */ ROM_REGION(vdt911_chr_region_len, vdt911_chr_region, 0) ROM_END static DRIVER_INIT( ti990_10 ) { #if 0 /* load specific ti990/12 rom page */ const int page = 3; memmove(memory_region(REGION_CPU1)+0x1FFC00, memory_region(REGION_CPU1)+0x1FFC00+(page*0x400), 0x400); #endif vdt911_init(); } INPUT_PORTS_START(ti990_10) VDT911_KEY_PORTS INPUT_PORTS_END static void ti990_10_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 = 4; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_INIT: info->init = device_init_ti990_hd; break; case DEVINFO_PTR_LOAD: info->load = device_load_ti990_hd; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti990_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; } } static void ti990_10_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_TYPE: info->i = IO_CASSETTE; 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 = 4; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_PTR_INIT: info->init = device_init_ti990_tape; break; case DEVINFO_PTR_LOAD: info->load = device_load_ti990_tape; break; case DEVINFO_PTR_UNLOAD: info->unload = device_unload_ti990_tape; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), "tap"); break; } } SYSTEM_CONFIG_START(ti990_10) CONFIG_DEVICE(ti990_10_harddisk_getinfo) CONFIG_DEVICE(ti990_10_cassette_getinfo) SYSTEM_CONFIG_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME */ COMP( 1975, ti990_10, 0, 0, ti990_10, ti990_10, ti990_10, ti990_10, "Texas Instruments", "TI Model 990/10 Minicomputer System" , 0)