1 // license:LGPL-2.1+
2 // copyright-holders:Michael Zapf
3 /****************************************************************************
4
5 The MESS TI-99/8 emulation driver
6
7 The TI-99/8 was the envisaged successor to the TI-99/4A but never passed
8 its prototype state. Only a few dozen consoles were built. The ROMs
9 were not even finalized, so the few available consoles have different
10 operating system versions and capabilities.
11
12
13 Characteristics
14 ---------------
15
16 Name: "Texas Instruments Computer TI-99/8" (no "Home")
17
18 Unofficial nickname: "Armadillo"
19
20 CPU: Single-CPU system using a TMS9995, but as a variant named MP9537. This
21 variant does not offer on-chip RAM or decrementer.
22
23 Video: TMS9118 Video Display Processor with 16 KiB RAM. The 9118 has the
24 same capabilities as the 9918/28 in the TI-99/4A, except for the
25 missing GROM clock (which must be provided separately) and the
26 different DRAM type (2 chips TMS 4416 16K*4). Delivers a 60 Hz
27 interrupt to the CPU via the PSI.
28
29 Keyboard: 50-key keyboard, slightly different to the TI-99/4A, but also with
30 modifiers Control, Function, Shift, Caps Lock. Connects to the TMS 9901
31 PSI like in the TI-99/4A, but the pin assignment and key matrix
32 are different:
33 - P0-P3: column select
34 - INT6*-INT11*: row inputs (INT6* is only used for joystick fire)
35
36 Cassette: Identical to TI-99/4A, except that the CS2 unit is not implemented
37
38 Sound: SN94624 as used in the TI-99/4A
39
40 Speech: TMS5200C, a rare variant of the TMS52xx family. Compatible to the
41 speech data for the separate speech synthesizer for the TI-99/4A.
42 Speech ROMs CD2325A, CD2326A (total 128K*1)
43
44 ROM: TMS4764 (8K*8), called "ROM0" in the specifications [1]
45 TMS47256 (32K*8), called "ROM1" [1]
46 TMS47128 (16K*8), "P-Code ROM" (only available in late prototypes)
47 See below for contents
48
49 GROMs: TI-specific ROM circuits with internal address counter and 6 KiB
50 capacity (see grom.c)
51 3 GROMs (system GROMs, access via port at logical address F830)
52 8 GROMs (Pascal / Text-to-speech GROMs, port at logical address F840)
53 8 GROMs (Pascal GROMs, port at logical address F850)
54 3 GROMs (Pascal GROMs, access via port at logical address F860)
55 (total of 132 KiB GROM)
56
57 RAM: 1 TMS4016 (SRAM 2K*8)
58 8 TMS4164 (DRAM 64K*1)
59
60 PSI: (programmable system interface) TMS9901 with connections to
61 keyboard, joystick port, cassette port, and external interrupt lines
62 (video, peripheral devices)
63
64 External connectors:
65 - Joystick port (compatible to TI-99/4A joystick slot)
66 - Cassette port
67 - Cartridge port (compatible to TI-99/4A cartridge slot, but vertically
68 orientated, so cartridges are plugged in from the top)
69 - I/O port (not compatible to TI-99/4A I/O port, needs a special P-Box
70 card called "Armadillo interface")
71 - Hexbus port (new peripheral system, also seen with later TI designs)
72 - Video port (composite)
73
74 Custom chips: Five custom chips contain mapping and selection logic
75 - "Vaquerro": Logical address space decoder
76 - "Mofetta" : Physical address space decoder
77 - "Amigo" : Mapper
78 - "Pollo" : DRAM controller
79 - "Oso" : Hexbus interface
80
81 Modes:
82 - Compatibility mode (TI-99/4A mode): Memory-mapped devices are
83 placed at the same location as found in the TI-99/4A, thereby
84 providing good downward compatibility.
85 The console starts up in compatibility mode.
86 - Native mode (Armadillo mode): Devices are located at positions above
87 0xF000 that allow for a contiguous usage of memory.
88
89 Mapper
90 ------
91 The mapper uses 4K pages (unlike the Geneve mapper with 8K pages) which
92 are defined by a 32 bit word. The address bits A0-A3 serve as the page
93 index, whereas bits A4-A15 are the offset in the page.
94 From the 32 bits, 24 bits define the physical address, so this allows for
95 a maximum of 16 MiB of mapped-addressable memory.
96
97 See more about the mapper in the file 998board.cpp
98
99
100 Availability of ROMs and documentation
101 --------------------------------------
102 By written consent, TI granted free use of all software and documentation
103 concerning the TI-99/8, including all specifications, ROMs, and source code
104 of ROMs.
105
106
107 Acknowledgements
108 ----------------
109 Special thanks go to Ciro Barile of the TI99 Italian User Club
110 (www.ti99iuc.it): By his courtesy we have a consistent dump of ROMs for
111 one of the most evolved versions of the TI-99/8 with
112
113 - complete GROM set (with Pascal)
114 - complete ROM set (with Hexbus DSR and TTS)
115 - complete speech ROM set
116
117 Also, by applying test programs on his real console, many unclear
118 specifications were resolved.
119
120
121 References
122 ----------
123 [1] Texas Instruments: Armadillo Product Specifications, July 1983
124 [2] Source code (Assembler and GPL) of the TI-99/8 ROMs and GROMs
125 [3] Schematics of the TI-99/8
126
127
128 Implementation
129 --------------
130 Initial version by Raphael Nabet, 2003.
131
132 February 2012: Rewritten as class [Michael Zapf]
133 November 2013: Included new dumps [Michael Zapf]
134
135 ===========================================================================
136 Known Issues (MZ, 2019-05-10)
137
138 KEEP IN MIND THAT TEXAS INSTRUMENTS NEVER RELEASED THE TI-99/8 AND THAT
139 THERE ARE ONLY A FEW PROTOTYPES OF THE TI-99/8 AVAILABLE. ALL SOFTWARE
140 MUST BE ASSUMED TO HAVE REMAINED IN A PRELIMINARY STATE.
141
142 - TI-99/4A disk controllers cannot be used with the TI-99/8 in Extended Basic II.
143 In the 99/8, the peripheral access block (PAB, set of data defining the
144 access to the device, like floppy) may be located in CPU RAM, while the
145 controllers of the 99/4A expect the PAB to be in video RAM only. Exbasic II
146 sets up the PAB in CPU RAM, which leads to a crash. Other cartridges from
147 the 99/4A certainly use video RAM, and so the disk controller works.
148 Therefore, the Hexbus floppy drive HX5102 is recommended for use with the
149 TI-99/8. You do not even need to attach the Peripheral Box.
150
151 mame ti99_8 -hexbus hx5102 -flop1 somedisk.dsk
152
153 - Multiple cartridges are not shown in the startup screen; only one
154 cartridge is presented. You have to manually select the cartridges with the
155 dip switch.
156
157 - SAVE and OLD MINIMEM do not work properly in XB II. It seems as if the
158 mapper shadows the NVRAM of the cartridge. You will lose the contents when
159 you turn off the machine.
160
161 *****************************************************************************/
162
163
164 #include "emu.h"
165 #include "cpu/tms9900/tms9995.h"
166
167 #include "sound/sn76496.h"
168 #include "machine/tms9901.h"
169 #include "machine/tmc0430.h"
170 #include "imagedev/cassette.h"
171
172 #include "bus/ti99/internal/998board.h"
173 #include "bus/ti99/gromport/gromport.h"
174 #include "bus/hexbus/hexbus.h"
175
176 #include "bus/ti99/joyport/joyport.h"
177 #include "bus/ti99/internal/ioport.h"
178
179 #include "softlist.h"
180 #include "speaker.h"
181
182 // Debugging
183 #define LOG_WARN (1U<<1) // Warnings
184 #define LOG_CONFIG (1U<<2) // Configuration
185 #define LOG_READY (1U<<3)
186 #define LOG_INTERRUPTS (1U<<4)
187 #define LOG_CRU (1U<<5)
188 #define LOG_CRUREAD (1U<<6)
189 #define LOG_RESETLOAD (1U<<7)
190
191 #define VERBOSE ( LOG_CONFIG | LOG_WARN | LOG_RESETLOAD )
192
193 #include "logmacro.h"
194
195 /*
196 READY bits.
197 */
198 enum
199 {
200 READY_GROM = 1,
201 READY_MAPPER = 2,
202 READY_PBOX = 4,
203 READY_SOUND = 8,
204 READY_CART = 16,
205 READY_SPEECH = 32,
206 READY_MAINBOARD = 64
207 };
208
209 class ti99_8_state : public driver_device
210 {
211 public:
ti99_8_state(const machine_config & mconfig,device_type type,const char * tag)212 ti99_8_state(const machine_config &mconfig, device_type type, const char *tag)
213 : driver_device(mconfig, type, tag),
214 m_cpu(*this, "maincpu"),
215 m_tms9901(*this, TI998_TMS9901_TAG),
216 m_gromport(*this, TI99_GROMPORT_TAG),
217 m_ioport(*this, TI99_IOPORT_TAG),
218 m_mainboard(*this, TI998_MAINBOARD_TAG),
219 m_joyport(*this, TI_JOYPORT_TAG),
220 m_cassette(*this, "cassette"),
221 m_keyboard(*this, "COL%u", 0U)
222 {
223 }
224
225 void ti99_8(machine_config &config);
226 void ti99_8_60hz(machine_config &config);
227 void ti99_8_50hz(machine_config &config);
228
229 // Lifecycle
230 void driver_start() override;
231 void driver_reset() override;
232
233 private:
234 // Machine management
235 DECLARE_MACHINE_START(ti99_8);
236 DECLARE_MACHINE_RESET(ti99_8);
237
238 // Processor connections with the main board
239 uint8_t cruread(offs_t offset);
240 void cruwrite(offs_t offset, uint8_t data);
241 void external_operation(offs_t offset, uint8_t data);
242 DECLARE_WRITE_LINE_MEMBER( clock_out );
243
244 // Connections from outside towards the CPU (callbacks)
245 DECLARE_WRITE_LINE_MEMBER( console_ready );
246 DECLARE_WRITE_LINE_MEMBER( console_reset );
247 DECLARE_WRITE_LINE_MEMBER( cpu_hold );
248 DECLARE_WRITE_LINE_MEMBER( notconnected );
249
250 // GROM clock (coming from Vaquerro)
251 DECLARE_WRITE_LINE_MEMBER( gromclk_in );
252
253 // Connections with the system interface chip 9901
254 DECLARE_WRITE_LINE_MEMBER( extint );
255 DECLARE_WRITE_LINE_MEMBER( video_interrupt );
256
257 // Connections with the system interface TMS9901
258 uint8_t psi_input(offs_t offset);
259 DECLARE_WRITE_LINE_MEMBER(keyC0);
260 DECLARE_WRITE_LINE_MEMBER(keyC1);
261 DECLARE_WRITE_LINE_MEMBER(keyC2);
262 DECLARE_WRITE_LINE_MEMBER(keyC3);
263 DECLARE_WRITE_LINE_MEMBER(audio_gate);
264 DECLARE_WRITE_LINE_MEMBER(cassette_output);
265 DECLARE_WRITE_LINE_MEMBER(cassette_motor);
266 void tms9901_interrupt(offs_t offset, uint8_t data);
267
268 void crumap(address_map &map);
269 void memmap(address_map &map);
270 void memmap_setaddress(address_map &map);
271
272 // Keyboard support
273 void set_keyboard_column(int number, int data);
274 int m_keyboard_column;
275
276 // READY handling
277 int m_ready_old;
278
279 // Latch for 9901 INT2, INT1 lines
280 int m_int1;
281 int m_int2;
282
283 // Connected devices
284 required_device<tms9995_device> m_cpu;
285 required_device<tms9901_device> m_tms9901;
286 required_device<bus::ti99::gromport::gromport_device> m_gromport;
287 required_device<bus::ti99::internal::ioport_device> m_ioport;
288 required_device<bus::ti99::internal::mainboard8_device> m_mainboard;
289 required_device<bus::ti99::joyport::joyport_device> m_joyport;
290 required_device<cassette_image_device> m_cassette;
291
292 required_ioport_array<14> m_keyboard;
293 };
294
295 /*
296 Memory map. We have a configurable mapper, so we need to delegate the
297 job to the mapper completely.
298 */
memmap(address_map & map)299 void ti99_8_state::memmap(address_map &map)
300 {
301 map(0x0000, 0xffff).rw(TI998_MAINBOARD_TAG, FUNC(bus::ti99::internal::mainboard8_device::read), FUNC(bus::ti99::internal::mainboard8_device::write));
302 }
303
memmap_setaddress(address_map & map)304 void ti99_8_state::memmap_setaddress(address_map &map)
305 {
306 map(0x0000, 0xffff).w(TI998_MAINBOARD_TAG, FUNC(bus::ti99::internal::mainboard8_device::setaddress));
307 }
308
309 /*
310 CRU map - see description above
311 The TMS9901 is fully decoded according to the specification, so we only
312 have 32 bits for it; the rest goes to the CRU bus
313 (decoded by the "Vaquerro" chip, signal NNOICS*)
314 */
315
crumap(address_map & map)316 void ti99_8_state::crumap(address_map &map)
317 {
318 map(0x0000, 0x2fff).rw(FUNC(ti99_8_state::cruread), FUNC(ti99_8_state::cruwrite));
319 map(0x0000, 0x003f).rw(m_tms9901, FUNC(tms9901_device::read), FUNC(tms9901_device::write));
320 }
321
322 /* ti99/8 : 54-key keyboard */
323 static INPUT_PORTS_START(ti99_8)
324
325 /* 16 ports for keyboard and joystick */
326 PORT_START("COL0") /* col 0 */
PORT_CODE(KEYCODE_CAPSLOCK)327 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ALPHA LOCK") PORT_CODE(KEYCODE_CAPSLOCK)
328 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FCTN") PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT)
329 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL)
330 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LSHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
331 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
332
333 PORT_START("COL1") /* col 1 */
334 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 ! DEL") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
335 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("q Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
336 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("a A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
337 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("z Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
338 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
339
340 PORT_START("COL2") /* col 2 */
341 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @ INS") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
342 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("w W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
343 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("s S (LEFT)") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
344 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("x X (DOWN)") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
345 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
346
347 PORT_START("COL3") /* col 3 */
348 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
349 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("e E (UP)") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
350 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("d D (RIGHT)") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
351 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("c C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
352 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
353
354 PORT_START("COL4") /* col 4 */
355 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $ CLEAR") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
356 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("r R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
357 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("f F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
358 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("v V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
359 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
360
361 PORT_START("COL5") /* col 5 */
362 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 % BEGIN") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
363 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("t T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
364 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("g G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
365 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("b B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
366 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
367
368 PORT_START("COL6") /* col 6 */
369 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^ PROC'D") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
370 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
371 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
372 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
373 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
374
375 PORT_START("COL7") /* col 7 */
376 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 & AID") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
377 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
378 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
379 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
380 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
381
382 PORT_START("COL8") /* col 8 */
383 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 * REDO") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
384 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
385 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
386 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
387 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
388
389 PORT_START("COL9") /* col 9 */
390 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 ( BACK") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
391 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
392 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
393 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
394 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
395
396 PORT_START("COL10") /* col 10 */
397 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
398 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
399 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
400 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
401 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
402
403 PORT_START("COL11") /* col 11 */
404 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= + QUIT") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
405 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
406 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
407 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RSHIFT") PORT_CODE(KEYCODE_RSHIFT)
408 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
409
410 PORT_START("COL12") /* col 12 */
411 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
412 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
413 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
414 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(SPACE)") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
415 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
416
417 PORT_START("COL13") /* col 13 */
418 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
419 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('`') PORT_CHAR('~')
420 PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED)
421
422 INPUT_PORTS_END
423
424
425 uint8_t ti99_8_state::cruread(offs_t offset)
426 {
427 LOGMASKED(LOG_CRUREAD, "read access to CRU address %04x\n", offset);
428 uint8_t value = 0;
429
430 // Let the mapper, the gromport, and the p-box decide whether they want
431 // to change the value at the CRU address
432 m_mainboard->crureadz(offset<<1, &value);
433 m_gromport->crureadz(offset<<1, &value);
434 m_ioport->crureadz(offset<<1, &value);
435
436 LOGMASKED(LOG_CRU, "CRU %04x -> %x\n", offset<<1, value);
437 return value;
438 }
439
cruwrite(offs_t offset,uint8_t data)440 void ti99_8_state::cruwrite(offs_t offset, uint8_t data)
441 {
442 LOGMASKED(LOG_CRU, "CRU %04x <- %x\n", offset<<1, data);
443 m_mainboard->cruwrite(offset<<1, data);
444 m_gromport->cruwrite(offset<<1, data);
445 m_ioport->cruwrite(offset<<1, data);
446 }
447
448 /***************************************************************************
449 TI99/8-specific tms9901 I/O handlers
450 These methods are callbacks from the TMS9901 system interface. That is,
451 they deliver the values queried via the TMS9901, and they represent
452 console functions which are under control of the TMS9901 (like the
453 keyboard column selection.)
454 ***************************************************************************/
455
psi_input(offs_t offset)456 uint8_t ti99_8_state::psi_input(offs_t offset)
457 {
458 switch (offset)
459 {
460 case tms9901_device::INT1:
461 return (m_int1==CLEAR_LINE)? 1 : 0;
462 case tms9901_device::INT2:
463 return (m_int2==CLEAR_LINE)? 1 : 0;
464
465 case tms9901_device::INT6:
466 if (m_keyboard_column >= 14)
467 return BIT(m_joyport->read_port(),0);
468
469 case tms9901_device::INT7_P15:
470 if (m_keyboard_column >= 14)
471 return BIT(m_joyport->read_port(),4);
472
473 case tms9901_device::INT8_P14:
474 if (m_keyboard_column >= 14)
475 return BIT(m_joyport->read_port(),1);
476
477 case tms9901_device::INT9_P13:
478 if (m_keyboard_column >= 14)
479 return BIT(m_joyport->read_port(),2);
480
481 case tms9901_device::INT10_P12:
482 if (m_keyboard_column >= 14)
483 return BIT(m_joyport->read_port(),3);
484
485 // return for last 5 cases if column<14
486 return BIT(m_keyboard[m_keyboard_column]->read(), offset-tms9901_device::INT6);
487
488 case tms9901_device::INT11_P11:
489 return (m_cassette->input() > 0);
490
491 default:
492 return 1;
493 }
494 }
495
496 /*
497 WRITE key column select (P2-P4), TI-99/8
498 */
set_keyboard_column(int number,int data)499 void ti99_8_state::set_keyboard_column(int number, int data)
500 {
501 if (data != 0)
502 m_keyboard_column |= 1 << number;
503 else
504 m_keyboard_column &= ~(1 << number);
505
506 if (m_keyboard_column >= 14)
507 {
508 m_joyport->write_port(m_keyboard_column - 13);
509 }
510 }
511
WRITE_LINE_MEMBER(ti99_8_state::keyC0)512 WRITE_LINE_MEMBER( ti99_8_state::keyC0 )
513 {
514 set_keyboard_column(0, state);
515 }
516
WRITE_LINE_MEMBER(ti99_8_state::keyC1)517 WRITE_LINE_MEMBER( ti99_8_state::keyC1 )
518 {
519 set_keyboard_column(1, state);
520 }
521
WRITE_LINE_MEMBER(ti99_8_state::keyC2)522 WRITE_LINE_MEMBER( ti99_8_state::keyC2 )
523 {
524 set_keyboard_column(2, state);
525 }
526
WRITE_LINE_MEMBER(ti99_8_state::keyC3)527 WRITE_LINE_MEMBER( ti99_8_state::keyC3 )
528 {
529 set_keyboard_column(3, state);
530 }
531
532 /*
533 Control cassette tape unit motor (P6)
534 */
WRITE_LINE_MEMBER(ti99_8_state::cassette_motor)535 WRITE_LINE_MEMBER( ti99_8_state::cassette_motor )
536 {
537 m_cassette->change_state(state==ASSERT_LINE? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
538 }
539
540 /*
541 Audio gate (P8)
542 Set to 1 before using tape: this enables the mixing of tape input sound
543 with computer sound.
544 We do not really need to emulate this as the tape recorder generates sound
545 on its own.
546 */
WRITE_LINE_MEMBER(ti99_8_state::audio_gate)547 WRITE_LINE_MEMBER( ti99_8_state::audio_gate )
548 {
549 }
550
551 /*
552 Tape output (P9)
553 I think polarity is correct, but don't take my word for it.
554 */
WRITE_LINE_MEMBER(ti99_8_state::cassette_output)555 WRITE_LINE_MEMBER( ti99_8_state::cassette_output )
556 {
557 m_cassette->output(state==ASSERT_LINE? +1 : -1);
558 }
559
tms9901_interrupt(offs_t offset,uint8_t data)560 void ti99_8_state::tms9901_interrupt(offs_t offset, uint8_t data)
561 {
562 m_cpu->set_input_line(INT_9995_INT1, data);
563 }
564
565 /*****************************************************************************/
566
567 /*
568 set the state of TMS9901's INT2 (called by the VDP)
569 */
WRITE_LINE_MEMBER(ti99_8_state::video_interrupt)570 WRITE_LINE_MEMBER( ti99_8_state::video_interrupt )
571 {
572 LOGMASKED(LOG_INTERRUPTS, "VDP int 2 on tms9901, level=%02x\n", state);
573 m_int2 = (line_state)state;
574 m_tms9901->set_int_line(2, state);
575 }
576
577 /***********************************************************
578 Links to external devices
579 ***********************************************************/
580
581 /*
582 Propagate READY signals to the CPU.
583 */
console_ready(int state)584 void ti99_8_state::console_ready(int state)
585 {
586 if (m_ready_old != state)
587 LOGMASKED(LOG_READY, "READY = %d\n", state);
588 m_ready_old = (line_state)state;
589 m_cpu->ready_line(state);
590 }
591
592 /*
593 Enqueue a RESET signal.
594 */
WRITE_LINE_MEMBER(ti99_8_state::console_reset)595 WRITE_LINE_MEMBER( ti99_8_state::console_reset )
596 {
597 LOGMASKED(LOG_RESETLOAD, "Incoming RESET line = %d\n", state);
598 if (machine().phase() != machine_phase::INIT)
599 {
600 // RESET the 9901
601 m_tms9901->rst1_line(state);
602
603 // Pull up the CRUS and PTGEN lines (9901 outputs have been deactivated, pull-up resistors on the board show effect)
604 m_mainboard->crus_in(true); // assert
605 m_mainboard->ptgen_in(true); // clear
606
607 // Setting ready to false so that automatic wait states are enabled
608 m_cpu->ready_line(CLEAR_LINE);
609 m_cpu->reset_line(ASSERT_LINE);
610
611 // Send RESET to the IOPort
612 m_ioport->reset_in(state);
613 }
614 }
615
616 /*
617 The HOLD line leading to the CPU entering the HOLD state.
618 */
WRITE_LINE_MEMBER(ti99_8_state::cpu_hold)619 WRITE_LINE_MEMBER( ti99_8_state::cpu_hold )
620 {
621 LOGMASKED(LOG_INTERRUPTS, "Incoming HOLD line = %d\n", state);
622 m_cpu->hold_line(state);
623 }
624
WRITE_LINE_MEMBER(ti99_8_state::extint)625 WRITE_LINE_MEMBER( ti99_8_state::extint )
626 {
627 LOGMASKED(LOG_INTERRUPTS, "EXTINT level = %02x\n", state);
628 m_int1 = (line_state)state;
629 m_tms9901->set_int_line(1, state);
630 }
631
WRITE_LINE_MEMBER(ti99_8_state::notconnected)632 WRITE_LINE_MEMBER( ti99_8_state::notconnected )
633 {
634 LOGMASKED(LOG_INTERRUPTS, "Setting a not connected line ... ignored\n");
635 }
636
external_operation(offs_t offset,uint8_t data)637 void ti99_8_state::external_operation(offs_t offset, uint8_t data)
638 {
639 static char const *const extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" };
640 if (offset == IDLE_OP) return;
641 else
642 LOGMASKED(LOG_WARN, "External operation %s not implemented on TI-99/8 board\n", extop[offset]);
643 }
644
645 /*
646 Clock line from the CPU. Used to control wait state generation.
647 */
WRITE_LINE_MEMBER(ti99_8_state::clock_out)648 WRITE_LINE_MEMBER( ti99_8_state::clock_out )
649 {
650 m_tms9901->phi_line(state);
651 m_mainboard->clock_in(state);
652 }
653
driver_start()654 void ti99_8_state::driver_start()
655 {
656 // Need to configure the speech ROM for inverse bit order
657 // speechrom_device* mem = subdevice<speechrom_device>(TI998_SPEECHROM_REG);
658 // mem->set_reverse_bit_order(true);
659
660 save_item(NAME(m_keyboard_column));
661 save_item(NAME(m_ready_old));
662 save_item(NAME(m_int1));
663 save_item(NAME(m_int2));
664 }
665
driver_reset()666 void ti99_8_state::driver_reset()
667 {
668 m_cpu->hold_line(CLEAR_LINE);
669
670 // Pulling down the line on RESET configures the CPU to insert one wait
671 // state on external memory accesses
672 // m_cpu->ready_line(ASSERT_LINE);
673
674 // m_gromport->set_grom_base(0x9800, 0xfff1);
675
676 // Clear INT1 and INT2 latch
677 m_int1 = CLEAR_LINE;
678 m_int2 = CLEAR_LINE;
679 console_reset(ASSERT_LINE);
680 console_reset(CLEAR_LINE);
681 }
682
ti99_8(machine_config & config)683 void ti99_8_state::ti99_8(machine_config& config)
684 {
685 using namespace bus::ti99::internal;
686 // basic machine hardware */
687 // TMS9995-MP9537 CPU @ 10.7 MHz
688 // MP9537 mask: This variant of the TMS9995 does not contain on-chip RAM
689 TMS9995_MP9537(config, m_cpu, XTAL(10'738'635));
690 m_cpu->set_addrmap(AS_PROGRAM, &ti99_8_state::memmap);
691 m_cpu->set_addrmap(AS_IO, &ti99_8_state::crumap);
692 m_cpu->set_addrmap(tms9995_device::AS_SETADDRESS, &ti99_8_state::memmap_setaddress);
693 m_cpu->extop_cb().set(FUNC(ti99_8_state::external_operation));
694 m_cpu->clkout_cb().set(FUNC(ti99_8_state::clock_out));
695 m_cpu->holda_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::holda_line));
696
697 // 9901 configuration
698 TMS9901(config, m_tms9901, 0);
699 m_tms9901->read_cb().set(FUNC(ti99_8_state::psi_input));
700 m_tms9901->p_out_cb(0).set(FUNC(ti99_8_state::keyC0));
701 m_tms9901->p_out_cb(1).set(FUNC(ti99_8_state::keyC1));
702 m_tms9901->p_out_cb(2).set(FUNC(ti99_8_state::keyC2));
703 m_tms9901->p_out_cb(3).set(FUNC(ti99_8_state::keyC3));
704 m_tms9901->p_out_cb(4).set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::crus_in));
705 m_tms9901->p_out_cb(5).set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptgen_in));
706 m_tms9901->p_out_cb(6).set(FUNC(ti99_8_state::cassette_motor));
707 m_tms9901->p_out_cb(8).set(FUNC(ti99_8_state::audio_gate));
708 m_tms9901->p_out_cb(9).set(FUNC(ti99_8_state::cassette_output));
709 m_tms9901->intreq_cb().set(FUNC(ti99_8_state::tms9901_interrupt));
710
711 // Mainboard with custom chips
712 TI99_MAINBOARD8(config, m_mainboard, 0);
713 m_mainboard->ready_cb().set(FUNC(ti99_8_state::console_ready));
714 m_mainboard->reset_cb().set(FUNC(ti99_8_state::console_reset));
715 m_mainboard->hold_cb().set(FUNC(ti99_8_state::cpu_hold));
716
717 // Cartridge port
718 TI99_GROMPORT(config, m_gromport, 0, ti99_gromport_options_998, "single").extend();
719 m_gromport->ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::system_grom_ready));
720 m_gromport->reset_cb().set(FUNC(ti99_8_state::console_reset));
721
722 // RAM
723 RAM(config, TI998_SRAM_TAG).set_default_size("2K").set_default_value(0);
724 RAM(config, TI998_DRAM_TAG).set_default_size("64K").set_default_value(0);
725
726 // Software list
727 SOFTWARE_LIST(config, "cart_list_ti99").set_original("ti99_cart");
728
729 // I/O port
730 TI99_IOPORT(config, m_ioport, 0, ti99_ioport_options_plain, nullptr);
731 m_ioport->extint_cb().set(FUNC(ti99_8_state::extint));
732 m_ioport->ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::pbox_ready));
733
734 // Hexbus
735 HEXBUS(config, TI998_HEXBUS_TAG, 0, hexbus_options, nullptr);
736
737 // Sound hardware
738 SPEAKER(config, "sound_out").front_center();
739 sn76496_device& soundgen(SN76496(config, TI998_SOUNDCHIP_TAG, 3579545));
740 soundgen.ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::sound_ready));
741 soundgen.add_route(ALL_OUTPUTS, "sound_out", 0.75);
742
743 // Speech hardware
744 // Note: SPEECHROM uses its tag for referencing the region
745 SPEECHROM(config, TI998_SPEECHROM_REG, 0).set_reverse_bit_order(true);
746 SPEAKER(config, "speech_out").front_center();
747
748 cd2501ecd_device& vsp(CD2501ECD(config, TI998_SPEECHSYN_TAG, 640000L));
749 vsp.ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::speech_ready));
750 vsp.set_speechrom_tag(TI998_SPEECHROM_REG);
751 vsp.add_route(ALL_OUTPUTS, "speech_out", 0.50);
752
753 // Cassette drive
754 SPEAKER(config, "cass_out").front_center();
755 CASSETTE(config, "cassette", 0).add_route(ALL_OUTPUTS, "cass_out", 0.25);
756
757 // GROM library
758 using namespace bus::ti99::internal;
759 TMC0430(config, TI998_SYSGROM0_TAG, TI998_SYSGROM_REG, 0x0000, 0).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::system_grom_ready));
760 TMC0430(config, TI998_SYSGROM1_TAG, TI998_SYSGROM_REG, 0x2000, 1).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::system_grom_ready));
761 TMC0430(config, TI998_SYSGROM2_TAG, TI998_SYSGROM_REG, 0x4000, 2).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::system_grom_ready));
762
763 TMC0430(config, TI998_GLIB10_TAG, TI998_GROMLIB1_REG, 0x0000, 0).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
764 TMC0430(config, TI998_GLIB11_TAG, TI998_GROMLIB1_REG, 0x2000, 1).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
765 TMC0430(config, TI998_GLIB12_TAG, TI998_GROMLIB1_REG, 0x4000, 2).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
766 TMC0430(config, TI998_GLIB13_TAG, TI998_GROMLIB1_REG, 0x6000, 3).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
767 TMC0430(config, TI998_GLIB14_TAG, TI998_GROMLIB1_REG, 0x8000, 4).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
768 TMC0430(config, TI998_GLIB15_TAG, TI998_GROMLIB1_REG, 0xa000, 5).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
769 TMC0430(config, TI998_GLIB16_TAG, TI998_GROMLIB1_REG, 0xc000, 6).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
770 TMC0430(config, TI998_GLIB17_TAG, TI998_GROMLIB1_REG, 0xe000, 7).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::ptts_grom_ready));
771
772 TMC0430(config, TI998_GLIB20_TAG, TI998_GROMLIB2_REG, 0x0000, 0).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
773 TMC0430(config, TI998_GLIB21_TAG, TI998_GROMLIB2_REG, 0x2000, 1).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
774 TMC0430(config, TI998_GLIB22_TAG, TI998_GROMLIB2_REG, 0x4000, 2).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
775 TMC0430(config, TI998_GLIB23_TAG, TI998_GROMLIB2_REG, 0x6000, 3).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
776 TMC0430(config, TI998_GLIB24_TAG, TI998_GROMLIB2_REG, 0x8000, 4).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
777 TMC0430(config, TI998_GLIB25_TAG, TI998_GROMLIB2_REG, 0xa000, 5).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
778 TMC0430(config, TI998_GLIB26_TAG, TI998_GROMLIB2_REG, 0xc000, 6).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
779 TMC0430(config, TI998_GLIB27_TAG, TI998_GROMLIB2_REG, 0xe000, 7).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p8_grom_ready));
780
781 TMC0430(config, TI998_GLIB30_TAG, TI998_GROMLIB3_REG, 0x0000, 0).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p3_grom_ready));
782 TMC0430(config, TI998_GLIB31_TAG, TI998_GROMLIB3_REG, 0x2000, 1).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p3_grom_ready));
783 TMC0430(config, TI998_GLIB32_TAG, TI998_GROMLIB3_REG, 0x4000, 2).ready_cb().set(TI998_MAINBOARD_TAG, FUNC(mainboard8_device::p3_grom_ready));
784
785 // Joystick port
786 TI99_JOYPORT(config, m_joyport, 0, ti99_joyport_options_mouse, "twinjoy");
787 }
788
789 /*
790 TI-99/8 US version (NTSC, 60 Hz)
791 */
ti99_8_60hz(machine_config & config)792 void ti99_8_state::ti99_8_60hz(machine_config &config)
793 {
794 ti99_8(config);
795 // Video hardware
796 tms9118_device &video(TMS9118(config, TI998_VDP_TAG, XTAL(10'738'635)));
797 video.set_vram_size(0x4000);
798 video.int_callback().set(FUNC(ti99_8_state::video_interrupt));
799 video.set_screen("screen");
800
801 SCREEN(config, "screen", SCREEN_TYPE_RASTER);
802 }
803
804 /*
805 TI-99/8 European version (PAL, 50 Hz)
806 */
ti99_8_50hz(machine_config & config)807 void ti99_8_state::ti99_8_50hz(machine_config &config)
808 {
809 ti99_8(config);
810 // Video hardware
811 tms9129_device &video(TMS9129(config, TI998_VDP_TAG, XTAL(10'738'635)));
812 video.set_vram_size(0x4000);
813 video.int_callback().set(FUNC(ti99_8_state::video_interrupt));
814 video.set_screen("screen");
815
816 SCREEN(config, "screen", SCREEN_TYPE_RASTER);
817 }
818
819 /*
820 All ROM dumps except the speech ROM have a CRC16 checksum as the final two
821 bytes. ROM1 contains four 8K chunks of ROM contents with an own CRC at their
822 ends. All GROMs, ROM0, and the four ROM1 parts were successfully
823 validated.
824 */
825 ROM_START(ti99_8)
826 // Logical (CPU) memory space: ROM0
827 ROM_REGION(0x2000, TI998_ROM0_REG, 0)
828 ROM_LOAD("rom0.u4", 0x0000, 0x2000, CRC(901eb8d6) SHA1(13190c5e834baa9c0a70066b566cfcef438ed88a))
829
830 // Physical memory space (mapped): ROM1
831 ROM_REGION(0x8000, TI998_ROM1_REG, 0)
832 ROM_LOAD("rom1.u25", 0x0000, 0x8000, CRC(b574461a) SHA1(42c6aed44802cfabdd26b565d6e5ddfcd689f11e))
833
834 // Physical memory space (mapped): P-Code ROM
835 // This circuit is only available in later versions of the console and seems
836 // to be piggy-backed on ROM1.
837 // To make things worse, the decoding logic of the custom chips do not show
838 // the required select line for this ROM on the available schematics, so
839 // they seem to be from the earlier version. The location in the address
840 // space was determined by ROM disassembly.
841 ROM_REGION(0x8000, TI998_PASCAL_REG, 0)
842 ROM_LOAD("pascal.u25a", 0x0000, 0x4000, CRC(d7ed6dd6) SHA1(32212ce6426ceccbff73d342d4a3ef699c0ae1e4))
843
844 // System GROMs. 3 chips @ f830
845 // The schematics do not enumerate the circuits but only say
846 // "circuits on board" (COB) so we name the GROMs as gM_N.bin where M is the
847 // ID (0-7) and N is the access port in the logical address space.
848 ROM_REGION(0x6000, TI998_SYSGROM_REG, 0)
849 ROM_LOAD("g0_f830.bin", 0x0000, 0x1800, CRC(1026db60) SHA1(7327095bf4f390476e69d9fd8424e98ea1f2325a))
850 ROM_LOAD("g1_f830.bin", 0x2000, 0x1800, CRC(93a43d65) SHA1(19be8a07d674bc7554c2bc9c7a5725d81e888e6e))
851 ROM_LOAD("g2_f830.bin", 0x4000, 0x1800, CRC(06f2b901) SHA1(f65e0fcb2c63e230b4a9563c72f91259b94ce955))
852
853 // TTS & Pascal library. 8 chips @ f840
854 ROM_REGION(0x10000, TI998_GROMLIB1_REG, 0)
855 ROM_LOAD("g0_f840.bin", 0x0000, 0x1800, CRC(44501071) SHA1(4b5ef7f1aa43a87e7ae4f02090944be5c39b1f26))
856 ROM_LOAD("g1_f840.bin", 0x2000, 0x1800, CRC(5a271d9e) SHA1(bb95befa2ffba2cc17ac437386e069e8ff621248))
857 ROM_LOAD("g2_f840.bin", 0x4000, 0x1800, CRC(d52502df) SHA1(17063e33ee8709d0df8030f38bb92c4322d55e1e))
858 ROM_LOAD("g3_f840.bin", 0x6000, 0x1800, CRC(86c12396) SHA1(119b6df9211b5399245e017721fc51b88b60879f))
859 ROM_LOAD("g4_f840.bin", 0x8000, 0x1800, CRC(f17a2ef8) SHA1(dcb044f71d7f8a165b41f39e35a368d8f2d63b67))
860 ROM_LOAD("g5_f840.bin", 0xA000, 0x1800, CRC(7dc41301) SHA1(dff714da68de352db93fba309db8e5a8ae7cab1a))
861 ROM_LOAD("g6_f840.bin", 0xC000, 0x1800, CRC(7e310a90) SHA1(e927d8b3f8b32aa4fb9f7d080d5262c566a77fc7))
862 ROM_LOAD("g7_f840.bin", 0xE000, 0x1800, CRC(3a9d20df) SHA1(1e6f9f8ec7df4b997a7579be742d0a7d54bc8763))
863
864 // Pascal library. 8 chips @ f850
865 ROM_REGION(0x10000, TI998_GROMLIB2_REG, 0)
866 ROM_LOAD("g0_f850.bin", 0x0000, 0x1800, CRC(2d948672) SHA1(cf15912d6dae5a450e0cfd796aa36ea5e521dc56))
867 ROM_LOAD("g1_f850.bin", 0x2000, 0x1800, CRC(7d64a842) SHA1(d5884bb2af21c8027311478ee506beac6f46203d))
868 ROM_LOAD("g2_f850.bin", 0x4000, 0x1800, CRC(e5ed8900) SHA1(03826882ce10fb5a6b3a9ccc85d3d1fe51979d0b))
869 ROM_LOAD("g3_f850.bin", 0x6000, 0x1800, CRC(87aaf19e) SHA1(fdbe163773b8a30fa6b9508e679be6fa4f99bf7a))
870 ROM_LOAD("g4_f850.bin", 0x8000, 0x1800, CRC(d3e789a5) SHA1(5ab06aa75ca694b1035ce5ac0bebacc928721388))
871 ROM_LOAD("g5_f850.bin", 0xA000, 0x1800, CRC(49fd90bd) SHA1(44b2cef29c2d5304a0dcfedbdcdf9f21f2201bf9))
872 ROM_LOAD("g6_f850.bin", 0xC000, 0x1800, CRC(31bac4ab) SHA1(e29049f0597d5de0bfd5c9c7bfea902abe858010))
873 ROM_LOAD("g7_f850.bin", 0xE000, 0x1800, CRC(71534098) SHA1(75e87123efde885e27dd749e07cb189eb2cc45a8))
874
875 // Pascal library. 3 chips @ f860
876 ROM_REGION(0x6000, TI998_GROMLIB3_REG, 0)
877 ROM_LOAD("g0_f860.bin", 0x0000, 0x1800, CRC(0ceef210) SHA1(b89957fbff094b758746391a69dea6907c66b950))
878 ROM_LOAD("g1_f860.bin", 0x2000, 0x1800, CRC(fc87de25) SHA1(4695b7f979f59a01ec16c55e4587c3379482b658))
879 ROM_LOAD("g2_f860.bin", 0x4000, 0x1800, CRC(e833e350) SHA1(6ffe501981a1112be1af596a489d96e287fc6be5))
880
881 // Speech ROM
882 ROM_REGION(0x8000, TI998_SPEECHROM_REG, 0)
883 ROM_LOAD("cd2325a.vsm", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe))
884 ROM_LOAD("cd2326a.vsm", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020))
885 ROM_END
886
887 #define rom_ti99_8e rom_ti99_8
888
889 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
890 COMP( 1983, ti99_8, 0, 0, ti99_8_60hz, ti99_8, ti99_8_state, empty_init, "Texas Instruments", "TI-99/8 Computer (US)", MACHINE_SUPPORTS_SAVE )
891 COMP( 1983, ti99_8e, ti99_8, 0, ti99_8_50hz, ti99_8, ti99_8_state, empty_init, "Texas Instruments", "TI-99/8 Computer (Europe)", MACHINE_SUPPORTS_SAVE )
892