diff options
Diffstat (limited to 'src/mame/drivers/ti990_10.c')
-rw-r--r-- | src/mame/drivers/ti990_10.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/src/mame/drivers/ti990_10.c b/src/mame/drivers/ti990_10.c new file mode 100644 index 00000000000..21c0fe33010 --- /dev/null +++ b/src/mame/drivers/ti990_10.c @@ -0,0 +1,389 @@ +// license:GPL-2.0+ +// copyright-holders:Raphael Nabet +/* + 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 "emu.h" + +#include "cpu/tms9900/ti990_10.h" +#include "sound/beep.h" +#include "bus/ti99x/990_hd.h" +#include "bus/ti99x/990_tap.h" +#include "video/911_vdt.h" + + +class ti990_10_state : public driver_device +{ +public: + ti990_10_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) , + m_maincpu(*this, "maincpu"), + m_intlines(0), + m_ckon_state(0) { } + + device_t *m_terminal; + DECLARE_DRIVER_INIT(ti990_10); + virtual void machine_reset(); + virtual void video_start(); + + DECLARE_WRITE_LINE_MEMBER( key_interrupt ); + DECLARE_WRITE_LINE_MEMBER( line_interrupt ); + DECLARE_WRITE_LINE_MEMBER( tape_interrupt ); + void ti990_set_int_line(int line, int state); + WRITE_LINE_MEMBER(ti990_set_int13); + TIMER_CALLBACK_MEMBER(clear_load); + void ti990_hold_load(); + WRITE_LINE_MEMBER(ti990_ckon_ckof_callback); + READ8_MEMBER( ti990_panel_read ); + WRITE8_MEMBER( ti990_panel_write ); + + required_device<cpu_device> m_maincpu; + UINT16 m_intlines; + int m_ckon_state; +}; + + +/* + Interrupt priority encoder. Actually part of the CPU board. +*/ + +void ti990_10_state::ti990_set_int_line(int line, int state) +{ + int level; + + + if (state) + m_intlines |= (1 << line); + else + m_intlines &= ~ (1 << line); + + if (m_intlines) + { + for (level = 0; ! (m_intlines & (1 << level)); level++) + ; + m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, level); /* interrupt it, baby */ + } + else + m_maincpu->set_input_line(0, CLEAR_LINE); +} + + +WRITE_LINE_MEMBER(ti990_10_state::ti990_set_int13) +{ + ti990_set_int_line(13, state); +} + +/* + hold and debounce load line (emulation is inaccurate) +*/ + +TIMER_CALLBACK_MEMBER(ti990_10_state::clear_load) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); +} + +void ti990_10_state::ti990_hold_load() +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + machine().scheduler().timer_set(attotime::from_msec(100), timer_expired_delegate(FUNC(ti990_10_state::clear_load),this)); +} + +/* + line interrupt +*/ + +/* m_ckon_state: 1 if line clock active (RTCLR flip-flop on TI990/10 schematics - +SMI sheet 4) */ +WRITE_LINE_MEMBER(ti990_10_state::line_interrupt) +{ + // set_int10(state); + if (m_ckon_state) + ti990_set_int_line(5, 1); +} + +WRITE_LINE_MEMBER(ti990_10_state::ti990_ckon_ckof_callback) +{ + m_ckon_state = state; + if (! m_ckon_state) + ti990_set_int_line(5, 0); +} + + + +/* + Control panel emulation + + three panel types + * operator panel + * programmer panel + * MDU (external unit connected instead of the control panel, as seen in + 945401-9701 p. 2-5 though 2-15) + + Operator panel: + * Power led + * Fault led + * Off/On/Load switch + + Programmer panel: + * 16 status light, 32 switches, IDLE, RUN leds + * interface to a low-level debugger in ROMs + + * MDU: + * includes a programmer panel, a tape unit, and a few parts + (diagnostic tape, diagnostic ROMs, etc.) + + CRU output: + 0-7: lights 0-7 + 8: increment scan + 9: clear scan (according to 990 handbook) + A: run light (additionally sets all data LEDs to 1s, the scan count to 0b10 and enables the HALT/SIE switch) + B: fault light + C: Memory Error Interrupt clear + D: Start panel timer + E: Set SIE function (interrupt after 2 instructions are executed) + F: flag (according to 990 handbook) + + input : + 0-7: switches 0-7 (or data from MDU tape) + 8: scan count bit 1 + 9: scan count bit 0 + A: timer active + B: programmer panel not present or locked + C: char in MDU tape unit buffer? + D: unused? + E: if 0, MDU unit present + F: flag (according to 990 handbook) +*/ + +READ8_MEMBER( ti990_10_state::ti990_panel_read ) +{ + if (offset == 1) + return 0x48; + + return 0; +} + +WRITE8_MEMBER( ti990_10_state::ti990_panel_write ) +{ +} + + +void ti990_10_state::machine_reset() +{ + ti990_hold_load(); +} + +/* +void ti990_10_state::rset_callback) +{ + ti990_cpuboard_reset(); + + // clear controller panel and smi fault LEDs +} + +void ti990_10_state::lrex_callback) +{ + // right??? + ti990_hold_load(); +} +*/ + +/* + TI990/10 video emulation. + + We emulate a single VDT911 CRT terminal. +*/ + +void ti990_10_state::video_start() +{ + m_terminal = machine().device("vdt911"); +} + +WRITE_LINE_MEMBER(ti990_10_state::key_interrupt) +{ + // set_int10(state); +} + +/* + Memory map - see description above +*/ + +static ADDRESS_MAP_START(ti990_10_memmap, AS_PROGRAM, 16, ti990_10_state ) + + AM_RANGE(0x000000, 0x0fffff) AM_RAM /* let's say we have 1MB of RAM */ + AM_RANGE(0x100000, 0x1ff7ff) AM_NOP /* free TILINE space */ + AM_RANGE(0x1ff800, 0x1ff81f) AM_DEVREADWRITE("hdc", ti990_hdc_device, read, write) /* disk controller TPCS */ + AM_RANGE(0x1ff820, 0x1ff87f) AM_NOP /* free TPCS */ + AM_RANGE(0x1ff880, 0x1ff89f) AM_DEVREADWRITE("tpc", tap_990_device, read, write) /* tape controller TPCS */ + AM_RANGE(0x1ff8a0, 0x1ffbff) AM_NOP /* free TPCS */ + AM_RANGE(0x1ffc00, 0x1fffff) AM_ROM /* LOAD ROM */ + +ADDRESS_MAP_END + + +/* + CRU map +*/ + +static ADDRESS_MAP_START(ti990_10_io, AS_IO, 8, ti990_10_state ) + AM_RANGE(0x10, 0x11) AM_DEVREAD("vdt911", vdt911_device, cru_r) + AM_RANGE(0x80, 0x8f) AM_DEVWRITE("vdt911", vdt911_device, cru_w) + AM_RANGE(0x1fa, 0x1fb) AM_NOP // AM_READ(ti990_10_mapper_cru_r) + AM_RANGE(0x1fc, 0x1fd) AM_NOP // AM_READ(ti990_10_eir_cru_r) + AM_RANGE(0x1fe, 0x1ff) AM_READ(ti990_panel_read) + AM_RANGE(0xfd0, 0xfdf) AM_NOP // AM_WRITE(ti990_10_mapper_cru_w) + AM_RANGE(0xfe0, 0xfef) AM_NOP // AM_WRITE(ti990_10_eir_cru_w) + AM_RANGE(0xff0, 0xfff) AM_WRITE(ti990_panel_write) + +ADDRESS_MAP_END + +/* + Callback from the tape controller. +*/ +WRITE_LINE_MEMBER(ti990_10_state::tape_interrupt) +{ + // set_int9(state); +} + +static MACHINE_CONFIG_START( ti990_10, ti990_10_state ) + /* basic machine hardware */ + /* TI990/10 CPU @ 4.0(???) MHz */ + MCFG_TMS99xx_ADD("maincpu", TI990_10, 4000000, ti990_10_memmap, ti990_10_io ) + + // VDT 911 terminal + MCFG_DEVICE_ADD("vdt911", VDT911, 0) + MCFG_VDT911_KEYINT_HANDLER(WRITELINE(ti990_10_state, key_interrupt)) + MCFG_VDT911_LINEINT_HANDLER(WRITELINE(ti990_10_state, line_interrupt)) + + // Hard disk + MCFG_DEVICE_ADD("hdc", TI990_HDC, 0) + MCFG_TI990_HDC_INT_CALLBACK(WRITELINE(ti990_10_state, ti990_set_int13)) + + // Tape controller + MCFG_DEVICE_ADD("tpc", TI990_TAPE_CTRL, 0) + MCFG_TI990_TAPE_INT_HANDLER(WRITELINE(ti990_10_state, tape_interrupt)) +MACHINE_CONFIG_END + + +/* + ROM loading +*/ +ROM_START(ti990_10) + + /*CPU memory space*/ +#if 0 + + ROM_REGION16_BE(0x200000, "maincpu",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, "maincpu",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, "maincpu",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, ROMREGION_ERASEFF) + +ROM_END + +DRIVER_INIT_MEMBER(ti990_10_state,ti990_10) +{ +#if 0 + /* load specific ti990/12 rom page */ + const int page = 3; + + memmove(memregion("maincpu")->base()+0x1FFC00, memregion("maincpu")->base()+0x1FFC00+(page*0x400), 0x400); +#endif +} + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ +COMP( 1975, ti990_10, 0, 0, ti990_10, 0, ti990_10_state, ti990_10, "Texas Instruments", "TI Model 990/10 Minicomputer System" , MACHINE_NOT_WORKING ) |