1 // license:LGPL-2.1+
2 // copyright-holders:Michael Zapf
3 /***************************************************************************
4 
5     TI-99/8 main board logic
6 
7     This component implements the address decoder and mapper logic from the
8     TI-99/8 console.
9 
10     The TI-99/8 defines a "logical address map" with 64 KiB (according to the
11     16 address bits) and a "physical address map" with 16 MiB (according to the
12     24 address bits of the mapper). Note that the mapper only uses 16 outgoing
13     address lines and multiplexes the address bytes.
14 
15     Note: The TI-99/8's internal codename was "Armadillo"
16 
17 
18     +-------+                        +--------+
19     |  CPU  |========LogAddrBus======| Mapper |====PhysAddrBus==========
20     |  TMS  |          ||            | AMIGO  |            ||
21     |  9995 |      +----------+      |        |       +----------+
22     |       |      | Logical  |      +--------+       | Physical |
23     +-------+      | space    |            |          | space    |
24                    | decoder  |            |          | decoder  |
25                    | VAQUERRO |            |          | MOFETTA  |
26                    +----------+            |          +----------+
27                        |                   |               |
28                    +--------------------+  |          +---------------------+
29                    | Devices            |  |          | Devices             |
30                    |            +-------+  |          |                     |
31                    | ROM0       | SRAM  |  |          | DRAM  (POLLO)       |
32                    | Video      | ----  |  |          | ROM1                |
33                    | Speech     | Maps--+--+          | Cartridge port      |
34                    | GROM       +-------+             | PEB                 |
35                    | Sound              |             | Hexbus (OSO)        |
36                    +--------------------+             +---------------------+
37 
38     Custom chips
39     ------------
40     The chipset of the TI-99/8 consists of five specifically programmed chips.
41     All are nicknamed after some Spanish words (albeit sometimes misspelled)
42 
43     VAQUERRO: Logical Address Space decoder  ("Vaquero" = "Cowboy")
44     MOFETTA : Physical Address Space decoder ("Mofeta"  = "Skunk")
45     AMIGO   : Mapper                         ("Amigo"   = "Friend")
46     OSO     : Hexbus adapter                 ("Oso"     = "Bear")
47     POLLO   : DRAM controller (Not emulated) ("Pollo"   = "Chicken")
48 
49     See the comments for the respective chip implementation for details.
50 
51 
52     ROM contents
53     ------------
54     The ROM0 chip is accessible at addresses 0000-1FFF in the logical address
55     space of the compatibility mode. It contains the GPL interpreter. In
56     native mode the ROM0 chip is invisible.
57 
58       ROM0
59       offset  Logical address     Name
60       -----------------------------------
61       0000    0000-1FFF           ROM0
62 
63 
64     The ROM1 chip contains 32 KiB of various system software. It is located in
65     the physical address space, so it must be mapped into the logical address
66     space by defining an appropriate map.
67 
68       ROM1
69       offset  Physical address            Name
70       ----------------------------------------------------------
71       0000    FFA000-FFDFFF               ROM1
72       4000    FF4000-FF5FFF @CRU>2700     Text-to-speech ROM/DSR
73       6000    FF4000-FF5FFF @CRU>1700     Hexbus DSR
74 
75     The DSR portions have to be selected via the CRU bits >1700 or >2700.
76 
77 
78     CRU map (I/O address space)
79     ===========================
80     0000-003e: TMS9901 system interface (see ti99_8.c)
81     1700-17fe: Hexbus
82     2000-26fe: Future external devices
83     2700-27fe: Additional ROM ("internal DSR")
84     2702     : System reset (when set to 1)
85     2800-3ffe: Future external devices
86     4000-fffe: Future external devices
87 
88     The TMS9995 offers the full 15-bit CRU address space. Devices designed for
89     the TI-99/4A should only be accessed in the area 1000-1ffe. They will (by
90     design) incompletely decode the CRU address and be mirrored in the higher
91     areas.
92 
93     Note that the cartridge port of the TI-99/8 offers support for 16K ROM
94     cartridges, but lacks CRU support.
95 
96     Michael Zapf, October 2010
97     February 2012: Rewritten as class
98     March 2016: Redesigned for custom chip emulation
99 
100     Informations taken from
101     [1] ARMADILLO PRODUCT SPECIFICATIONS
102     [2] TI-99/8 Graphics Programming Language interpreter
103 
104 ***************************************************************************/
105 
106 #include "emu.h"
107 #include "998board.h"
108 #include "cpu/tms9900/tms99com.h"
109 
110 #define LOG_DETAIL      (1U<<1)     // More detail
111 #define LOG_CRU         (1U<<2)     // CRU logging
112 #define LOG_ADDRESS     (1U<<3)     // Address bus
113 #define LOG_MEM         (1U<<4)     // Memory access
114 #define LOG_MAP         (1U<<5)     // Mapper
115 #define LOG_READY       (1U<<6)     // READY line
116 #define LOG_CLOCK       (1U<<7)     // CLKOUT
117 #define LOG_MOFETTA     (1U<<8)     // Mofetta operation
118 #define LOG_AMIGO       (1U<<9)     // Amigo operation
119 #define LOG_OSO         (1U<<10)    // Oso operation
120 #define LOG_HEXBUS      (1U<<11)    // Hexbus operation
121 #define LOG_WS          (1U<<12)    // Wait states
122 #define LOG_CPURY       (1U<<13)    // Combined ready line
123 #define LOG_GROM        (1U<<14)    // GROM operation
124 #define LOG_PUNMAP      (1U<<15)    // Unmapped physical addresss
125 #define LOG_WARN        (1U<<31)    // Warnings
126 
127 #define VERBOSE ( LOG_WARN )
128 
129 #include "logmacro.h"
130 
131 DEFINE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device, "ti998_mainboard", "TI-99/8 Mainboard")
132 DEFINE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device, "ti998_vaquerro", "TI-99/8 Logical Address Space Decoder")
133 DEFINE_DEVICE_TYPE_NS(TI99_MOFETTA, bus::ti99::internal, mofetta_device, "ti998_mofetta", "TI-99/8 Physical Address Space Decoder")
134 DEFINE_DEVICE_TYPE_NS(TI99_OSO, bus::ti99::internal, oso_device, "ti998_oso", "TI-99/8 Hexbus interface")
135 DEFINE_DEVICE_TYPE_NS(TI99_AMIGO, bus::ti99::internal, amigo_device, "ti998_amigo", "TI-99/8 Address space mapper")
136 
137 namespace bus { namespace ti99 { namespace internal {
138 
139 enum
140 {
141 	SGMSEL = 1,
142 	TSGSEL = 2,
143 	P8GSEL = 4,
144 	P3GSEL = 8,
145 	VIDSEL = 16
146 };
147 
mainboard8_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)148 mainboard8_device::mainboard8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
149 	: device_t(mconfig, TI99_MAINBOARD8, tag, owner, clock),
150 	m_A14_set(false),
151 	m_pending_write(false),
152 	m_speech_ready(true),
153 	m_sound_ready(true),
154 	m_pbox_ready(true),
155 	m_ready(*this),
156 	m_console_reset(*this),
157 	m_hold_line(*this),
158 	m_vaquerro(*this, TI998_VAQUERRO_TAG),
159 	m_mofetta(*this, TI998_MOFETTA_TAG),
160 	m_amigo(*this, TI998_AMIGO_TAG),
161 	m_oso(*this, TI998_OSO_TAG),
162 	m_maincpu(*owner, "maincpu"),
163 	m_video(*owner, TI998_VDP_TAG),
164 	m_sound(*owner, TI998_SOUNDCHIP_TAG),
165 	m_speech(*owner, TI998_SPEECHSYN_TAG),
166 	m_gromport(*owner, TI99_GROMPORT_TAG),
167 	m_ioport(*owner, TI99_IOPORT_TAG),
168 	m_sram(*owner, TI998_SRAM_TAG),
169 	m_dram(*owner, TI998_DRAM_TAG),
170 	m_sgrom0(*owner, TI998_SYSGROM0_TAG),
171 	m_sgrom1(*owner, TI998_SYSGROM1_TAG),
172 	m_sgrom2(*owner, TI998_SYSGROM2_TAG),
173 	m_tsgrom0(*owner, TI998_GLIB10_TAG),
174 	m_tsgrom1(*owner, TI998_GLIB11_TAG),
175 	m_tsgrom2(*owner, TI998_GLIB12_TAG),
176 	m_tsgrom3(*owner, TI998_GLIB13_TAG),
177 	m_tsgrom4(*owner, TI998_GLIB14_TAG),
178 	m_tsgrom5(*owner, TI998_GLIB15_TAG),
179 	m_tsgrom6(*owner, TI998_GLIB16_TAG),
180 	m_tsgrom7(*owner, TI998_GLIB17_TAG),
181 	m_p8grom0(*owner, TI998_GLIB20_TAG),
182 	m_p8grom1(*owner, TI998_GLIB21_TAG),
183 	m_p8grom2(*owner, TI998_GLIB22_TAG),
184 	m_p8grom3(*owner, TI998_GLIB23_TAG),
185 	m_p8grom4(*owner, TI998_GLIB24_TAG),
186 	m_p8grom5(*owner, TI998_GLIB25_TAG),
187 	m_p8grom6(*owner, TI998_GLIB26_TAG),
188 	m_p8grom7(*owner, TI998_GLIB27_TAG),
189 	m_p3grom0(*owner, TI998_GLIB30_TAG),
190 	m_p3grom1(*owner, TI998_GLIB31_TAG),
191 	m_p3grom2(*owner, TI998_GLIB32_TAG),
192 	m_sgrom_idle(true),
193 	m_tsgrom_idle(true),
194 	m_p8grom_idle(true),
195 	m_p3grom_idle(true)
196 {
197 }
198 
199 // Debugger support
200 // The memory accesses by the debugger are routed around the custom chip logic
201 
debugger_read(offs_t offset)202 uint8_t mainboard8_device::debugger_read(offs_t offset)
203 {
204 	int logical_address = offset;
205 	bool compat_mode = (m_crus_debug==ASSERT_LINE);
206 
207 	// Check whether the mapper itself is accessed
208 	int mapaddr = compat_mode? 0x8810 : 0xf870;
209 	bool mapper_accessed = ((offset & 0xfff1)==mapaddr);
210 
211 	if (mapper_accessed) return 0; // do not allow the debugger to mess with the mapper
212 
213 	// or SRAM
214 	int sramaddr = compat_mode? 0x8000 : 0xf000;
215 
216 	if ((offset & 0xf800)==sramaddr)
217 	{
218 		// SRAM access
219 		return m_sram->pointer()[logical_address & 0x07ff];
220 	}
221 	if ((offset & 0xe000)==0x0000 && compat_mode)
222 	{
223 		// ROM0 access
224 		return m_rom0[logical_address & 0x1fff];
225 	}
226 
227 	// Physical space
228 	u8 value = 0;
229 	int physical_address = m_amigo->get_physical_address_debug(offset);
230 
231 	if ((physical_address & 0x00ff0000)==0x00000000)
232 	{
233 		// DRAM
234 		return m_dram->pointer()[physical_address & 0xffff];
235 	}
236 	if ((physical_address & 0x00ffc000)==0x00f00000)
237 	{
238 		// Pascal ROM 16K
239 		return m_pascalrom[physical_address & 0x3fff];
240 	}
241 	if ((physical_address & 0x00ffe000)==0x00ff4000)
242 	{
243 		// Internal DSR, Hexbus DSR, or PEB
244 		if (m_mofetta->hexbus_access_debug()) return m_rom1[(physical_address & 0x1fff) | 0x6000];
245 		if (m_mofetta->intdsr_access_debug()) return m_rom1[(physical_address & 0x1fff) | 0x4000];
246 		m_ioport->memen_in(ASSERT_LINE);
247 		m_ioport->readz(physical_address & 0xffff, &value);
248 		m_ioport->memen_in(CLEAR_LINE);
249 		return value;
250 	}
251 	if ((physical_address & 0x00ffe000)==0x00ff6000)
252 	{
253 		// Cartridge space lower 8
254 		m_gromport->romgq_line(ASSERT_LINE);
255 		m_gromport->readz(physical_address & 0x1fff, &value);
256 		m_gromport->romgq_line(CLEAR_LINE);
257 		return value;
258 	}
259 	if ((physical_address & 0x00ffe000)==0x00ff8000)
260 	{
261 		// Cartridge space upper 8
262 		m_gromport->romgq_line(ASSERT_LINE);
263 		m_gromport->readz((physical_address & 0x1fff) | 0x2000, &value);
264 		m_gromport->romgq_line(CLEAR_LINE);
265 		return value;
266 	}
267 	if ((physical_address & 0x00ffe000)==0x00ffa000)
268 	{
269 		// ROM1 lower 8
270 		return m_rom1[(physical_address & 0x1fff) | 0x0000];
271 	}
272 	if ((physical_address & 0x00ffe000)==0x00ffc000)
273 	{
274 		// ROM1 upper 8
275 		return m_rom1[(physical_address & 0x1fff) | 0x2000];
276 	}
277 	return 0;
278 }
279 
debugger_write(offs_t offset,uint8_t data)280 void mainboard8_device::debugger_write(offs_t offset, uint8_t data)
281 {
282 	int logical_address = offset;
283 	bool compat_mode = (m_crus_debug==ASSERT_LINE);
284 
285 	// Check whether the mapper itself is accessed
286 	int mapaddr = compat_mode? 0x8810 : 0xf870;
287 	bool mapper_accessed = ((offset & 0xfff1)==mapaddr);
288 
289 	if (mapper_accessed)
290 	{
291 		// Allow for loading/saving mapper registers
292 		m_amigo->mapper_access_debug(data);
293 		return;
294 	}
295 
296 	// SRAM
297 	int sramaddr = compat_mode? 0x8000 : 0xf000;
298 
299 	if ((offset & 0xf800)==sramaddr)
300 	{
301 		// SRAM access
302 		m_sram->pointer()[logical_address & 0x07ff] = data & 0xff;
303 		return;
304 	}
305 
306 	// ROM0 (no write access)
307 	if ((offset & 0xe000)==0x0000 && compat_mode) return;
308 
309 	// Physical space
310 	int physical_address = m_amigo->get_physical_address_debug(offset);
311 
312 	if ((physical_address & 0x00ff0000)==0x00000000)
313 	{
314 		// DRAM
315 		m_dram->pointer()[physical_address & 0xffff] = data & 0xff;
316 		return;
317 	}
318 
319 	// Pascal ROM (no write)
320 	if ((physical_address & 0x00ffc000)==0x00f00000) return;
321 
322 	// Internal DSR, Hexbus DSR, or PEB
323 	if ((physical_address & 0x00ffe000)==0x00ff4000)
324 	{
325 		if (m_mofetta->hexbus_access_debug()) return;
326 		if (m_mofetta->intdsr_access_debug()) return;
327 		m_ioport->memen_in(ASSERT_LINE);
328 		m_ioport->write(physical_address & 0xffff, data & 0xff);
329 		m_ioport->memen_in(CLEAR_LINE);     return;
330 	}
331 	if ((physical_address & 0x00ffe000)==0x00ff6000)
332 	{
333 		// Cartridge space lower 8
334 		m_gromport->romgq_line(ASSERT_LINE);
335 		m_gromport->write(physical_address & 0x1fff, data & 0xff);
336 		m_gromport->romgq_line(CLEAR_LINE);
337 		return;
338 	}
339 	if ((physical_address & 0x00ffe000)==0x00ff8000)
340 	{
341 		// Cartridge space upper 8
342 		m_gromport->romgq_line(ASSERT_LINE);
343 		m_gromport->write((physical_address & 0x1fff) | 0x2000, data & 0xff);
344 		m_gromport->romgq_line(CLEAR_LINE);
345 		return;
346 	}
347 
348 	// ROM1 not writable
349 	if ((physical_address & 0x00ffe000)==0x00ffa000 || (physical_address & 0x00ffe000)==0x00ffc000) return;
350 }
351 
352 // =============== CRU bus access ==================
353 
crureadz(offs_t offset,uint8_t * value)354 void mainboard8_device::crureadz(offs_t offset, uint8_t *value)
355 {
356 	m_ioport->crureadz(offset, value);
357 }
358 
359 /*
360     CRU handling. Mofetta is the only chip that bothers to handle it, beside the PEB
361 */
cruwrite(offs_t offset,uint8_t data)362 void mainboard8_device::cruwrite(offs_t offset, uint8_t data)
363 {
364 	m_mofetta->cruwrite(offset, data);
365 	m_ioport->cruwrite(offset, data);
366 }
367 
368 // =============== Memory bus access ==================
369 
setaddress(offs_t offset,uint8_t busctrl)370 void mainboard8_device::setaddress(offs_t offset, uint8_t busctrl)
371 {
372 	m_dbin_level = ((busctrl & TMS99xx_BUS_DBIN)!=0);
373 	LOGMASKED(LOG_ADDRESS, "set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
374 
375 	// No data is waiting on the data bus
376 	m_pending_write = false;
377 
378 	// Memory cycle begins
379 	m_vaquerro->memen_in(ASSERT_LINE);
380 	m_amigo->memen_in(ASSERT_LINE);
381 
382 	// Save the logical address
383 	m_logical_address = offset;
384 	m_physical_address = 0;
385 
386 	// In TI's bit order, A14 is the second line from the right side (2^1)
387 	m_A14_set = ((m_logical_address & 2)!=0); // Needed for clock_in
388 
389 	// Check for match in logical space
390 	m_vaquerro->set_address(m_logical_address, m_dbin_level);
391 
392 	// Select GROMs if addressed
393 	select_groms();
394 
395 	// Speech select lines will always be asserted/cleared as soon as the address is available
396 	m_speech->wsq_w((m_vaquerro->spwt_out() == ASSERT_LINE)? false : true);
397 	m_speech->rsq_w((m_vaquerro->sprd_out() == ASSERT_LINE)? false : true);
398 
399 	// If it is a logical space address, tell the mapper to stay inactive
400 	line_state lasreq = (line_state)m_vaquerro->lascsq_out();
401 	m_amigo->lascs_in(lasreq);
402 	m_mofetta->lascs_in(lasreq);
403 
404 	// Need to set the address in any case so that the lines can be cleared
405 	m_amigo->set_address(m_logical_address);
406 
407 	// AMIGO is the one to control the READY line to the CPU
408 	// MOFETTA does not contribute to READY
409 	m_ready(m_amigo->cpury_out());
410 }
411 
WRITE_LINE_MEMBER(mainboard8_device::reset_console)412 WRITE_LINE_MEMBER( mainboard8_device::reset_console )
413 {
414 	m_console_reset(state);
415 }
416 
WRITE_LINE_MEMBER(mainboard8_device::hold_cpu)417 WRITE_LINE_MEMBER( mainboard8_device::hold_cpu )
418 {
419 	m_hold_line(state);
420 }
421 
422 /*
423     HOLD Acknowledge from the CPU
424 */
WRITE_LINE_MEMBER(mainboard8_device::holda_line)425 WRITE_LINE_MEMBER( mainboard8_device::holda_line )
426 {
427 	m_amigo->holda_in(state);
428 }
429 
430 /*
431     Clock line from the CPU. Forward to the custom chips.
432 */
WRITE_LINE_MEMBER(mainboard8_device::clock_in)433 WRITE_LINE_MEMBER( mainboard8_device::clock_in )
434 {
435 	LOGMASKED(LOG_CLOCK, "CLKOUT = %d\n", state);
436 
437 	// Propagate to Vaquerro; may change GGRDY (trailing edge) and the GROM select lines
438 	m_vaquerro->clock_in((line_state)state);
439 
440 	// Set the incoming ready line of Amigo (Mapper) before the clock
441 	bool readycomb = ((m_vaquerro->ggrdy_out()==ASSERT_LINE) && m_speech_ready && m_sound_ready && m_pbox_ready);
442 	m_amigo->srdy_in(readycomb? ASSERT_LINE : CLEAR_LINE);
443 
444 	// This may change the incoming READY lines of Vaquerro
445 	if (state==CLEAR_LINE) select_groms();
446 
447 	m_amigo->clock_in((line_state)state);
448 
449 	// Mofetta only needs the clock to produce the GROM clock
450 	m_mofetta->clock_in(state);
451 
452 	m_mofetta->skdrcs_in(m_amigo->skdrcs_out());
453 
454 	// Clock to Oso
455 	m_oso->clock_in(state);
456 
457 	int gromclk = m_mofetta->gromclk_out();
458 
459 	if (gromclk != m_gromclk)   // when it changed, propagate to the GROMs
460 	{
461 		m_gromclk = gromclk;
462 
463 		// Get some more performance. We only propagate the clock line to
464 		// those GROMs that are not idle.
465 		// Yields about 25% in bench (hoped for more, but well)
466 		if (!m_sgrom_idle)
467 		{
468 			m_sgrom0->gclock_in(gromclk);
469 			m_sgrom1->gclock_in(gromclk);
470 			m_sgrom2->gclock_in(gromclk);
471 			m_gromport->gclock_in(gromclk);
472 			m_sgrom_idle = m_sgrom0->idle();
473 		}
474 
475 		if (!m_tsgrom_idle)
476 		{
477 			m_tsgrom0->gclock_in(gromclk);
478 			m_tsgrom1->gclock_in(gromclk);
479 			m_tsgrom2->gclock_in(gromclk);
480 			m_tsgrom3->gclock_in(gromclk);
481 			m_tsgrom4->gclock_in(gromclk);
482 			m_tsgrom5->gclock_in(gromclk);
483 			m_tsgrom6->gclock_in(gromclk);
484 			m_tsgrom7->gclock_in(gromclk);
485 			m_tsgrom_idle = m_tsgrom0->idle();
486 		}
487 		if (!m_p8grom_idle)
488 		{
489 			m_p8grom0->gclock_in(gromclk);
490 			m_p8grom1->gclock_in(gromclk);
491 			m_p8grom2->gclock_in(gromclk);
492 			m_p8grom3->gclock_in(gromclk);
493 			m_p8grom4->gclock_in(gromclk);
494 			m_p8grom5->gclock_in(gromclk);
495 			m_p8grom6->gclock_in(gromclk);
496 			m_p8grom7->gclock_in(gromclk);
497 			m_p8grom_idle = m_p8grom0->idle();
498 		}
499 
500 		if (!m_p3grom_idle)
501 		{
502 			m_p3grom0->gclock_in(gromclk);
503 			m_p3grom1->gclock_in(gromclk);
504 			m_p3grom2->gclock_in(gromclk);
505 			m_p3grom_idle = m_p3grom0->idle();
506 		}
507 	}
508 
509 	// Check video for writing
510 	if (m_pending_write && m_vaquerro->vdpwt_out()==ASSERT_LINE)
511 	{
512 		if (m_A14_set) m_video->register_write(m_latched_data);
513 		else m_video->vram_write(m_latched_data);
514 		m_pending_write = false;
515 		LOGMASKED(LOG_MEM, "Write %04x (video) <- %02x\n", m_logical_address, m_latched_data);
516 		cycle_end();
517 		return;
518 	}
519 
520 	// Propagate the READY signal
521 	m_ready(m_amigo->cpury_out());
522 
523 	// In case we're reading, the CPU will now do the READ operation.
524 	// Otherwise we must do the write operation now which we postponed before.
525 
526 	if (m_pending_write && (state==CLEAR_LINE))
527 	{
528 		if (m_amigo->skdrcs_out()==ASSERT_LINE)
529 		{
530 			m_dram->pointer()[m_physical_address & 0xffff] = m_latched_data;
531 			m_pending_write = false;
532 			LOGMASKED(LOG_MEM, "Write %04x (phys %06x, DRAM) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
533 		}
534 
535 		if (m_mofetta->alccs_out()==ASSERT_LINE)
536 		{
537 			m_oso->write(m_physical_address>>1, m_latched_data);
538 			m_pending_write = false;
539 			LOGMASKED(LOG_MEM, "Write %04x (phys %06x, OSO) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
540 		}
541 
542 		if (m_mofetta->cmas_out()==ASSERT_LINE)
543 		{
544 			m_gromport->romgq_line(ASSERT_LINE);
545 			m_gromport->write(m_physical_address & 0x3fff, m_latched_data);
546 			m_pending_write = false;
547 			LOGMASKED(LOG_MEM, "Write %04x (phys %06x, cartridge) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
548 		}
549 		else
550 		{
551 			m_gromport->romgq_line(CLEAR_LINE);
552 		}
553 
554 		if (m_mofetta->dbc_out()==ASSERT_LINE)
555 		{
556 			m_ioport->write(m_physical_address, m_latched_data);
557 			m_pending_write = false;
558 			LOGMASKED(LOG_MEM, "Write %04x (phys %06x, PEB) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
559 		}
560 	}
561 
562 	if (m_dbin_level==CLEAR_LINE && !m_pending_write)       // Memory cycle ends
563 		cycle_end();
564 }
565 
select_groms()566 void mainboard8_device::select_groms()
567 {
568 	// Select the GROM libs
569 	// Note that we must also deselect them again, so we have to visit each
570 	// one of them
571 
572 	int select = m_vaquerro->gromcs_out();
573 
574 	// Avoid to be called too often; this would have a bad penalty on emulation performance
575 	// This simple check actually increases bench performance from 120% to 240%
576 	if (select != m_prev_grom)
577 	{
578 		m_prev_grom = select;
579 		line_state a14 = m_A14_set? ASSERT_LINE : CLEAR_LINE;
580 
581 		if (select & SGMSEL) m_sgrom_idle = false;
582 		if (select & TSGSEL) m_tsgrom_idle = false;
583 		if (select & P8GSEL) m_p8grom_idle = false;
584 		if (select & P3GSEL) m_p3grom_idle = false;
585 
586 		line_state ssel = (select & SGMSEL)? ASSERT_LINE : CLEAR_LINE;
587 		line_state tsel = (select & TSGSEL)? ASSERT_LINE : CLEAR_LINE;
588 		line_state p8sel = (select & P8GSEL)? ASSERT_LINE : CLEAR_LINE;
589 		line_state p3sel = (select & P3GSEL)? ASSERT_LINE : CLEAR_LINE;
590 
591 		m_sgrom0->set_lines((line_state)m_dbin_level, a14, ssel);
592 		m_sgrom1->set_lines((line_state)m_dbin_level, a14, ssel);
593 		m_sgrom2->set_lines((line_state)m_dbin_level, a14, ssel);
594 
595 		m_tsgrom0->set_lines((line_state)m_dbin_level, a14, tsel);
596 		m_tsgrom1->set_lines((line_state)m_dbin_level, a14, tsel);
597 		m_tsgrom2->set_lines((line_state)m_dbin_level, a14, tsel);
598 		m_tsgrom3->set_lines((line_state)m_dbin_level, a14, tsel);
599 		m_tsgrom4->set_lines((line_state)m_dbin_level, a14, tsel);
600 		m_tsgrom5->set_lines((line_state)m_dbin_level, a14, tsel);
601 		m_tsgrom6->set_lines((line_state)m_dbin_level, a14, tsel);
602 		m_tsgrom7->set_lines((line_state)m_dbin_level, a14, tsel);
603 
604 		m_p8grom0->set_lines((line_state)m_dbin_level, a14, p8sel);
605 		m_p8grom1->set_lines((line_state)m_dbin_level, a14, p8sel);
606 		m_p8grom2->set_lines((line_state)m_dbin_level, a14, p8sel);
607 		m_p8grom3->set_lines((line_state)m_dbin_level, a14, p8sel);
608 		m_p8grom4->set_lines((line_state)m_dbin_level, a14, p8sel);
609 		m_p8grom5->set_lines((line_state)m_dbin_level, a14, p8sel);
610 		m_p8grom6->set_lines((line_state)m_dbin_level, a14, p8sel);
611 		m_p8grom7->set_lines((line_state)m_dbin_level, a14, p8sel);
612 
613 		m_p3grom0->set_lines((line_state)m_dbin_level, a14, p3sel);
614 		m_p3grom1->set_lines((line_state)m_dbin_level, a14, p3sel);
615 		m_p3grom2->set_lines((line_state)m_dbin_level, a14, p3sel);
616 
617 		// Write to the cartridge port. The GROMs on cartridges are accessed as system GROMs
618 		if (select & SGMSEL) m_gromport->romgq_line(CLEAR_LINE);
619 		m_gromport->set_gromlines((line_state)m_dbin_level, a14, ssel);
620 	}
621 
622 	// If we're planning to write to the GROMs, let's do it right now
623 	if (select !=0 && m_pending_write)
624 	{
625 		m_pending_write = false;
626 		switch (select)
627 		{
628 		case SGMSEL:
629 			m_sgrom0->write(m_latched_data);
630 			m_sgrom1->write(m_latched_data);
631 			m_sgrom2->write(m_latched_data);
632 			LOGMASKED(LOG_MEM, "Write GS <- %02x\n", m_latched_data);
633 			m_gromport->write(0, m_latched_data);
634 			break;
635 
636 		case TSGSEL:
637 			m_tsgrom0->write(m_latched_data);
638 			m_tsgrom1->write(m_latched_data);
639 			m_tsgrom2->write(m_latched_data);
640 			m_tsgrom3->write(m_latched_data);
641 			m_tsgrom4->write(m_latched_data);
642 			m_tsgrom5->write(m_latched_data);
643 			m_tsgrom6->write(m_latched_data);
644 			m_tsgrom7->write(m_latched_data);
645 			LOGMASKED(LOG_MEM, "Write GT <- %02x\n", m_latched_data);
646 			break;
647 
648 		case P8GSEL:
649 			m_p8grom0->write(m_latched_data);
650 			m_p8grom1->write(m_latched_data);
651 			m_p8grom2->write(m_latched_data);
652 			m_p8grom3->write(m_latched_data);
653 			m_p8grom4->write(m_latched_data);
654 			m_p8grom5->write(m_latched_data);
655 			m_p8grom6->write(m_latched_data);
656 			m_p8grom7->write(m_latched_data);
657 			LOGMASKED(LOG_MEM, "Write G8 <- %02x\n", m_latched_data);
658 			break;
659 
660 		case P3GSEL:
661 			m_p3grom0->write(m_latched_data);
662 			m_p3grom1->write(m_latched_data);
663 			m_p3grom2->write(m_latched_data);
664 			LOGMASKED(LOG_MEM, "Write G3 <- %02x\n", m_latched_data);
665 			break;
666 
667 		default:
668 			LOGMASKED(LOG_WARN, "Error: Multiple GROM libs selected: SGM=%d TSG=%d P8G=%d P3G=%d\n", (select & SGMSEL)!=0, (select & TSGSEL)!=0, (select & P8GSEL)!=0, (select & P3GSEL)!=0);
669 			break;
670 		}
671 	}
672 }
673 
set_paddress(int address)674 void mainboard8_device::set_paddress(int address)
675 {
676 	// Keep this value as the current address
677 	m_physical_address = (m_physical_address << 16) | address;
678 	LOGMASKED(LOG_DETAIL, "Setting physical address %06x\n", m_physical_address);
679 
680 	m_mofetta->set_address(address, m_dbin_level);
681 	m_ioport->setaddress_dbin(address, m_dbin_level);
682 }
683 
WRITE_LINE_MEMBER(mainboard8_device::msast_in)684 WRITE_LINE_MEMBER( mainboard8_device::msast_in )
685 {
686 	LOGMASKED(LOG_DETAIL, "msast = %d\n", state);
687 
688 	// Start physical space cycle on the trailing edge
689 	if (state==CLEAR_LINE)
690 	{
691 		m_mofetta->pmemen_in(ASSERT_LINE);
692 		m_ioport->memen_in(ASSERT_LINE);
693 	}
694 	m_mofetta->msast_in(state);
695 	m_ioport->msast_in(state);
696 }
697 
698 
read(offs_t offset)699 uint8_t mainboard8_device::read(offs_t offset)
700 {
701 	uint8_t value = 0;
702 	const char* what;
703 
704 	if (machine().side_effects_disabled())
705 	{
706 		return debugger_read(offset);
707 	}
708 
709 	// =================================================
710 	//   Logical space
711 	// =================================================
712 	if (m_amigo->mapper_accessed())
713 	{
714 		value = m_amigo->read();
715 		what = "mapper";
716 		goto readdone;
717 	}
718 
719 	if (m_amigo->sramcs_out()==ASSERT_LINE)
720 	{
721 		value = m_sram->pointer()[m_logical_address & 0x07ff];
722 		what = "SRAM";
723 		goto readdone;
724 	}
725 
726 	if (m_vaquerro->lascsq_out()==ASSERT_LINE)
727 	{
728 		// VDP access
729 		if (m_vaquerro->vdprd_out()==ASSERT_LINE)
730 		{
731 			value = m_A14_set? m_video->register_read() : m_video->vram_read();
732 			what = "video";
733 			goto readdone;
734 		}
735 
736 		// System ROM0
737 		if (m_vaquerro->sromcs_out()==ASSERT_LINE)
738 		{
739 			value = m_rom0[m_logical_address & 0x1fff];
740 			what = "ROM0";
741 			goto readdone;
742 		}
743 
744 		// Speech
745 		if (m_vaquerro->sprd_out()==ASSERT_LINE)
746 		{
747 			value = m_speech->status_r() & 0xff;
748 			what = "speech";
749 			goto readdone;
750 		}
751 
752 		// GROMs
753 		switch (m_vaquerro->gromcs_out())
754 		{
755 		case SGMSEL:
756 			m_sgrom_idle = false;
757 			m_sgrom0->readz(&value);
758 			m_sgrom1->readz(&value);
759 			m_sgrom2->readz(&value);
760 			m_gromport->readz(0, &value);
761 			if (!m_A14_set) LOGMASKED(LOG_GROM, "GS>%04x\n", m_sgrom0->debug_get_address()-1);
762 			what = "system GROM";
763 			goto readdone;
764 
765 		case TSGSEL:
766 			m_tsgrom_idle = false;
767 			m_tsgrom0->readz(&value);
768 			m_tsgrom1->readz(&value);
769 			m_tsgrom2->readz(&value);
770 			m_tsgrom3->readz(&value);
771 			m_tsgrom4->readz(&value);
772 			m_tsgrom5->readz(&value);
773 			m_tsgrom6->readz(&value);
774 			m_tsgrom7->readz(&value);
775 			if (!m_A14_set) LOGMASKED(LOG_GROM, "GT>%04x\n", m_tsgrom0->debug_get_address()-1);
776 			what = "TTS GROM";
777 			goto readdone;
778 
779 		case P8GSEL:
780 			m_p8grom_idle = false;
781 			m_p8grom0->readz(&value);
782 			m_p8grom1->readz(&value);
783 			m_p8grom2->readz(&value);
784 			m_p8grom3->readz(&value);
785 			m_p8grom4->readz(&value);
786 			m_p8grom5->readz(&value);
787 			m_p8grom6->readz(&value);
788 			m_p8grom7->readz(&value);
789 			if (!m_A14_set) LOGMASKED(LOG_GROM, "G8>%04x\n", m_p8grom0->debug_get_address()-1);
790 			what = "P8 GROM";
791 			goto readdone;
792 
793 		case P3GSEL:
794 			m_p3grom_idle = false;
795 			m_p3grom0->readz(&value);
796 			m_p3grom1->readz(&value);
797 			m_p3grom2->readz(&value);
798 			if (!m_A14_set) LOGMASKED(LOG_GROM, "G3>%04x\n", m_p3grom0->debug_get_address()-1);
799 			what = "P3 GROM";
800 			goto readdone;
801 		default:
802 			break;
803 		}
804 
805 		// These messages appear in fact every time that a GPL command writes
806 		// an immediate value to a write-only address (like 9400) because the
807 		// GPL interpreter always tries to load the value from the provided memory address first
808 
809 		LOGMASKED(LOG_WARN, "Read %04x (unmapped) ignored\n", m_logical_address);
810 
811 		// Memory cycle ends
812 		cycle_end();
813 		return 0;
814 	}
815 	else
816 	{
817 		// =================================================
818 		//   Physical space
819 		// =================================================
820 		if (m_amigo->skdrcs_out()==ASSERT_LINE)
821 		{
822 			value = m_dram->pointer()[m_physical_address & 0xffff];
823 			what = "DRAM";
824 			goto readdonephys;
825 		}
826 
827 		if (m_mofetta->rom1cs_out()==ASSERT_LINE)
828 		{
829 			int address = (m_physical_address & 0x1fff);
830 			if (m_mofetta->rom1am_out()==ASSERT_LINE) address |= 0x4000;
831 			if (m_mofetta->rom1al_out()==ASSERT_LINE) address |= 0x2000;
832 			value = m_rom1[address];
833 
834 			LOGMASKED(LOG_MEM, "Read %04x (ROM1@%04x) -> %02x\n", m_logical_address, address, value);
835 			cycle_end();
836 			return value;
837 		}
838 
839 		if (m_mofetta->alccs_out()==ASSERT_LINE)
840 		{
841 			value = m_oso->read(m_physical_address>>1);
842 			what = "OSO";
843 			goto readdonephys;
844 		}
845 
846 		if (m_mofetta->prcs_out()==ASSERT_LINE)
847 		{
848 			value = m_pascalrom[m_physical_address & 0x3fff];
849 			what = "PASCAL";
850 			goto readdonephys;
851 		}
852 
853 		if (m_mofetta->cmas_out()==ASSERT_LINE)
854 		{
855 			m_gromport->romgq_line(ASSERT_LINE);
856 			m_gromport->readz(m_physical_address & 0x3fff, &value);
857 			what = "Cartridge";
858 			goto readdonephys;
859 		}
860 
861 		if (m_mofetta->dbc_out()==ASSERT_LINE)
862 		{
863 			m_ioport->readz(m_physical_address & 0xffff, &value);
864 			what = "PEB";
865 			goto readdonephys;
866 		}
867 
868 		LOGMASKED(LOG_PUNMAP, "Read %04x (phys %06x, unmapped) ignored\n", m_logical_address, m_physical_address);
869 
870 		// Memory cycle ends
871 		cycle_end();
872 		return 0;
873 	}
874 
875 
876 readdone:
877 	LOGMASKED(LOG_MEM, "Read %04x (%s) -> %02x\n", m_logical_address, what, value);
878 	cycle_end();
879 	return value;
880 
881 readdonephys:
882 	LOGMASKED(LOG_MEM, "Read %04x (phys %06x, %s) -> %02x\n", m_logical_address, m_physical_address, what, value);
883 	cycle_end();
884 	return value;
885 }
886 
cycle_end()887 void mainboard8_device::cycle_end()
888 {
889 	// Memory cycle ends
890 	m_vaquerro->memen_in(CLEAR_LINE);
891 	m_amigo->memen_in(CLEAR_LINE);
892 	m_mofetta->pmemen_in(CLEAR_LINE);
893 	m_ioport->memen_in(CLEAR_LINE);
894 }
895 
896 /*
897     When writing, the emulation relies on a push mechanism; the write
898     operation follows the setaddress operation immediately.
899 
900     If the READY line is pulled down due to the mapping process, we must
901     store the data bus value until the physical address is available.
902 */
write(offs_t offset,uint8_t data)903 void mainboard8_device::write(offs_t offset, uint8_t data)
904 {
905 	m_latched_data = data;
906 	m_pending_write = true;
907 
908 	if (machine().side_effects_disabled())
909 	{
910 		return debugger_write(offset, data);
911 	}
912 
913 	// Some logical space devices can be written immediately
914 	// GROMs and video must wait to be selected
915 	if (m_amigo->mapper_accessed())
916 	{
917 		LOGMASKED(LOG_MEM, "Write %04x (mapper) <- %02x\n", m_logical_address, data);
918 		m_amigo->write(data);
919 		m_pending_write = false;
920 	}
921 
922 	// Sound ... we have to put it before SRAM because in compatibility mode the
923 	// sound address lies within the SRAM area
924 	if (m_vaquerro->sccs_out()==ASSERT_LINE)
925 	{
926 		LOGMASKED(LOG_MEM, "Write %04x (sound) <- %02x\n", m_logical_address, data);
927 		m_sound->write(data);         // Sound chip will lower READY after this access
928 		m_pending_write = false;
929 	}
930 	else
931 	{
932 		// SRAM
933 		if (m_amigo->sramcs_out()==ASSERT_LINE)
934 		{
935 			LOGMASKED(LOG_MEM, "Write %04x (SRAM) <- %02x\n", m_logical_address, data);
936 			m_sram->pointer()[m_logical_address & 0x07ff] = data;
937 			m_pending_write = false;
938 		}
939 	}
940 
941 	// Speech
942 	if (m_vaquerro->spwt_out()==ASSERT_LINE)
943 	{
944 		LOGMASKED(LOG_MEM, "Write %04x (speech) <- %02x\n", m_logical_address, data);
945 		m_speech->data_w(data);
946 		m_pending_write = false;
947 	}
948 
949 	if (!m_pending_write)
950 		cycle_end();
951 
952 	// The remaining physical devices will respond as soon as the physical address is completely set
953 }
954 
955 /*
956     Set 99/4A compatibility mode (CRUS=1)
957 */
WRITE_LINE_MEMBER(mainboard8_device::crus_in)958 WRITE_LINE_MEMBER( mainboard8_device::crus_in )
959 {
960 	LOGMASKED(LOG_CRU, "%s CRUS\n", (state==1)? "Assert" : "Clear");
961 	m_vaquerro->crus_in(state);
962 	m_amigo->crus_in(state);
963 	m_crus_debug = (line_state)state;
964 }
965 
966 /*
967     Set mapper /PTGEN line ("Pascal and Text-to-speech GROMs enable").
968     Note that PTGEN is negative logic.
969 */
WRITE_LINE_MEMBER(mainboard8_device::ptgen_in)970 WRITE_LINE_MEMBER( mainboard8_device::ptgen_in )
971 {
972 	LOGMASKED(LOG_CRU, "%s PTGEN*\n", (state==0)? "Assert" : "Clear");
973 	m_vaquerro->crusgl_in((state==0)? ASSERT_LINE : CLEAR_LINE);
974 }
975 
976 
977 /*
978     READY lines, to be combined
979 */
WRITE_LINE_MEMBER(mainboard8_device::system_grom_ready)980 WRITE_LINE_MEMBER( mainboard8_device::system_grom_ready )
981 {
982 	m_vaquerro->sgmry(state);
983 }
984 
WRITE_LINE_MEMBER(mainboard8_device::ptts_grom_ready)985 WRITE_LINE_MEMBER( mainboard8_device::ptts_grom_ready )
986 {
987 	m_vaquerro->tsgry(state);
988 }
989 
WRITE_LINE_MEMBER(mainboard8_device::p8_grom_ready)990 WRITE_LINE_MEMBER( mainboard8_device::p8_grom_ready )
991 {
992 	m_vaquerro->p8gry(state);
993 }
994 
WRITE_LINE_MEMBER(mainboard8_device::p3_grom_ready)995 WRITE_LINE_MEMBER( mainboard8_device::p3_grom_ready )
996 {
997 	m_vaquerro->p3gry(state);
998 }
999 
WRITE_LINE_MEMBER(mainboard8_device::sound_ready)1000 WRITE_LINE_MEMBER( mainboard8_device::sound_ready )
1001 {
1002 	m_sound_ready = state;
1003 }
1004 
WRITE_LINE_MEMBER(mainboard8_device::speech_ready)1005 WRITE_LINE_MEMBER( mainboard8_device::speech_ready )
1006 {
1007 	// The TMS5200 implementation uses true/false, not ASSERT/CLEAR semantics
1008 	m_speech_ready = (state==false)? ASSERT_LINE : CLEAR_LINE;
1009 }
1010 
WRITE_LINE_MEMBER(mainboard8_device::pbox_ready)1011 WRITE_LINE_MEMBER( mainboard8_device::pbox_ready )
1012 {
1013 	m_pbox_ready = state;
1014 }
1015 
WRITE_LINE_MEMBER(mainboard8_device::ggrdy_in)1016 WRITE_LINE_MEMBER( mainboard8_device::ggrdy_in )
1017 {
1018 	m_amigo->srdy_in((state==ASSERT_LINE && m_speech_ready && m_sound_ready && m_pbox_ready)? ASSERT_LINE : CLEAR_LINE);
1019 }
1020 
device_start()1021 void mainboard8_device::device_start()
1022 {
1023 	// Lines going to the main driver class, then to the CPU
1024 	m_ready.resolve_safe();         // READY
1025 	m_console_reset.resolve_safe(); // RESET
1026 	m_hold_line.resolve_safe();     // HOLD
1027 
1028 	m_rom0  = machine().root_device().memregion(TI998_ROM0_REG)->base();
1029 	m_rom1  = machine().root_device().memregion(TI998_ROM1_REG)->base();
1030 	m_pascalrom  = machine().root_device().memregion(TI998_PASCAL_REG)->base();
1031 
1032 	// Register state variables
1033 	save_item(NAME(m_A14_set));
1034 	save_item(NAME(m_logical_address));
1035 	save_item(NAME(m_physical_address));
1036 	save_item(NAME(m_pending_write));
1037 	save_item(NAME(m_latched_data));
1038 	save_item(NAME(m_gromclk));
1039 	save_item(NAME(m_prev_grom));
1040 	save_item(NAME(m_speech_ready));
1041 	save_item(NAME(m_sound_ready));
1042 	save_item(NAME(m_pbox_ready));
1043 	save_item(NAME(m_dbin_level));
1044 	save_item(NAME(m_last_ready));
1045 	save_item(NAME(m_sgrom_idle));
1046 	save_item(NAME(m_tsgrom_idle));
1047 	save_item(NAME(m_p8grom_idle));
1048 	save_item(NAME(m_p3grom_idle));
1049 }
1050 
device_reset()1051 void mainboard8_device::device_reset()
1052 {
1053 	m_last_ready = CLEAR_LINE;
1054 	m_speech_ready = true;
1055 	m_sound_ready = true;
1056 	m_pbox_ready = true;
1057 	m_pending_write = false;
1058 	m_prev_grom = 0;
1059 	m_A14_set = false;
1060 	// Configure RAM and AMIGO
1061 	m_amigo->connect_sram(m_sram->pointer());
1062 }
1063 
device_add_mconfig(machine_config & config)1064 void mainboard8_device::device_add_mconfig(machine_config &config)
1065 {
1066 	TI99_VAQUERRO(config, TI998_VAQUERRO_TAG, 0);
1067 	TI99_MOFETTA(config, TI998_MOFETTA_TAG, 0);
1068 	TI99_AMIGO(config, TI998_AMIGO_TAG, 0);
1069 	TI99_OSO(config, TI998_OSO_TAG, 0);
1070 }
1071 
1072 /***************************************************************************
1073   ===== VAQUERRO: Logical Address Space decoder =====
1074 
1075     Logical address space (LAS)
1076     ===========================
1077     The LAS is the address space as seen by the TMS 9995 CPU. It is 64 KiB large.
1078     The LAS can be configured in two ways:
1079     - the native (99/8) mode
1080     - and the compatibility mode (99/4A)
1081 
1082     Both modes are selected by CRU bit 20 on base 0000 (named "CRUS").
1083 
1084     The console starts up in compatibility mode.
1085 
1086     The compatibility mode organizes the LAS in a similar way as the TI-99/4A.
1087     This means that machine language programs should run with no or only minor
1088     changes. In particular, game cartridges work without problems.
1089 
1090     The native mode rearranges the address space and puts memory-mapped devices
1091     to other positions.
1092 
1093     TI-99/4A compatibility mode (CRUS=1)
1094     ------------------------------------
1095     0000-1fff: 2 KiB ROM0
1096     2000-7fff: Free area
1097     8000-87ff: 2 KiB SRAM
1098       8000-81ff: mapper files (8 files with 16*4 bytes each)
1099       8200-82ff: Free RAM
1100       8300-83ff: Scratch-pad RAM as in the 99/4A
1101       8400-840f: Sound chip
1102     8800-880f: VDP read port (data, status)
1103     8810-881f: Mapper access port
1104     8820-8bff: Free area
1105     8c00-8c0f: VDP write port (data, address)
1106     8c10-8fff: Free area
1107     9000-900f: Speech synthesizer read (on-board)
1108     9010-93ff: Free area
1109     9400-940f: Speech synthesizer write (on-board)
1110     9410-97ff: Free area
1111     9800-980f: System GROM read (data, address)
1112     9810-9bff: Free area
1113     9c00-9c0f: System GROM write (data, address)
1114     9c10-fffb: Free area
1115     fffc-ffff: NMI vector
1116 
1117     TI-99/8 native mode (CRUS=0)
1118     ----------------------------
1119     0000-efff: Free area
1120     f000-f7ff: 2 KiB SRAM
1121       f000-f1ff: mapper files (8 files with 16*4 bytes each)
1122       f200-f7ff: Free RAM
1123     f800-f80f: Sound chip
1124     f810-f81f: VDP read (data, status) and write (data, address)
1125     f820-f82f: Speech synthesizer read/write
1126     f830-f83f: System GROM read/write
1127     f840-f86f: Free area
1128     f870-f87f: Mapper access port
1129     f880-fffb: Free area
1130     fffc-ffff: NMI vector
1131 
1132     Note that ROM0 is not visible in the native mode.
1133 
1134     If CRU bit 21 (PTGEN*) is set to 0, Pascal GROMs appear in the LAS in either
1135     mode. It is highly recommended to use native mode when turning on these
1136     GROMs, because the area where they appear may be occupied by a program in
1137     99/4A mode.
1138 
1139     Pascal and Text-to-speech GROM enabled (PTGEN*=0)
1140     -------------------------------------------------
1141     f840-f84f: Text-to-speech GROM read/write
1142     f850-f85f: P-Code library #1 GROM read/write
1143     f860-f86f: P-Code library #2 GROM read/write
1144 
1145 
1146 ***************************************************************************/
1147 
vaquerro_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1148 vaquerro_device::vaquerro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1149 	: device_t(mconfig, TI99_VAQUERRO, tag, owner, clock),
1150 	m_crus(ASSERT_LINE),
1151 	m_crugl(ASSERT_LINE),
1152 	m_ggrdy(ASSERT_LINE)
1153 {
1154 }
1155 
set_address(offs_t offset,int state)1156 void vaquerro_device::set_address(offs_t offset, int state)
1157 {
1158 	// Do the decoding
1159 	// state = dbin, offset = address
1160 
1161 	bool reading = (state==ASSERT_LINE);
1162 	bool sgfap = false;
1163 	bool tsgfap = false;
1164 	bool p8gfap = false;
1165 	bool p3gfap = false;
1166 	bool vfap = false;
1167 
1168 	m_a14 = ((offset & 2)!=0)? ASSERT_LINE : CLEAR_LINE; // Needed for clock_in
1169 
1170 	m_dbin_level = (line_state)state;
1171 
1172 	int offbase = (offset & 0xfff1);
1173 
1174 	// ===================   TI (compatibility) mode   ======================
1175 	if (m_crus == ASSERT_LINE)
1176 	{
1177 		LOGMASKED(LOG_DETAIL, "Compatibility mode\n");
1178 
1179 		// SPRD (Speech read)
1180 		m_sprd = ((offbase==0x9000) && reading);
1181 
1182 		// SPWT (Speech write)
1183 		m_spwt = ((offbase==0x9400) && !reading);
1184 
1185 		// Sound
1186 		m_sccs = ((offbase==0x8400)&& !reading);
1187 
1188 		// ROM0
1189 		m_sromcs = (((offset & 0xe000)==0x0000) && reading);
1190 
1191 		// Video select
1192 		vfap = ((offbase==0x8800) && reading) || ((offbase==0x8c00) && !reading);
1193 
1194 		// System GROM
1195 		sgfap = ((offbase==0x9800) && reading) || ((offbase==0x9c00) && !reading);
1196 	}
1197 	// ======================   Native mode    ======================
1198 	else
1199 	{
1200 		LOGMASKED(LOG_DETAIL, "Native mode\n");
1201 
1202 		// SPRD (Speech read)
1203 		m_sprd = ((offbase==0xf820) && reading);
1204 
1205 		// SPWT (Speech write)
1206 		m_spwt = ((offbase==0xf820) && !reading);
1207 
1208 		// Sound
1209 		m_sccs = ((offbase==0xf800) && !reading);
1210 
1211 		// Video
1212 		vfap = (offbase==0xf810);
1213 
1214 		// System GROM (read and write)
1215 		sgfap = (offbase==0xf830);
1216 	}
1217 
1218 	// These lines are not decoded for compatibility or native mode, only
1219 	// the line CRUGL determines whether they become visible.
1220 	tsgfap = (offbase==0xf840) && m_crugl;
1221 	p8gfap = (offbase==0xf850) && m_crugl;
1222 	p3gfap = (offbase==0xf860) && m_crugl;
1223 
1224 	// The LASREQ line says whether Vaquerro does the job, or whether it is Mofetta's turn.
1225 	m_grom_or_video = sgfap || tsgfap || p8gfap || p3gfap || vfap ;
1226 
1227 	m_lasreq = (m_sprd || m_spwt || m_sccs || m_sromcs || m_grom_or_video);
1228 
1229 	LOGMASKED(LOG_DETAIL, "sgfap=%d tsgfap=%d p8gfap=%d p3gfap=%d vfap=%d\n", sgfap, tsgfap, p8gfap, p3gfap, vfap);
1230 
1231 	// Pass the selection to the wait state generators
1232 	// and pick up the current select line states
1233 	m_sgmws.select_in(sgfap);
1234 	m_tsgws.select_in(tsgfap);
1235 	m_p8gws.select_in(p8gfap);
1236 	m_p3gws.select_in(p3gfap);
1237 	m_vidws.select_in(vfap);
1238 
1239 	m_gromsel = m_sgmws.select_out() | m_tsgws.select_out() | m_p8gws.select_out() | m_p3gws.select_out();
1240 
1241 	m_vdprd = (reading && (m_vidws.select_out()!=0));
1242 	m_vdpwt = (!reading && (m_vidws.select_out()!=0));
1243 
1244 	if (m_grom_or_video)
1245 	{
1246 		// We don't see the current selection now; only with next clock pulse.
1247 		m_mainboard->ggrdy_in(m_sry);
1248 		LOGMASKED(LOG_READY, "GGRDY = %d\n", m_sry);
1249 	}
1250 }
1251 
WRITE_LINE_MEMBER(vaquerro_device::crusgl_in)1252 WRITE_LINE_MEMBER( vaquerro_device::crusgl_in )
1253 {
1254 	m_crugl = (state==ASSERT_LINE);
1255 }
1256 
WRITE_LINE_MEMBER(vaquerro_device::crus_in)1257 WRITE_LINE_MEMBER( vaquerro_device::crus_in )
1258 {
1259 	m_crus = (line_state)state;
1260 }
1261 
WRITE_LINE_MEMBER(vaquerro_device::memen_in)1262 WRITE_LINE_MEMBER( vaquerro_device::memen_in )
1263 {
1264 	m_memen = (state==ASSERT_LINE);
1265 }
1266 
1267 /*
1268     Called by Mofetta
1269 */
READ_LINE_MEMBER(vaquerro_device::lascsq_out)1270 READ_LINE_MEMBER( vaquerro_device::lascsq_out )
1271 {
1272 	return (m_lasreq && m_memen)? ASSERT_LINE : CLEAR_LINE;
1273 }
1274 
1275 /*
1276     Incoming ready lines from the GROM library
1277 */
WRITE_LINE_MEMBER(vaquerro_device::sgmry)1278 WRITE_LINE_MEMBER( vaquerro_device::sgmry )
1279 {
1280 	LOGMASKED(LOG_READY, "Incoming SGMRY = %d\n", state);
1281 	m_sgmws.ready_in((line_state)state);
1282 }
1283 
WRITE_LINE_MEMBER(vaquerro_device::tsgry)1284 WRITE_LINE_MEMBER( vaquerro_device::tsgry )
1285 {
1286 	LOGMASKED(LOG_READY, "Incoming TSGRY = %d\n", state);
1287 	m_tsgws.ready_in((line_state)state);
1288 }
1289 
WRITE_LINE_MEMBER(vaquerro_device::p8gry)1290 WRITE_LINE_MEMBER( vaquerro_device::p8gry )
1291 {
1292 	LOGMASKED(LOG_READY, "Incoming 8GRY = %d\n", state);
1293 	m_p8gws.ready_in((line_state)state);
1294 }
1295 
WRITE_LINE_MEMBER(vaquerro_device::p3gry)1296 WRITE_LINE_MEMBER( vaquerro_device::p3gry )
1297 {
1298 	LOGMASKED(LOG_READY, "Incoming P3GRY = %d\n", state);
1299 	m_p3gws.ready_in((line_state)state);
1300 }
1301 
1302 /*
1303     Outgoing READY
1304 */
READ_LINE_MEMBER(vaquerro_device::ggrdy_out)1305 READ_LINE_MEMBER( vaquerro_device::ggrdy_out )
1306 {
1307 	LOGMASKED(LOG_READY, "GGRDY out = %d\n", m_ggrdy);
1308 	return m_ggrdy;
1309 }
1310 
1311 /*
1312     Select lines
1313 */
1314 
1315 // =========================
1316 
gromcs_out()1317 int vaquerro_device::gromcs_out()
1318 {
1319 	return m_gromsel;
1320 }
1321 
1322 // =========================
1323 
READ_LINE_MEMBER(vaquerro_device::vdprd_out)1324 READ_LINE_MEMBER( vaquerro_device::vdprd_out )
1325 {
1326 	return (m_vdprd && m_memen)? ASSERT_LINE : CLEAR_LINE;
1327 }
1328 
READ_LINE_MEMBER(vaquerro_device::vdpwt_out)1329 READ_LINE_MEMBER( vaquerro_device::vdpwt_out )
1330 {
1331 	return (m_vdpwt && m_memen)? ASSERT_LINE : CLEAR_LINE;
1332 }
1333 
READ_LINE_MEMBER(vaquerro_device::sprd_out)1334 READ_LINE_MEMBER( vaquerro_device::sprd_out )
1335 {
1336 	return (m_sprd && m_memen)? ASSERT_LINE : CLEAR_LINE;
1337 }
1338 
READ_LINE_MEMBER(vaquerro_device::spwt_out)1339 READ_LINE_MEMBER( vaquerro_device::spwt_out )
1340 {
1341 	return (m_spwt && m_memen)? ASSERT_LINE : CLEAR_LINE;
1342 }
1343 
READ_LINE_MEMBER(vaquerro_device::sromcs_out)1344 READ_LINE_MEMBER( vaquerro_device::sromcs_out )
1345 {
1346 	return (m_sromcs && m_memen)? ASSERT_LINE : CLEAR_LINE;
1347 }
1348 
READ_LINE_MEMBER(vaquerro_device::sccs_out)1349 READ_LINE_MEMBER( vaquerro_device::sccs_out )
1350 {
1351 	return (m_sccs && m_memen)? ASSERT_LINE : CLEAR_LINE;
1352 }
1353 
1354 /*
1355     Incoming clock signal.
1356 
1357     The Vaquerro has a Wait State generation logic circuit for the video
1358     processor and all 4 GROM libraries. Each one has its separate generator.
1359     The GROMs get a 16 cycle wait period after their access, while the video
1360     processors gets an 8 cycle wait period. If during that period another
1361     access occurs, the system READY line will be cleared, triggering wait
1362     states in the CPU.
1363 */
WRITE_LINE_MEMBER(vaquerro_device::clock_in)1364 WRITE_LINE_MEMBER( vaquerro_device::clock_in )
1365 {
1366 	line_state level = (line_state)state;
1367 
1368 	// Propagate to the wait state generators (note that we need both clock levels)
1369 	m_sgmws.clock_in(level);
1370 	m_tsgws.clock_in(level);
1371 	m_p8gws.clock_in(level);
1372 	m_p3gws.clock_in(level);
1373 	m_vidws.clock_in(level);
1374 
1375 	// Collect the selections
1376 	// Each one has its own indication, defined at init time
1377 	m_gromsel = m_sgmws.select_out() | m_tsgws.select_out() | m_p8gws.select_out() | m_p3gws.select_out();
1378 
1379 	bool reading = (m_dbin_level==ASSERT_LINE);
1380 
1381 	m_vdprd = (reading && (m_vidws.select_out()!=0));
1382 	m_vdpwt = (!reading && (m_vidws.select_out()!=0));
1383 
1384 	// Get the READY levels from the GROMs
1385 	if (level==CLEAR_LINE)
1386 	{
1387 		m_sry = m_sgmws.ready_out() || m_tsgws.ready_out() || m_p8gws.ready_out() || m_p3gws.ready_out() || m_vidws.ready_out();
1388 		LOGMASKED(LOG_WS, "ready_out = (%d, %d, %d, %d, %d)\n", m_sgmws.ready_out(), m_tsgws.ready_out(), m_p8gws.ready_out(), m_p3gws.ready_out(),m_vidws.ready_out());
1389 	}
1390 
1391 	// If the output gate is closed, propagate ASSERT_LINE (pulled up)
1392 	m_ggrdy = (!m_grom_or_video || m_sry)? ASSERT_LINE : CLEAR_LINE;
1393 }
1394 
1395 
device_start()1396 void vaquerro_device::device_start()
1397 {
1398 	m_mainboard = downcast<mainboard8_device*>(owner());
1399 	m_sgmws.init(SGMSEL);
1400 	m_tsgws.init(TSGSEL);
1401 	m_p8gws.init(P8GSEL);
1402 	m_p3gws.init(P3GSEL);
1403 	m_vidws.init(VIDSEL);
1404 
1405 	save_item(NAME(m_memen));
1406 	save_item(NAME(m_video_wait));
1407 	save_item(NAME(m_crus));
1408 	save_item(NAME(m_crugl));
1409 	save_item(NAME(m_lasreq));
1410 	save_item(NAME(m_grom_or_video));
1411 	save_item(NAME(m_spwt));
1412 	save_item(NAME(m_sccs));
1413 	save_item(NAME(m_sromcs));
1414 	save_item(NAME(m_sprd));
1415 	save_item(NAME(m_vdprd));
1416 	save_item(NAME(m_vdpwt));
1417 	save_item(NAME(m_gromsel));
1418 	save_item(NAME(m_ggrdy));
1419 	save_item(NAME(m_sry));
1420 	save_item(NAME(m_a14));
1421 	save_item(NAME(m_dbin_level));
1422 
1423 	// FIXME: In rare occasions, the saved state is invalid and restoring
1424 	// may crash the emulated 99/8 (e.g. with invalid opcodes)
1425 	// Saving the wait state logic does not affect the operation, as it seems,
1426 	// so we leave it out.
1427 }
1428 
device_reset()1429 void vaquerro_device::device_reset()
1430 {
1431 	m_ggrdy = ASSERT_LINE;
1432 	m_vdpwt = m_vdprd = CLEAR_LINE;
1433 	m_gromsel = 0;
1434 	m_sgmws.treset_in(ASSERT_LINE);
1435 	m_tsgws.treset_in(ASSERT_LINE);
1436 	m_p8gws.treset_in(ASSERT_LINE);
1437 	m_p3gws.treset_in(ASSERT_LINE);
1438 	m_vidws.treset_in(ASSERT_LINE);
1439 }
1440 
1441 /*
1442     Wait state generation logic inside Vaquerro
1443 
1444     Analysis of the logic diagram of the Vaquerro delivers the following
1445     behavior (for the first GROM library; similar behavior applies for the
1446     other libraries). Note that the CLKOUT line is inverted.
1447 
1448     1. When the GROMs are unselected by address (SGFAP), the SRY line is Z
1449        (System READY). The GROM ready line (SGMRY) has no effect.
1450     2. When SGFAP is asserted while the internal counter is off, the
1451        READY line changes from Z to Low and the GROM select line (SGCS) is
1452        asserted (both immediately, before the next tick edge). SGMRY has no effect.
1453        The circuit state is constant during further clock ticks.
1454     3. After being selected, when SGMRY is asserted (GROM is ready), SRY
1455        changes to High on the next trailing edge. This will allow the
1456        CPU to complete the GROM access on the next cycle,
1457        and the address bus will change, typically deselecting the GROMs.
1458        Until this deselection, the circuit state remains constant
1459        (SGCS asserted, READY=H).
1460     4. When the GROMs are deselected, SRY changes to Z, and SGCS is cleared
1461        (immediately). A counter is started at 0 that is incremented on each clock
1462        tick (leading edge).
1463     5. When SGFAP is asserted while the counter is less that 15, SRY changes
1464        to Low immediately. SGCS remains cleared, so the GROMs are not selected.
1465        While SGFAP stays cleared, the counter completes its way to 15,
1466        then 0, and turns off.
1467     6. When the counter reaches 15, it returns to 0 on the next tick
1468        (leading). On the following trailing edge, the GROM select line is
1469        asserted, while the READY line remains Low.
1470     7. Continue at 3.
1471 */
select_in(bool addressed)1472 void vaquerro_device::waitstate_generator::select_in(bool addressed)
1473 {
1474 	m_addressed = addressed;
1475 }
1476 
select_out()1477 int vaquerro_device::waitstate_generator::select_out()
1478 {
1479 	return (!m_counting && m_addressed)? m_selvalue : 0;
1480 }
1481 
1482 /*
1483     Should be low by default.
1484 */
ready_out()1485 line_state vaquerro_device::waitstate_generator::ready_out()
1486 {
1487 	return (m_ready && !m_counting && m_generate)? ASSERT_LINE : CLEAR_LINE;
1488 }
1489 
is_counting()1490 bool vaquerro_device::waitstate_generator::is_counting()
1491 {
1492 	return m_counting;
1493 }
1494 
is_generating()1495 bool vaquerro_device::waitstate_generator::is_generating()
1496 {
1497 	return m_generate;
1498 }
1499 
is_ready()1500 bool vaquerro_device::waitstate_generator::is_ready()
1501 {
1502 	return m_ready;
1503 }
1504 
1505 /*
1506     READY in. This may only show an effect with the next trailing edge of CLKOUT.
1507 */
ready_in(line_state ready)1508 void vaquerro_device::grom_waitstate_generator::ready_in(line_state ready)
1509 {
1510 	m_ready = (ready==ASSERT_LINE);
1511 }
1512 
clock_in(line_state clkout)1513 void vaquerro_device::grom_waitstate_generator::clock_in(line_state clkout)
1514 {
1515 	if (clkout == ASSERT_LINE)
1516 	{
1517 		if (m_counting) m_counter++;
1518 	}
1519 	else
1520 	{
1521 		if (m_counting && m_counter==16)
1522 		{
1523 			m_counter = 0;
1524 			m_counting = false;
1525 		}
1526 		else
1527 		{
1528 			if (!m_addressed && m_generate) m_counting = true;
1529 			m_generate = ((m_addressed || m_counting) && (m_counter != 15));
1530 		}
1531 	}
1532 }
1533 
treset_in(line_state reset)1534 void vaquerro_device::waitstate_generator::treset_in(line_state reset)
1535 {
1536 	if (reset==ASSERT_LINE)
1537 	{
1538 		m_counter = 0;
1539 		m_generate = m_counting = m_addressed = false;
1540 	}
1541 }
1542 
clock_in(line_state clkout)1543 void vaquerro_device::video_waitstate_generator::clock_in(line_state clkout)
1544 {
1545 	if (clkout == ASSERT_LINE)
1546 	{
1547 		if (m_counting) m_counter++;
1548 	}
1549 	else
1550 	{
1551 		if (m_counting && m_counter==7)
1552 		{
1553 			m_counter = 0;
1554 			m_counting = false;
1555 		}
1556 		else
1557 		{
1558 			if (!m_addressed && m_generate) m_counting = true;
1559 			m_generate = ((m_addressed || m_counting) && (m_counter != 6));
1560 		}
1561 	}
1562 }
1563 
1564 /***************************************************************************
1565   ===== MOFETTA: Physical Address Space decoder =====
1566 
1567      Physical address space (PAS)
1568      ============================
1569      The PAS is 24 bits wide and accessed via the custom mapper chip nicknamed
1570      "Amigo". The mapper exchanges map definitions with SRAM (see LAS). That
1571      means, a map can be prepared in SRAM, and for activating it, the mapper
1572      is accessed on its port, telling it to load or save a map.
1573 
1574      000000-00ffff: 64 KiB console DRAM
1575      010000-efffff: undefined
1576 
1577      f00000-f03fff: PASCAL support ROM (not mentioned in [1])
1578 
1579      f04000-feffff: undefined
1580      ff0000       : unmapped (code for mapper)
1581      ff0001-ff3fff: undefined
1582      ff4000-ff5fff: DSR ROM in Peripheral Box, Hexbus DSR (CRU 1700) or additional ROM (CRU 2700)
1583      ff6000-ff9fff: Cartridge ROM space
1584      ffa000-ffdfff: 16 KiB ROM1
1585      ffe000-ffe00f: Interrupt level sense
1586      ffe010-ffffff: undefined
1587 
1588 
1589 ***************************************************************************/
1590 
1591 enum
1592 {
1593 	UNDEF=0,
1594 	DRAM,
1595 	PASCAL,
1596 	INTERNAL
1597 };
1598 
mofetta_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1599 mofetta_device::mofetta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1600 	: device_t(mconfig, TI99_MOFETTA, tag, owner, clock),
1601 	m_gotfirstword(false)
1602 {
1603 }
1604 
set_address(offs_t offset,int state)1605 void mofetta_device::set_address(offs_t offset, int state)
1606 {
1607 	if (!m_gotfirstword)
1608 	{
1609 		// Store the first word and wait for clearing of MSAST
1610 		LOGMASKED(LOG_MOFETTA, "Got the upper word of the address: %04x\n", offset);
1611 		m_address_latch = offset;
1612 	}
1613 	else
1614 	{
1615 		// Second part - now decode the address
1616 		LOGMASKED(LOG_MOFETTA, "Got the lower word of the address: %04x\n", offset);
1617 
1618 		bool acs, tcs, rcs, acsx;
1619 		bool reading = (state==ASSERT_LINE);
1620 		int offbase = (offset & 0xe000);
1621 
1622 		// PASCAL ROM select (16K)
1623 		m_prcs = (m_prefix == 0xf0) && ((offset & 0xc000) == 0x0000);
1624 
1625 		// Hexbus select
1626 		acs = (m_prefix == 0xff) && (offbase == 0x4000) && m_alcpg;
1627 
1628 		// Internal DSR select (ff4000-ff5fff @ CRU>2700)
1629 		tcs = (m_prefix == 0xff) && (offbase == 0x4000) && m_txspg;
1630 
1631 		// Hexbus select (ff4000-ff5fef @ CRU>1700), excluding OSO
1632 		acsx = acs && ((offset & 0x1ff0)!=0x1ff0);
1633 
1634 		// Upper 16K of ROM1
1635 		m_rom1am = !((offbase == 0xa000) || (offbase == 0xc000));
1636 
1637 		// ROM select
1638 		rcs = (m_prefix == 0xff) && reading && !m_rom1am;
1639 
1640 		// ROM1 select (containing 16K ROM, 8K TTS, 8K ACS)
1641 		m_rom1cs = tcs || rcs || acsx;
1642 
1643 		// Accessing OSO (ff5ff0 @ CRU>1700)
1644 		m_alccs = acs && ((offset & 0x1ff0)==0x1ff0);
1645 
1646 		// Second half of ROM or ACS
1647 		m_rom1al = reading && (m_prefix == 0xff) && ((offbase == 0xc000) || acs);
1648 
1649 		// Cartridge port (ff6000-ff9fff)
1650 		m_cmas = (m_prefix == 0xff) && ((offbase == 0x6000) || (offbase == 0x8000));
1651 
1652 		m_gotfirstword = false;
1653 	}
1654 }
1655 
1656 /*
1657     Mofetta delivers the GROMCLK. In the 99/4A, this clock is produced by the VDP.
1658     Apart from that, Mofetta does not need the CLKOUT.
1659 */
WRITE_LINE_MEMBER(mofetta_device::clock_in)1660 WRITE_LINE_MEMBER( mofetta_device::clock_in )
1661 {
1662 	if (state == CLEAR_LINE)    // TODO: Correct edge?
1663 	{
1664 		m_gromclock_count++;
1665 		if (m_gromclock_count >=3)
1666 		{
1667 			m_gromclk_up = !m_gromclk_up;
1668 			m_gromclock_count = 0;
1669 		}
1670 	}
1671 }
1672 
READ_LINE_MEMBER(mofetta_device::alccs_out)1673 READ_LINE_MEMBER( mofetta_device::alccs_out )
1674 {
1675 	return (m_alccs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1676 }
1677 
READ_LINE_MEMBER(mofetta_device::gromclk_out)1678 READ_LINE_MEMBER( mofetta_device::gromclk_out )
1679 {
1680 	return m_gromclk_up? ASSERT_LINE : CLEAR_LINE;
1681 }
1682 
READ_LINE_MEMBER(mofetta_device::rom1cs_out)1683 READ_LINE_MEMBER( mofetta_device::rom1cs_out )
1684 {
1685 	return (m_rom1cs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1686 }
1687 
READ_LINE_MEMBER(mofetta_device::rom1am_out)1688 READ_LINE_MEMBER( mofetta_device::rom1am_out )
1689 {
1690 	return (m_rom1am && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1691 }
1692 
READ_LINE_MEMBER(mofetta_device::rom1al_out)1693 READ_LINE_MEMBER( mofetta_device::rom1al_out )
1694 {
1695 	return (m_rom1al && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1696 }
1697 
READ_LINE_MEMBER(mofetta_device::prcs_out)1698 READ_LINE_MEMBER( mofetta_device::prcs_out )
1699 {
1700 	return (m_prcs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1701 }
1702 
READ_LINE_MEMBER(mofetta_device::cmas_out)1703 READ_LINE_MEMBER( mofetta_device::cmas_out )
1704 {
1705 	return (m_cmas && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
1706 }
1707 
1708 /*
1709     Asserted when a PEB access occurs
1710 */
READ_LINE_MEMBER(mofetta_device::dbc_out)1711 READ_LINE_MEMBER( mofetta_device::dbc_out )
1712 {
1713 	return (m_lasreq || m_cmas || m_rom1cs || m_skdrcs || !m_pmemen)? CLEAR_LINE : ASSERT_LINE;
1714 }
1715 
1716 /*
1717     Debugger support
1718 */
hexbus_access_debug()1719 bool mofetta_device::hexbus_access_debug()
1720 {
1721 	return m_alcpg;
1722 }
1723 
intdsr_access_debug()1724 bool mofetta_device::intdsr_access_debug()
1725 {
1726 	return m_txspg;
1727 }
1728 
cruwrite(offs_t offset,uint8_t data)1729 void mofetta_device::cruwrite(offs_t offset, uint8_t data)
1730 {
1731 	if ((offset & 0xff00)==0x2700)
1732 	{
1733 		if ((offset & 0x0002)!=0)
1734 		{
1735 			// SWRST (Software reset)
1736 			// Value seems to be irrelevant
1737 			LOGMASKED(LOG_CRU, "Doing a software reset by SBO 2702\n");
1738 			m_mainboard->reset_console(ASSERT_LINE);
1739 			m_mainboard->reset_console(CLEAR_LINE);
1740 		}
1741 		else
1742 		{
1743 			m_txspg = (data!=0);        // CRU>2700
1744 			LOGMASKED(LOG_CRU, "Turning %s CRU>2700\n", m_txspg? "on" : "off");
1745 		}
1746 	}
1747 	else
1748 	{
1749 		if ((offset & 0xff00)==0x1700)
1750 		{
1751 			m_alcpg = (data!=0);        // CRU>1700
1752 			LOGMASKED(LOG_CRU, "Turning %s CRU>1700\n", m_alcpg? "on" : "off");
1753 		}
1754 	}
1755 }
1756 
1757 /*
1758     Setting or clearing the MSAST line.
1759 */
WRITE_LINE_MEMBER(mofetta_device::msast_in)1760 WRITE_LINE_MEMBER( mofetta_device::msast_in )
1761 {
1762 	if (state == ASSERT_LINE)
1763 	{
1764 		if (m_msast == CLEAR_LINE)      // Leading edge
1765 		{
1766 			m_gotfirstword = true; // Process first word
1767 			// We now have the first part, containing the flags and the upper byte.
1768 			m_prefix = m_address_latch & 0xff;
1769 		}
1770 	}
1771 	// TODO: Evaluate the first three bits
1772 	m_msast = (line_state)state;
1773 }
1774 
WRITE_LINE_MEMBER(mofetta_device::pmemen_in)1775 WRITE_LINE_MEMBER( mofetta_device::pmemen_in )
1776 {
1777 	m_pmemen = (state==ASSERT_LINE);
1778 }
1779 
WRITE_LINE_MEMBER(mofetta_device::lascs_in)1780 WRITE_LINE_MEMBER( mofetta_device::lascs_in )
1781 {
1782 	m_lasreq = (state==ASSERT_LINE);
1783 }
1784 
WRITE_LINE_MEMBER(mofetta_device::skdrcs_in)1785 WRITE_LINE_MEMBER( mofetta_device::skdrcs_in )
1786 {
1787 	m_skdrcs = (state==ASSERT_LINE);
1788 }
1789 
device_start()1790 void mofetta_device::device_start()
1791 {
1792 	m_mainboard = downcast<mainboard8_device*>(owner());
1793 
1794 	save_item(NAME(m_pmemen));
1795 	save_item(NAME(m_lasreq));
1796 	save_item(NAME(m_skdrcs));
1797 	save_item(NAME(m_gromclk_up));
1798 	save_item(NAME(m_gotfirstword));
1799 	save_item(NAME(m_address_latch));
1800 	save_item(NAME(m_prefix));
1801 	save_item(NAME(m_alcpg));
1802 	save_item(NAME(m_txspg));
1803 	save_item(NAME(m_rom1cs));
1804 	save_item(NAME(m_rom1am));
1805 	save_item(NAME(m_rom1al));
1806 	save_item(NAME(m_alccs));
1807 	save_item(NAME(m_prcs));
1808 	save_item(NAME(m_cmas));
1809 	save_item(NAME(m_gromclock_count));
1810 	save_item(NAME(m_msast));
1811 }
1812 
device_reset()1813 void mofetta_device::device_reset()
1814 {
1815 	m_gotfirstword = false;
1816 	m_alcpg = false;
1817 	m_txspg = false;
1818 	m_prefix = 0;
1819 }
1820 
1821 /***************************************************************************
1822 
1823   ==============================
1824     Mapper (codename "Amigo")
1825   ==============================
1826 
1827     Unfortunately, we do not have logic diagrams for Amigo, so we have to
1828     guess how it is actually working.
1829 
1830     Initial setting of mapper (as defined in the power-up routine, TI-99/4A mode)
1831 
1832     0   00ff0000 -> Unmapped; logical address 0000...0fff = ROM0
1833     1   00ff0000 -> Unmapped; logical address 1000...1fff = ROM0
1834     2   00000800 -> DRAM; 2000 = 000800, 2fff = 0017ff
1835     3   00001800 -> DRAM; 3000 = 001800, 3fff = 0027ff
1836     4   00ff4000 -> DSR space (internal / ioport)
1837     5   00ff5000 -> DSR space (internal / ioport)
1838     6   00ff6000 -> Cartridge space (6000..6fff)
1839     7   00ff7000 -> Cartridge space (7000..7fff)
1840     8   00ff0000 -> Unmapped; device ports (VDP) and SRAM
1841     9   00ff0000 -> Unmapped; device ports (Speech, GROM)
1842     A   00002800 -> DRAM; a000 = 002800, afff = 0037ff
1843     B   00003800 -> DRAM; b000 = 003800, bfff = 0047ff
1844     C   00004800 -> DRAM; c000 = 004800, cfff = 0057ff
1845     D   00005800 -> DRAM; d000 = 005800, dfff = 0067ff
1846     E   00006800 -> DRAM; e000 = 006800, efff = 0077ff
1847     F   00007800 -> DRAM; f000 = 007800, ffff = 0087ff
1848 
1849     Format of map table entry
1850 
1851     +--+---+---+---+---+---+---+---+ +-----------+ +----------+ +---------+
1852     | W| X | R | 0 | 0 | 0 | 0 | 0 | | Upper (8) | | High (8) | | Low (8) |
1853     +--+---+---+---+---+---+---+---+ +-----------+ +----------+ +---------+
1854 
1855     W: Write protection if set to 1
1856     X: Execute protection if set to 1
1857     R: Read protection if set to 1
1858 
1859     When a protection violation occurs, the tms9901 INT1* pin is pulled low
1860     (active).  The pin remains low until the mapper status register is read.
1861 
1862     Address handling
1863     ----------------
1864     Physical address is (Upper * 2^16) + (High * 2^8) + Low
1865 
1866     The mapper calculates the actual physical address by looking up the
1867     table entry from the first four bits of the logical address and then
1868     *adding* the remaining 12 bits of the logical address on the map value.
1869 
1870     The value 0xff0000 is used to indicate a non-mapped area.
1871 
1872     Mapper control register
1873     -----------------------
1874     The mapper control register is used to initiate a map load/save operation.
1875 
1876     +---+---+---+---+---+---+---+---+
1877     | 0 | 0 | 0 | 0 | Map File  | RW|
1878     +---+---+---+---+---+---+---+---+
1879 
1880     The map file is a number from 0-7 indicating the set of map values for the
1881     operation, which means the location in SRAM where the next 64 values are
1882     loaded from or stored into.
1883 
1884     RW = 1: load from SRAM into mapper
1885     RW = 0: store from mapper into SRAM
1886 
1887     When read, the mapper register returns the violation flags:
1888     +---+---+---+---+---+---+---+---+
1889     | W | X | R | 0 | 0 | 0 | 0 | 0 |
1890     +---+---+---+---+---+---+---+---+
1891 
1892 ***************************************************************************/
1893 
amigo_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1894 amigo_device::amigo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1895 	: device_t(mconfig, TI99_AMIGO, tag, owner, clock),
1896 	m_logical_space(true),
1897 	m_crus(ASSERT_LINE)
1898 {
1899 }
1900 
1901 enum
1902 {
1903 	IDLE = 0,
1904 	CREATE_PADDR,
1905 	ADDR_MSW,
1906 	ADDR_LSW,
1907 	SRAMLOAD,
1908 	SRAMSAVE
1909 };
1910 
1911 /*
1912     Debugger support
1913 */
get_physical_address_debug(offs_t offset)1914 int amigo_device::get_physical_address_debug(offs_t offset)
1915 {
1916 	return  ((offset & 0x0fff) + m_base_register[(offset >> 12) & 0x000f]) & 0x00ffffff;
1917 }
1918 
1919 /*
1920     Incoming READY line (SRDY)
1921 */
WRITE_LINE_MEMBER(amigo_device::srdy_in)1922 WRITE_LINE_MEMBER( amigo_device::srdy_in )
1923 {
1924 	LOGMASKED(LOG_READY, "Incoming SRDY = %d\n", state);
1925 	m_srdy = (line_state)state;
1926 
1927 	// If the access is going to logical space, pass through the READY line
1928 	if (m_logical_space)
1929 	{
1930 		LOGMASKED(LOG_CPURY, "Setting CPURY = %d (SRDY)\n", m_ready_out);
1931 		m_ready_out = m_srdy;
1932 	}
1933 }
1934 
WRITE_LINE_MEMBER(amigo_device::memen_in)1935 WRITE_LINE_MEMBER( amigo_device::memen_in )
1936 {
1937 	m_memen = (state==ASSERT_LINE);
1938 }
1939 
1940 /*
1941     Polled from the mainboard
1942 */
READ_LINE_MEMBER(amigo_device::cpury_out)1943 READ_LINE_MEMBER( amigo_device::cpury_out )
1944 {
1945 	return m_ready_out;
1946 }
1947 
1948 /*
1949     Polled from the mainboard
1950 */
READ_LINE_MEMBER(amigo_device::sramcs_out)1951 READ_LINE_MEMBER( amigo_device::sramcs_out )
1952 {
1953 	return m_sram_accessed && m_memen? ASSERT_LINE : CLEAR_LINE;
1954 }
1955 
1956 /*
1957     SKDRCS line (maybe "Sixty-four Kilobyte DRam Chip Select"). We assume that
1958     Amigo asserts the select line not before the whole address was written.
1959     This is actually more than needed because we only have 64K DRAM (which
1960     would only need a 16 bit address), and Amigo itself selects it.
1961 */
READ_LINE_MEMBER(amigo_device::skdrcs_out)1962 READ_LINE_MEMBER( amigo_device::skdrcs_out )
1963 {
1964 	return m_dram_accessed && (m_amstate == IDLE) && m_memen? ASSERT_LINE : CLEAR_LINE;
1965 }
1966 
1967 /*
1968     Incoming CRUS line. Needed to set the mapper config addresses.
1969 */
WRITE_LINE_MEMBER(amigo_device::crus_in)1970 WRITE_LINE_MEMBER( amigo_device::crus_in )
1971 {
1972 	m_crus = (line_state)state;
1973 }
1974 
1975 /*
1976     Incoming LASCS line.
1977 */
WRITE_LINE_MEMBER(amigo_device::lascs_in)1978 WRITE_LINE_MEMBER( amigo_device::lascs_in )
1979 {
1980 	m_logical_space = (state==ASSERT_LINE);
1981 }
1982 
1983 /*
1984     The logical address bus has been set. The Amigo chip now has to map this
1985     address to a physical address. There are three phases (3 clock ticks):
1986     1. Sample the logical address lines, determine the map register
1987        (first four bits), create the physical address by adding the remaining
1988        12 bits and the map register contents
1989     2. Set the physical address bus with the first 16 bits of the physical
1990        address. Assert the MSAST line.
1991     3. Set the physical address bus with the second 16 bits of the physical
1992        address. Clear the MSAST line. Forward any incoming READY=0 to the CPU.
1993 */
set_address(offs_t offset)1994 uint8_t amigo_device::set_address(offs_t offset)
1995 {
1996 	// Check whether the mapper itself is accessed
1997 	int mapaddr = (m_crus==ASSERT_LINE)? 0x8810 : 0xf870;
1998 	m_mapper_accessed = ((offset & 0xfff1)==mapaddr);
1999 
2000 	// or SRAM
2001 	int sramaddr = (m_crus==ASSERT_LINE)? 0x8000 : 0xf000;
2002 	m_sram_accessed = ((offset & 0xf800)==sramaddr);
2003 
2004 	m_logical_space |= (m_mapper_accessed || m_sram_accessed);
2005 
2006 	// Is the address not in the logical address space?
2007 	if (!m_logical_space)
2008 	{
2009 		LOGMASKED(LOG_AMIGO, "Amigo decoding; %04x is a physical address.\n", offset);
2010 		// Build the physical address
2011 		// The first three bits are the protection bits (Write, Execute, Read)
2012 		// Theoretically, the addition of the logical address could mess up those
2013 		// first three bits, but the physical address is only 24 bits wide, so we
2014 		// have a space of 5 zeros between the protection bits and the address.
2015 		// We should just clear those five bits after the addition.
2016 
2017 		m_physical_address = ((offset & 0x0fff) + m_base_register[(offset >> 12) & 0x000f]) & 0x00ffffff;
2018 
2019 		// TODO: Process flags
2020 
2021 		// Is it DRAM?
2022 		m_dram_accessed = (m_physical_address & 0x00ff0000)==0;
2023 
2024 		// This takes one clock pulse.
2025 		m_amstate = CREATE_PADDR;
2026 
2027 		// Pull down READY
2028 		m_ready_out = CLEAR_LINE;
2029 
2030 		LOGMASKED(LOG_CPURY, "Setting CPURY = %d (PAS)\n", m_ready_out);
2031 	}
2032 	else
2033 	{
2034 		// This was a logical space access. Pass through READY.
2035 		m_dram_accessed = false;
2036 		m_amstate = IDLE;
2037 		m_ready_out = m_srdy;
2038 		LOGMASKED(LOG_CPURY, "Setting CPURY = %d (LAS)\n", m_ready_out);
2039 	}
2040 
2041 	return 0;
2042 }
2043 
2044 /*
2045     Read the mapper status bits
2046 */
read()2047 uint8_t amigo_device::read()
2048 {
2049 	// Read the protection status bits and reset them
2050 	uint8_t value = m_protflag;
2051 	m_protflag = 0;
2052 	return value;
2053 }
2054 
2055 /*
2056     Configure the mapper. This is the only reason to write to the AMIGO.
2057 */
write(uint8_t data)2058 void amigo_device::write(uint8_t data)
2059 {
2060 	// Load or save map file
2061 	if ((data & 0xf0)==0x00)
2062 	{
2063 		// Need to HOLD the CPU
2064 		m_amstate = ((data & 1)==1)? SRAMLOAD : SRAMSAVE;
2065 		m_sram_address = (data & 0x0e) << 5;
2066 		m_hold_acknowledged = false;
2067 		m_basereg = 0;
2068 		m_mapvalue = 0;
2069 		m_mainboard->hold_cpu(ASSERT_LINE);
2070 	}
2071 	else LOGMASKED(LOG_WARN, "Invalid value written to Amigo: %02x\n", data);
2072 }
2073 
WRITE_LINE_MEMBER(amigo_device::clock_in)2074 WRITE_LINE_MEMBER( amigo_device::clock_in )
2075 {
2076 	if (state==CLEAR_LINE)
2077 	{
2078 		switch (m_amstate)
2079 		{
2080 		case IDLE:
2081 			break;
2082 		case CREATE_PADDR:
2083 			// Address has been created
2084 			m_amstate = ADDR_MSW;
2085 			break;
2086 		case ADDR_MSW:
2087 			// Transmit the first word (without the protection bits)
2088 			m_mainboard->set_paddress((m_physical_address >> 16) & 0x00ff);
2089 			m_amstate = ADDR_LSW;
2090 			break;
2091 		case ADDR_LSW:
2092 			m_mainboard->msast_in(ASSERT_LINE); // Pulse MSAST
2093 			m_mainboard->msast_in(CLEAR_LINE);
2094 			m_mainboard->set_paddress(m_physical_address & 0xffff);
2095 			m_amstate = IDLE;
2096 			m_ready_out = m_srdy;   // Propagate incoming READY
2097 			break;
2098 
2099 		case SRAMLOAD:
2100 			if (m_hold_acknowledged) mapper_load();
2101 			break;
2102 
2103 		case SRAMSAVE:
2104 			if (m_hold_acknowledged) mapper_save();
2105 			break;
2106 
2107 		default:
2108 			LOGMASKED(LOG_WARN, "Invalid state in mapper: %d\n", m_amstate);
2109 		}
2110 	}
2111 }
2112 
mapper_load()2113 void amigo_device::mapper_load()
2114 {
2115 	m_mapvalue = (m_mapvalue << 8)  | m_sram[m_sram_address++];
2116 
2117 	if ((m_sram_address & 0x03)==0)
2118 	{
2119 		LOGMASKED(LOG_MAP, "Loaded basereg %02d = %08x\n", m_basereg, m_mapvalue);
2120 		m_base_register[m_basereg++] = m_mapvalue;
2121 	}
2122 	if (m_basereg == 16)
2123 	{
2124 		m_amstate = IDLE;
2125 		m_mainboard->hold_cpu(CLEAR_LINE);
2126 	}
2127 }
2128 
mapper_save()2129 void amigo_device::mapper_save()
2130 {
2131 	if ((m_sram_address & 0x03)==0)
2132 	{
2133 		if (m_basereg == 16)
2134 		{
2135 			m_amstate = IDLE;
2136 			m_mainboard->hold_cpu(CLEAR_LINE);
2137 			return;
2138 		}
2139 		else
2140 		{
2141 			m_mapvalue = m_base_register[m_basereg];
2142 			LOGMASKED(LOG_MAP, "Saving basereg %02d = %08x\n", m_basereg, m_mapvalue);
2143 			m_basereg++;
2144 		}
2145 	}
2146 
2147 	m_sram[m_sram_address++] = (m_mapvalue >> 24) & 0xff;
2148 	m_mapvalue = m_mapvalue << 8;
2149 }
2150 
2151 /*
2152     Debugger support
2153 */
mapper_access_debug(int data)2154 void amigo_device::mapper_access_debug(int data)
2155 {
2156 	if ((data & 0xf0)==0x00)
2157 	{
2158 		int address = (data & 0x0e) << 5;
2159 
2160 		if ((data & 1)==1)
2161 		{
2162 			for (int i=0; i < 64; i++)
2163 			{
2164 				// Load from SRAM
2165 				m_base_register[i/4] = (m_base_register[i/4] << 8) | (m_sram[address++] & 0xff);
2166 			}
2167 		}
2168 		else
2169 		{
2170 			for (int i=0; i < 16; i++)
2171 			{
2172 				// Save to SRAM
2173 				m_sram[address++] = (m_base_register[i] >> 24) & 0xff;
2174 				m_sram[address++] = (m_base_register[i] >> 16) & 0xff;
2175 				m_sram[address++] = (m_base_register[i] >> 8) & 0xff;
2176 				m_sram[address++] = m_base_register[i] & 0xff;
2177 			}
2178 		}
2179 	}
2180 }
2181 
WRITE_LINE_MEMBER(amigo_device::holda_in)2182 WRITE_LINE_MEMBER( amigo_device::holda_in )
2183 {
2184 	LOGMASKED(LOG_MAP, "HOLD acknowledged = %d\n", state);
2185 	m_hold_acknowledged = (state==ASSERT_LINE);
2186 }
2187 
device_start()2188 void amigo_device::device_start()
2189 {
2190 	m_mainboard = downcast<mainboard8_device*>(owner());
2191 
2192 	std::fill(std::begin(m_base_register), std::end(m_base_register), 0);
2193 
2194 	save_item(NAME(m_memen));
2195 	save_pointer(NAME(m_base_register),16);
2196 	save_item(NAME(m_logical_space));
2197 	save_item(NAME(m_physical_address));
2198 	save_item(NAME(m_srdy));
2199 	save_item(NAME(m_ready_out));
2200 	save_item(NAME(m_crus));
2201 	save_item(NAME(m_amstate));
2202 	save_item(NAME(m_protflag));
2203 	save_item(NAME(m_sram_accessed));
2204 	save_item(NAME(m_dram_accessed));
2205 	save_item(NAME(m_mapper_accessed));
2206 	save_item(NAME(m_hold_acknowledged));
2207 	save_item(NAME(m_sram_address));
2208 	save_item(NAME(m_basereg));
2209 	save_item(NAME(m_mapvalue));
2210 }
2211 
device_reset()2212 void amigo_device::device_reset()
2213 {
2214 	m_logical_space = true;
2215 }
2216 
2217 /***************************************************************************
2218 
2219   ===== OSO: Hexbus interface =====
2220 
2221   The Hexbus is a 4-bit peripheral bus with master/slave coordination. Bytes
2222   are written over the bus in two passes. Hexbus was the designated standard
2223   peripheral bus for TI computers before TI left the home computer market.
2224 
2225   Existing devices are floppy drive, RS232 serial adapter, and
2226   a "Wafertape" drive (kind of tape streamer)
2227 
2228   Registers:  Read   Write  Bits of register
2229   ----------------------------------------------------------------------------
2230   Data     :  5FF8     -    ADB3  ADB2  ADB1    ADB0    ADB3  ADB2  ADB1  ADB0
2231   Status   :  5FFA     -    HSKWT HSKRD BAVIAS  BAVAIS  SBAV  WBUSY RBUSY SHSK
2232   Control  :  5FFC   5FFA   WIEN  RIEN  BAVIAEN BAVAIEN BAVC  WEN   REN   CR7
2233   Xmit     :  5FFE   5FF8   XDR0  XDR1  XDR2    XDR3    XDR4  XDR5  XDR6  XDR7
2234 
2235   ADBx = Hexbus data bit X
2236   HSKWT = Set when a byte has been sent over the bus and HSK has been asserted
2237   HSKRD = Set when a byte has been received
2238   BAVIAS = set when the BAV* signal (bus available) transits to active state
2239   BAVAIS = set when the BAV* signal transits to inactive state (=1)
2240   SBAV = set when BAV* = 0 (active)
2241   WBUSY = set when a write action is in progress (two transfers @ 4 bits)
2242   Reset when HSKWT is set
2243   RBUSY = set when a read action is in progress (two transfers @ 4 bits)
2244   Reset when HSKRD is set
2245   SHSK = set when HSK* is active (0)
2246 
2247   WIEN = Enable interrupt for write completion
2248   RIEN = Enable interrupt for read completion
2249   BAVIAEN = BAVIA enable (slave mode)
2250   BAVAIEN = BAVAI enable (slave mode)
2251   BAVC = set BAV* line (0=active)
2252   WEN = set write enable (byte is written from xmit reg)
2253   REN = set read enable (latch HSK and read byte into data reg)
2254   CR7 = future extension
2255   XDRx = transmit register bit
2256 
2257   Hexbus connector (console)
2258   +---+---+---+---+
2259   | 4 | 3 | 2 | 1 |      4 = L;    3 = BAV*; 2 = ADB1; 1 = ADB0
2260   +---+---+---+---+
2261   | 8 | 7 | 6 | 5 |      8 = ADB3; 7 = ADB2; 6 = nc;   5 = HSK*
2262   +---+---+---+---+
2263 
2264 ****************************************************************************/
2265 
oso_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2266 oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2267 	bus::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock),
2268 	m_int(*this),
2269 	m_hexbusout(*this, ":" TI998_HEXBUS_TAG),
2270 	m_data(0),
2271 	m_status(0xff),
2272 	m_control(0),
2273 	m_xmit(0),
2274 	m_bav(false), m_sbav(false), m_sbavold(false), m_bavold(false),
2275 	m_hsk(false), m_hsklocal(false), m_shsk(false), m_hskold(false),
2276 	m_wq1(false), m_wq1old(false), m_wq2(false), m_wq2old(false),
2277 	m_wnp(false), m_wbusy(false), m_wbusyold(false), m_sendbyte(false),
2278 	m_wrset(false), m_counting(false), m_clkcount(0),
2279 	m_rq1(false), m_rq2(false), m_rq2old(false),
2280 	m_rnib(false), m_rnibcold(false),
2281 	m_rdset(false), m_rdsetold(false),
2282 	m_msns(false), m_lsns(false),
2283 	m_rhsus(false), m_rbusy(false),
2284 	m_phi3(false),
2285 	m_oldvalue(0xff)
2286 {
2287 	m_hexbus_inbound = nullptr;
2288 	m_hexbus_outbound = nullptr;
2289 }
2290 
read(offs_t offset)2291 uint8_t oso_device::read(offs_t offset)
2292 {
2293 	int value = 0;
2294 	offset &= 0x03;
2295 	switch (offset)
2296 	{
2297 	case 0:
2298 		// read 5FF8: read data register
2299 		value = m_data;
2300 		LOGMASKED(LOG_OSO, "Read data register = %02x\n", value);
2301 		// Release the handshake
2302 		m_rhsus = false;
2303 		break;
2304 	case 1:
2305 		// read 5FFA: read status register
2306 		value = m_status;
2307 		clear_int_status();
2308 		LOGMASKED(LOG_OSO, "Read status %02x (HSKWT=%d,HSKRD=%d,BAVIAS=%d,BAVAIS=%d,SBAV=%d,WBUSY=%d,RBUSY=%d,SHSK=%d)\n", value,
2309 			(value&HSKWT)? 1:0, (value&HSKRD)? 1:0, (value&BAVIAS)? 1:0,
2310 			(value&BAVAIS)? 1:0, (value&SBAV)? 1:0, (value&WBUSY)? 1:0,
2311 			(value&RBUSY)? 1:0,(value&SHSK)? 1:0);
2312 		break;
2313 	case 2:
2314 		// read 5FFC: read control register
2315 		value = m_control;
2316 		LOGMASKED(LOG_OSO, "Read control register = %02x\n", value);
2317 		break;
2318 	case 3:
2319 		// read 5FFE: read transmit register
2320 		value = m_xmit;
2321 		LOGMASKED(LOG_OSO, "Read transmit register = %02x\n", value);
2322 		break;
2323 	}
2324 	return value;
2325 }
2326 
write(offs_t offset,uint8_t data)2327 void oso_device::write(offs_t offset, uint8_t data)
2328 {
2329 	offset &= 0x03;
2330 	switch (offset)
2331 	{
2332 	case 0:
2333 		// write 5FF8: write transmit register
2334 		LOGMASKED(LOG_OSO, "Write transmit register %02x\n", data);
2335 
2336 		// trigger some actions in the write subsystem
2337 		m_sendbyte = true;
2338 		if (!m_wq1)
2339 		{
2340 			m_wbusyold = true;
2341 			set_status(WBUSY, true);
2342 		}
2343 
2344 		m_xmit = data;
2345 		break;
2346 	case 1:
2347 		// write 5FFA: write control register
2348 		LOGMASKED(LOG_OSO, "Write control register %02x (WIEN=%d, RIEN=%d, BAVIAEN=%d, BAVAIEN=%d, BAVC=%d, WEN=%d, REN=%d)\n",
2349 			data, (data & WIEN)? 1:0, (data & RIEN)? 1:0, (data&BAVIAEN)? 1:0, (data&BAVAIEN)? 1:0,
2350 			(data & BAVC)? 1:0, (data & WEN)? 1:0, (data & REN)? 1:0);
2351 		m_control = data;
2352 		m_bav = control_bit(BAVC);
2353 
2354 		// Reset some flipflops in the write/read timing section
2355 		if (!control_bit(WEN))
2356 		{
2357 			m_wq1 = m_wq2 = m_wrset = false;
2358 		}
2359 		if (!control_bit(REN))
2360 		{
2361 			m_rq1 = m_rq2 = m_rdset = false;
2362 		}
2363 		update_hexbus();
2364 		break;
2365 	default:
2366 		// write 5FFC, 5FFE: undefined
2367 		LOGMASKED(LOG_OSO, "Invalid write on %04x: %02x\n", (offset<<1) | 0x5ff0, data);
2368 		break;
2369 	}
2370 }
2371 
clear_int_status()2372 void oso_device::clear_int_status()
2373 {
2374 	m_status &= ~(HSKWT | HSKRD | BAVIAS | BAVAIS);
2375 	m_int(CLEAR_LINE);
2376 }
2377 
2378 /*
2379     Phi3 incoming clock pulse
2380 */
WRITE_LINE_MEMBER(oso_device::clock_in)2381 WRITE_LINE_MEMBER( oso_device::clock_in )
2382 {
2383 	m_phi3 = state;
2384 	if (state==ASSERT_LINE)
2385 	{
2386 		// Control lines SHSK, SBAV
2387 		// When BAV/HSK is 0/1 for two rising edges of Phi3*, SBAV/SHSK goes to
2388 		// 0/1 at the following falling edge of Phi3*.
2389 		// Page 5
2390 
2391 		// In reality, the HSK and BAV signals are checked for their minimum
2392 		// width (by waiting for two cycles of constant level), but due to
2393 		// problems with synchronous execution between different parts in the
2394 		// emulation, we accept the level change immediately.
2395 
2396 		m_sbav = m_bav;   // could mean "stable BAV"
2397 		// if (control_bit(WEN)) logerror("hskhold=%d, hsk=%d\n", m_hskhold? 1:0, m_hsk? 1:0);
2398 
2399 		m_shsk = m_hsk;
2400 		set_status(SHSK, m_shsk);
2401 		set_status(SBAV, m_sbav);
2402 
2403 		// Raising edge of SBAV*
2404 		if (m_sbav == true && m_sbavold == false)
2405 			set_status(BAVIAS, true);
2406 		// Falling edge of SBAV*
2407 		if (m_sbav == false && m_sbavold == true)
2408 			set_status(BAVAIS, true);
2409 		m_sbavold = m_sbav;
2410 
2411 		// Implement the write timing logic
2412 		// This subcircuit in the OSO chip autonomously runs the Hexbus
2413 		// protocol. After loading a byte into the transmit register, it sends
2414 		// both nibbles (little-endian) one after another over the Hexbus,
2415 		// pausing for 30 cycles, and checking the HSK line.
2416 
2417 		// The schematics show some fascinating signal line spaghetti with
2418 		// embedded JK* flipflops which may give you some major headaches.
2419 		// Compared to that, the lines below are a true relief.
2420 
2421 		if (control_bit(WEN))  // Nothing happens without WEN
2422 		{
2423 			if (!m_wrset && m_sendbyte)
2424 				LOGMASKED(LOG_OSO, "Starting write process\n");
2425 
2426 			// Page 3: Write timing
2427 			// Note: First pass counts to 30, second to 31
2428 			bool cnt30 = ((m_clkcount & 0x1e) == 30);
2429 			bool cont = (m_wrset && !m_wq2 && !m_wq1) || (cnt30 && m_wq2 && !m_wq1)
2430 			|| (cnt30 && !m_wq2 && m_wq1) || (m_shsk && m_wq2 && m_wq1);
2431 
2432 			bool jwq1 = cont && m_wq2;
2433 			bool kwq1 = !(cont && !m_wq2) && !(!cont && m_wq2 && m_wnp);
2434 
2435 			bool jwq2 = cont;
2436 			bool kwq2 = !(m_wq1 && !cont);
2437 
2438 			if (m_wq1 == m_wq2) m_clkcount = 0;
2439 
2440 			// Reset "byte loaded" flipflop during the second phase
2441 			if (m_wq1 == true)
2442 				m_sendbyte = false;
2443 
2444 			// logerror("sendbyte=%d, wq1=%d, wq2=%d, jwq1=%d, kwq1=%d, jwq2=%d, kwq2=%d\n", m_sendbyte, m_wq1, m_wq2, jwq1, kwq1, jwq2, kwq2);
2445 			// logerror("sendbyte=%d, wq1=%d, wq2=%d, m_shsk=%d\n", m_sendbyte, m_wq1, m_wq2, m_shsk);
2446 			// WBUSY is asserted on byte load, during phase 1, and phase 2.
2447 			m_wbusy = m_sendbyte || m_wq1 || m_wq2;
2448 
2449 			// Set status bits and raise interrupt (p. 4)
2450 			set_status(WBUSY, m_wbusy);
2451 
2452 			// Raising edge of wbusy*
2453 			// This is true when the two nibbles of the byte have been written and acknowledged
2454 			// by the receiver which has released HSK*
2455 			if (m_wbusyold == true && m_wbusy == false)
2456 			{
2457 				LOGMASKED(LOG_HEXBUS, "Setting HSKWT to true\n");
2458 				set_status(HSKWT, true);
2459 				// Problem: By turning off the WBUSY signal, the transmit register goes inactive
2460 				// so the peripheral setting dominates again. However, the peripheral sender will not
2461 				// send its value again.
2462 			}
2463 			m_wbusyold = m_wbusy;
2464 
2465 			// Operate flipflops
2466 			// Write phases
2467 			// 74LS109: J-K* flipflop (inverted K)
2468 			if (jwq1)
2469 			{
2470 				if (!kwq1) m_wq1 = !m_wq1;
2471 				else m_wq1 = true;
2472 			}
2473 			else
2474 				if (!kwq1) m_wq1 = false;
2475 
2476 			if (jwq2)
2477 			{
2478 				if (!kwq2) m_wq2 = !m_wq2;
2479 				else m_wq2 = true;
2480 			}
2481 			else
2482 				if (!kwq2) m_wq2 = false;
2483 
2484 			// Set WNP on rising edge of WQ2*
2485 			if (m_wq2 != m_wq2old)
2486 			{
2487 				if (!m_wq2)
2488 					m_wnp = true;
2489 
2490 				m_wq2old = m_wq2;
2491 			}
2492 			m_wq1old = m_wq1;
2493 
2494 			// Reset WNP if phases are done
2495 			if (!m_wq2 && !m_wq1)
2496 			{
2497 				m_wnp = false;
2498 			}
2499 		}
2500 
2501 		// This is the reading behavior. In this case, the master (this
2502 		// component) pulls down BAV*, then the slave sets the data lines
2503 		// with the back nibble, pulls down HSK*, then releases HSK*,
2504 		// puts the front nibble on the data lines, pulls down HSK* again,
2505 		// releases it, and this continues until the master releases BAV*
2506 
2507 		if (control_bit(REN))
2508 		{
2509 			bool rdsetin = !status_bit(WBUSY) && m_sbav && m_shsk;
2510 			bool next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
2511 			bool drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
2512 			bool jrq2 = next && !m_rq1;
2513 			bool krq2 = !m_rq1 || m_rnib;
2514 			bool rnibc = m_rq1;
2515 
2516 			//logerror("n=%d,d1=%d,j2=%d,k2=%d,rn=%d\n", next, drq1, jrq2, krq2, m_rnib);
2517 			// Next state
2518 			if (!m_rdsetold && rdsetin)
2519 			{
2520 				m_rdset = true; // raising edge
2521 			}
2522 			m_rdsetold = rdsetin;
2523 			// logerror("rdset=%d, rdsetin=%d\n", m_rdset, rdsetin);
2524 
2525 			// Set the RQ1 flipflop
2526 			m_rq1 = drq1;
2527 
2528 			// Set the RQ2 flipflop
2529 			if (jrq2)
2530 			{
2531 				if (!krq2) m_rq2 = !m_rq2;
2532 				else m_rq2 = true;
2533 			}
2534 			else
2535 				if (!krq2) m_rq2 = false;
2536 
2537 			if (m_rq2) m_rdset = false;
2538 
2539 			// Set the rnib flipflop. This is in sequence to the RQ1 flipflop.
2540 			rnibc = m_rq1;
2541 			if (m_rnibcold == false && rnibc == true) // raising edge
2542 				m_rnib = !m_rnib;
2543 
2544 			m_rnibcold = rnibc;
2545 
2546 			// Debugging only
2547 			// next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
2548 			// drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
2549 			// jrq2 = next && !m_rq1;
2550 			// krq2 = !m_rq1 || m_rnib;
2551 			// logerror("r=%d,n=%d,rn=%d,d1=%d,j2=%d,k2=%d,q1=%d,q2=%d\n", m_rdset, next, m_rnib, drq1, jrq2, krq2, m_rq1, m_rq2);
2552 
2553 			// Set RBUSY
2554 			bool rbusy = m_rq1 || m_rq2;
2555 
2556 			if (rbusy != m_rbusy)
2557 				LOGMASKED(LOG_HEXBUS, "RBUSY=%d\n",rbusy);
2558 
2559 			m_rbusy = rbusy;
2560 			set_status(RBUSY, rbusy);
2561 
2562 			// Flipflop resets
2563 			if (!rbusy) m_rnib = false;
2564 
2565 			bool msns = m_rnib && !m_rq1 && m_rq2;
2566 			bool lsns = !m_rnib && !m_rq1 && m_rq2;
2567 
2568 			// if (msns != m_msns) LOGMASKED(LOG_HEXBUS, "MSNS=%d\n", msns);
2569 			// if (lsns != m_lsns) LOGMASKED(LOG_HEXBUS, "LSNS=%d\n", lsns);
2570 
2571 			m_lsns = lsns;
2572 			m_msns = msns;
2573 
2574 			// Raising edge of RQ2*
2575 			if (m_rq2old == true && m_rq2 == false)
2576 			{
2577 				LOGMASKED(LOG_HEXBUS, "Byte available for reading\n");
2578 				set_status(HSKRD, true);
2579 				m_rhsus = true;  // byte is available for reading
2580 			}
2581 			m_rq2old = m_rq2;
2582 		}
2583 		else
2584 		{
2585 			m_rhsus = false;
2586 		}
2587 
2588 		// Handshake control
2589 		// Set HSK (Page 6, RHSUS*)
2590 		// This is very likely an error in the schematics. It does not make
2591 		// sense, and simulations show that the behaviour would be wrong.
2592 		// bool hskwrite = !m_wq1 && m_wq2;
2593 		bool hskwrite = (m_wq1 != m_wq2);
2594 
2595 		// We can simplify this to a single flag because the CPU read operation
2596 		// is atomic here (starts and immediately terminates)
2597 		m_hsklocal = hskwrite || m_rhsus;
2598 		update_hexbus();
2599 	}
2600 	// Actions that occur for Phi3=0
2601 	else
2602 	{
2603 		m_wrset = m_sendbyte;
2604 		// Only count when one phase is active
2605 		m_counting = !(m_wq1==m_wq2);
2606 
2607 		if (m_counting)
2608 			m_clkcount++;
2609 		else
2610 			m_clkcount = 0; // Reset when not counting
2611 	}
2612 
2613 	// Flipflop resets (not related to clock)
2614 	if (!control_bit(WEN))
2615 	{
2616 		m_wq1 = m_wq2 = m_wrset = m_counting = false;
2617 		m_clkcount = 0;
2618 	}
2619 	if (!control_bit(REN))
2620 	{
2621 		m_rq1 = m_rq2 = m_rdset = false;
2622 	}
2623 
2624 	// Raise interrupt
2625 	if ((control_bit(WIEN) && status_bit(HSKWT))
2626 		|| (control_bit(RIEN) && status_bit(HSKRD))
2627 		|| (control_bit(BAVAIEN) && status_bit(BAVAIS))
2628 		|| (control_bit(BAVIAEN) && status_bit(BAVIAS)))
2629 	{
2630 		m_int(ASSERT_LINE);
2631 	}
2632 }
2633 
2634 /*
2635     Change the Hexbus line levels and propagate them towards the peripherals.
2636 */
update_hexbus()2637 void oso_device::update_hexbus()
2638 {
2639 	bool changed = false;
2640 	if (m_hsklocal != m_hskold)
2641 	{
2642 		LOGMASKED(LOG_HEXBUS, "%s HSK*\n", m_hsklocal? "Pulling down" : "Releasing");
2643 		m_hskold = m_hsklocal;
2644 		changed = true;
2645 	}
2646 
2647 	if (m_bav != m_bavold)
2648 	{
2649 		LOGMASKED(LOG_HEXBUS, "%s BAV*\n", m_bav? "Pulling down" : "Releasing");
2650 		m_bavold = m_bav;
2651 		changed = true;
2652 	}
2653 
2654 	if (!changed) return;
2655 
2656 	// If wbusy==false, set the data output to 1111; since the Hexbus is
2657 	// a pull-down line bus, this means to inactivate the output
2658 	uint8_t nibble = m_wbusy? m_xmit : 0xff;
2659 	if (m_wnp) nibble >>= 4;
2660 
2661 	uint8_t value = to_line_state(nibble, control_bit(BAVC), m_hsklocal);
2662 
2663 	// if (m_oldvalue != value)
2664 	//      LOGMASKED(LOG_OSO, "Set hexbus = %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value, (value & 0x04)? 1:0, (value & 0x10)? 1:0, ((value>>4)&0x0c) | (value&0x03));
2665 
2666 	// As for Oso, we can be sure that hexbus_write does not trigger further
2667 	// activities from the peripherals that cause a call to hexbus_value_changed.
2668 	hexbus_write(value);
2669 
2670 	// Check how the bus has changed. This depends on the states of all
2671 	// connected peripherals
2672 
2673 	// Update the state of BAV and HSK
2674 	m_bav = (bus_bav_level()==ASSERT_LINE);
2675 	m_hsk = (bus_hsk_level()==ASSERT_LINE);
2676 
2677 	// Sometimes, Oso does not have a chance to advance its state after the
2678 	// last byte was read. In that case, a change of rdsetin would not be
2679 	// sensed. We reset the flag right here and so pretend that the tick
2680 	// has happened.
2681 	if (m_hsk==false) m_rdsetold = false;
2682 
2683 	m_oldvalue = m_current_bus_value;
2684 }
2685 
2686 /*
2687     Called when the value on the Hexbus has changed.
2688 */
hexbus_value_changed(uint8_t data)2689 void oso_device::hexbus_value_changed(uint8_t data)
2690 {
2691 //  LOGMASKED(LOG_OSO, "Hexbus value changed to %02x\n", data);
2692 	bool bav = (bus_bav_level()==ASSERT_LINE);
2693 	bool hsk = (bus_hsk_level()==ASSERT_LINE);
2694 
2695 	if ((bav != m_bav) || (hsk != m_hsk))
2696 	{
2697 		m_bav = bav | control_bit(BAVC);
2698 		m_hsk = hsk;
2699 
2700 		LOGMASKED(LOG_HEXBUS, "BAV*=%d, HSK*=%d\n", m_bav? 0:1, m_hsk? 0:1);
2701 		int nibble = data_lines(data);
2702 
2703 		// The real devices are driven at a similar clock rate like the 99/8.
2704 		// The designers assumed that there is a clock tick of Oso between
2705 		// every clock tick of the peripheral device. This is not true for
2706 		// the emulation in MAME, however. For that reason, we trigger "fake"
2707 		// clock ticks on every change of the hexbus.
2708 		for (int fake=0; fake < 4; fake++)
2709 		{
2710 			if (m_msns)
2711 			{
2712 				m_data = (m_data & 0x0f) | (nibble<<4);
2713 				LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
2714 			}
2715 			if (m_lsns)
2716 			{
2717 				m_data = (m_data & 0xf0) | nibble;
2718 				LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
2719 			}
2720 
2721 			LOGMASKED(LOG_HEXBUS, "Fake tick %d\n", fake);
2722 			bool phi3 = m_phi3;  // mind that clock_in swaps the state of m_phi3
2723 			clock_in(!phi3);
2724 			clock_in(phi3);
2725 			LOGMASKED(LOG_HEXBUS, "Fake tick %d end\n", fake);
2726 		}
2727 	}
2728 	else
2729 	{
2730 		LOGMASKED(LOG_HEXBUS, "No change for BAV* and HSK*\n");
2731 	}
2732 }
2733 
device_start()2734 void oso_device::device_start()
2735 {
2736 	m_status = m_xmit = m_control = m_data = 0;
2737 	m_int.resolve_safe();
2738 
2739 	// Establish the downstream link in the parent class hexbus_chained_device
2740 	set_outbound_hexbus(m_hexbusout);
2741 
2742 	// Establish callback for inbound propagations
2743 	m_hexbus_outbound->set_chain_element(this);
2744 
2745 	save_item(NAME(m_data));
2746 	save_item(NAME(m_status));
2747 	save_item(NAME(m_control));
2748 	save_item(NAME(m_xmit));
2749 }
2750 
2751 } } } // end namespace bus::ti99::internal
2752 
2753