summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/internal/998board.h
blob: 1787c0f9cecfd1a84319e0bd738f418930c17bae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
// license:LGPL-2.1+
// copyright-holders:Michael Zapf
/****************************************************************************

    TI-99/8 main board logic

    This component implements the address decoder and mapper logic from the
    TI-99/8 console.

    See 998board.c for documentation

    Michael Zapf

*****************************************************************************/

#ifndef MAME_BUS_TI99_INTERNAL_998BOARD_H
#define MAME_BUS_TI99_INTERNAL_998BOARD_H

#pragma once

#include "bus/ti99/ti99defs.h"
#include "bus/ti99/gromport/gromport.h"
#include "bus/hexbus/hexbus.h"

#include "bus/ti99/internal/ioport.h"
#include "machine/ram.h"
#include "machine/tmc0430.h"
#include "sound/sn76496.h"
#include "sound/tms5220.h"
#include "video/tms9928a.h"

// -------------- Defines ------------------------------------

#define TI998_SRAM_TAG        "sram8"
#define TI998_DRAM_TAG        "dram8"
#define TI998_MAPPER_TAG      "mapper"
#define TI998_MAINBOARD_TAG  "mainboard8"
#define TI998_SPEECHSYN_TAG     "speech"

#define TI998_ROM0_REG        "rom0_region"
#define TI998_ROM1_REG        "rom1_region"
#define TI998_PASCAL_REG      "pascal_region"
#define TI998_SYSGROM_REG     "sysgrom_region"
#define TI998_GROMLIB1_REG    "gromlib1_region"
#define TI998_GROMLIB2_REG    "gromlib2_region"
#define TI998_GROMLIB3_REG    "gromlib3_region"
#define TI998_SPEECHROM_REG       "speech_region"

#define TI998_GROMLIB_TAG "gromlib"
#define TI998_SYSGROM_TAG TI998_GROMLIB_TAG "0"
#define TI998_SYSGROM0_TAG TI998_SYSGROM_TAG "_0"
#define TI998_SYSGROM1_TAG TI998_SYSGROM_TAG "_1"
#define TI998_SYSGROM2_TAG TI998_SYSGROM_TAG "_2"

#define TI998_GLIB1_TAG TI998_GROMLIB_TAG "1"
#define TI998_GLIB10_TAG TI998_GLIB1_TAG "_0"
#define TI998_GLIB11_TAG TI998_GLIB1_TAG "_1"
#define TI998_GLIB12_TAG TI998_GLIB1_TAG "_2"
#define TI998_GLIB13_TAG TI998_GLIB1_TAG "_3"
#define TI998_GLIB14_TAG TI998_GLIB1_TAG "_4"
#define TI998_GLIB15_TAG TI998_GLIB1_TAG "_5"
#define TI998_GLIB16_TAG TI998_GLIB1_TAG "_6"
#define TI998_GLIB17_TAG TI998_GLIB1_TAG "_7"

#define TI998_GLIB2_TAG TI998_GROMLIB_TAG "2"
#define TI998_GLIB20_TAG TI998_GLIB2_TAG "_0"
#define TI998_GLIB21_TAG TI998_GLIB2_TAG "_1"
#define TI998_GLIB22_TAG TI998_GLIB2_TAG "_2"
#define TI998_GLIB23_TAG TI998_GLIB2_TAG "_3"
#define TI998_GLIB24_TAG TI998_GLIB2_TAG "_4"
#define TI998_GLIB25_TAG TI998_GLIB2_TAG "_5"
#define TI998_GLIB26_TAG TI998_GLIB2_TAG "_6"
#define TI998_GLIB27_TAG TI998_GLIB2_TAG "_7"

#define TI998_GLIB3_TAG TI998_GROMLIB_TAG "3"
#define TI998_GLIB30_TAG TI998_GLIB3_TAG "_0"
#define TI998_GLIB31_TAG TI998_GLIB3_TAG "_1"
#define TI998_GLIB32_TAG TI998_GLIB3_TAG "_2"

#define TI998_VAQUERRO_TAG "vaquerro"
#define TI998_MOFETTA_TAG "mofetta"
#define TI998_AMIGO_TAG "amigo"
#define TI998_OSO_TAG "oso"

// --------------------------------------------------

namespace bus { namespace ti99 { namespace internal {

class mainboard8_device;

/*
    Custom chip: Vaquerro
*/
class vaquerro_device : public device_t
{
public:
	vaquerro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	void device_start() override;
	void device_reset() override;

	line_state ready();
	void treset();

	DECLARE_READ8_MEMBER( read );
	DECLARE_SETADDRESS_DBIN_MEMBER( set_address );

	DECLARE_READ_LINE_MEMBER( sprd_out );
	DECLARE_READ_LINE_MEMBER( spwt_out );
	DECLARE_READ_LINE_MEMBER( sccs_out );
	DECLARE_READ_LINE_MEMBER( sromcs_out );

	// Collective select line query
	int gromcs_out();

	DECLARE_READ_LINE_MEMBER( vdprd_out );
	DECLARE_READ_LINE_MEMBER( vdpwt_out );
	DECLARE_READ_LINE_MEMBER( lascsq_out );
	DECLARE_READ_LINE_MEMBER( ggrdy_out );
	DECLARE_WRITE_LINE_MEMBER( hold_cpu );

	DECLARE_WRITE_LINE_MEMBER( crus_in );
	DECLARE_WRITE_LINE_MEMBER( crusgl_in );
	DECLARE_WRITE_LINE_MEMBER( clock_in );
	DECLARE_WRITE_LINE_MEMBER( memen_in );

	DECLARE_WRITE_LINE_MEMBER( sgmry );
	DECLARE_WRITE_LINE_MEMBER( tsgry );
	DECLARE_WRITE_LINE_MEMBER( p8gry );
	DECLARE_WRITE_LINE_MEMBER( p3gry );

private:
	/*
	    Wait state generator (part of Vaquerro)
	*/
	class waitstate_generator
	{
	public:
		waitstate_generator() :
			m_counting(false),
			m_generate(false),
			m_counter(0),
			m_addressed(true),
			m_ready(true)
		{
		}

		virtual ~waitstate_generator() { }
		void select_in(bool addressed);
		virtual void ready_in(line_state ready) = 0;
		virtual void clock_in(line_state clkout) = 0;
		void treset_in(line_state reset);

		int select_out();
		void init(int select_value) { m_selvalue = select_value; }

		line_state ready_out();

		bool is_counting();
		bool is_generating();
		bool is_ready();

	protected:
		// Two flipflops
		bool m_counting;
		bool m_generate;
		// Counter
		int  m_counter;

		// Select value (indicates selected line)
		int  m_selvalue;

		// Line state flags
		bool m_addressed;
		bool m_ready;
	};

	class grom_waitstate_generator : public waitstate_generator
	{
	public:
		void ready_in(line_state ready) override;
		void clock_in(line_state clkout) override;
	};

	class video_waitstate_generator : public waitstate_generator
	{
	public:
		void ready_in(line_state ready) override { }
		void clock_in(line_state clkout) override;
	};

	// Memory cycle state
	bool m_memen;

	// Waiting for video
	bool m_video_wait;

	// State of the CRUS line
	int m_crus;

	// Are the GROM libraries turned on?
	bool m_crugl;

	// Do we have a logical address space match?
	bool m_lasreq = false;

	// Keep the decoding result (opens the SRY gate)
	bool m_grom_or_video = false;

	// Select lines
	bool m_spwt;
	bool m_sccs;
	bool m_sromcs;
	bool m_sprd;
	bool m_vdprd;
	bool m_vdpwt;

	// Collective GROM select state
	int m_gromsel;

	// Outgoing READY
	int m_ggrdy;

	// Outgoing READY latch (common flipflop driving SRY)
	bool m_sry;

	// Holds the A14 address line state. We need this for the clock_in method.
	int m_a14;

	// Keeps the recent DBIN level
	int m_dbin_level;

	// Wait state logic components
	grom_waitstate_generator m_sgmws, m_tsgws, m_p8gws, m_p3gws;
	video_waitstate_generator m_vidws;

	// Pointer to mainboard
	mainboard8_device* m_mainboard;
};

/*
    Custom chip: Mofetta
*/
class mofetta_device : public device_t
{
public:
	mofetta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	void device_start() override;
	void device_reset() override;

	DECLARE_WRITE8_MEMBER( cruwrite );
	DECLARE_SETADDRESS_DBIN_MEMBER( set_address );

	// Debugger support
	bool hexbus_access_debug();
	bool intdsr_access_debug();

	DECLARE_WRITE_LINE_MEMBER( clock_in );
	DECLARE_WRITE_LINE_MEMBER( msast_in );
	DECLARE_WRITE_LINE_MEMBER( lascs_in );
	DECLARE_WRITE_LINE_MEMBER( pmemen_in );
	DECLARE_WRITE_LINE_MEMBER( skdrcs_in );

	DECLARE_READ8_MEMBER( rom1cs_out );
	DECLARE_READ_LINE_MEMBER( gromclk_out );

	DECLARE_READ_LINE_MEMBER( alccs_out );
	DECLARE_READ_LINE_MEMBER( prcs_out );
	DECLARE_READ_LINE_MEMBER( cmas_out );
	DECLARE_READ_LINE_MEMBER( dbc_out );

	DECLARE_READ_LINE_MEMBER( rom1cs_out );
	DECLARE_READ_LINE_MEMBER( rom1am_out );
	DECLARE_READ_LINE_MEMBER( rom1al_out );

private:
	// Memory cycle state
	bool m_pmemen;

	// Logical access
	bool m_lasreq;

	// DRAM access
	bool m_skdrcs;

	// Indicates the UP level of the GROMCLK
	bool m_gromclk_up;

	// Have we got the upper word of the address?
	bool m_gotfirstword;

	// Address latch
	int m_address_latch;

	// Most significant byte of the 24-bit address
	int m_prefix;

	// CRU select of the 1700 device
	bool m_alcpg;

	// CRU select of the 2700 device
	bool m_txspg;

	// ROM1 select lines
	bool m_rom1cs;
	bool m_rom1am;
	bool m_rom1al;

	// OSO select
	bool m_alccs;

	// Pascal ROM select line
	bool m_prcs;

	// Cartridge port select line
	bool m_cmas;

	// GROM clock count (as frequency divider)
	int m_gromclock_count;

	// Remember last msast state for edge detection
	int m_msast;

	// Pointer to mainboard
	mainboard8_device* m_mainboard;
};

/*
    Custom chip: Amigo
*/
class amigo_device : public device_t
{
public:
	amigo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	void device_start() override;
	void device_reset() override;

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );
	DECLARE_SETOFFSET_MEMBER( set_address );

	// Debugger support
	int get_physical_address_debug(offs_t offset);
	void mapper_access_debug(int data);

	DECLARE_WRITE_LINE_MEMBER( srdy_in );
	DECLARE_WRITE_LINE_MEMBER( clock_in );
	DECLARE_WRITE_LINE_MEMBER( crus_in );
	DECLARE_WRITE_LINE_MEMBER( lascs_in );
	DECLARE_WRITE_LINE_MEMBER( memen_in );

	DECLARE_WRITE_LINE_MEMBER( holda_in );

	DECLARE_READ_LINE_MEMBER( cpury_out );
	DECLARE_READ_LINE_MEMBER( sramcs_out );
	DECLARE_READ_LINE_MEMBER( skdrcs_out );

	void connect_sram(uint8_t* sram) { m_sram = sram; }
	bool mapper_accessed() { return m_mapper_accessed; }

private:
	// Memory cycle state
	bool m_memen;

	// DMA methods for loading/saving maps
	void mapper_load();
	void mapper_save();

	// Address mapper registers. Each offset is selected by the first 4 bits
	// of the logical address.
	uint32_t  m_base_register[16];

	// Indicates a logical space access
	bool m_logical_space;

	// Physical address
	uint32_t  m_physical_address;

	// Pointer to SRAM where AMIGO needs to upload/download its map values
	uint8_t* m_sram;

	// Pointer to mainboard
	mainboard8_device* m_mainboard;

	// Keep the system ready state
	int m_srdy;

	// Outgoing READY level
	int m_ready_out;

	// Keep the CRUS setting
	int m_crus;

	// State of the address creation
	int m_amstate;

	// Protection flags
	int m_protflag;

	// Accessing SRAM
	bool m_sram_accessed;

	// Accessing DRAM
	bool m_dram_accessed;

	// Accessing the mapper
	bool m_mapper_accessed;

	// HOLDA flag
	bool m_hold_acknowledged;

	// Address in SRAM during DMA
	uint32_t  m_sram_address;

	// Number of the currently loaded/save base register
	int m_basereg;

	// Latched value for mapper DMA transfer
	uint32_t m_mapvalue;
};

/*
    Custom chip: OSO
*/
class oso_device : public bus::hexbus::hexbus_chained_device
{
public:
	oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );
	void device_start() override;
	// Don't add a hexbus connector; we use the one from the driver instance
	virtual void device_add_mconfig(machine_config &config) override { };

	void hexbus_value_changed(uint8_t data) override;

	WRITE_LINE_MEMBER( clock_in );

	// INT line
	devcb_write_line m_int;

private:
	bool control_bit(int bit) { return (m_control & bit)!=0; }
	bool status_bit(int bit) { return (m_status & bit)!=0; }
	void clear_int_status();
	void set_status(int bit, bool set) { m_status = (set)? (m_status | bit) : (m_status & ~bit); }
	void update_hexbus();

	// Registers
	uint8_t m_data;
	uint8_t m_status;
	uint8_t m_control;
	uint8_t m_xmit;

	// Last hexbus value; when the new value is different, send it via the hexbus
	uint8_t m_lasthxvalue;

	bool m_bav;         // Bus available; when true, a communication is about to happen
	bool m_sbav;        // Stable BAV; the BAV signal is true for two clock cycles
	bool m_sbavold;     // Old SBAV state
	bool m_bavhold;     // For computing the SBAV signal

	bool m_hsk;         // Handshake line; when true, a bus member needs more time to process the message
	bool m_shsk;        // Stable HSK
	bool m_shskold;     // see above
	bool m_hskhold;     // see above

	// Page 3 in OSO schematics: Write timing
	bool m_wq1;         // Flipflop 1
	bool m_wq1old;      // Previous state
	bool m_wq2;         // Flipflop 2
	bool m_wq2old;      // Previous state
	bool m_wnp;         // Write nibble selection; true means upper 4 bits
	bool m_wbusyold;    // Old state of the WBUSY line
	bool m_sendbyte;    // Byte has been loaded into the XMIT register
	bool m_wrset;       // Start sending
	bool m_counting;    // Counter running
	int m_clkcount;     // Counter for 30 cycles

	// Page 4 in OSO schematics: Read timing
	bool m_rq1;         // Flipflop 1
	bool m_rq2;         // Flipflop 2
	bool m_rq2old;      // Previous state
	bool m_rnib;        // Read nibble, true means upper 4 bits
	bool m_rnibcold;    // Needed to detect the raising edge
	bool m_rdset;       // Start reading
	bool m_rdsetold;    // Old state
	bool m_msns;        // Upper 4 bits
	bool m_lsns;        // Lower 4 bits

	// Page 6 (RHSUS*)
	bool m_rhsus;       // Needed to assert the HSK line until the CPU has read the byte
};

class mainboard8_device : public device_t
{
public:
	mainboard8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// Memory space
	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );
	DECLARE_SETOFFSET_MEMBER( setoffset );

	// Memory space for debugger access
	DECLARE_READ8_MEMBER( debugger_read );
	DECLARE_WRITE8_MEMBER( debugger_write );

	// I/O space
	DECLARE_READ8Z_MEMBER( crureadz );
	DECLARE_WRITE8_MEMBER( cruwrite );

	// Control lines
	DECLARE_WRITE_LINE_MEMBER( clock_in );
	DECLARE_WRITE_LINE_MEMBER( dbin_in );
	DECLARE_WRITE_LINE_MEMBER( msast_in );
	DECLARE_WRITE_LINE_MEMBER( crus_in );
	DECLARE_WRITE_LINE_MEMBER( ptgen_in );
	DECLARE_WRITE_LINE_MEMBER( reset_console );
	DECLARE_WRITE_LINE_MEMBER( hold_cpu );
	DECLARE_WRITE_LINE_MEMBER( ggrdy_in );

	DECLARE_WRITE_LINE_MEMBER( holda_line );

	template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object)
	{
		return downcast<mainboard8_device &>(device).m_ready.set_callback(object);
	}

	template<class _Object> static devcb_base &set_reset_wr_callback(device_t &device, _Object object)
	{
		return downcast<mainboard8_device &>(device).m_console_reset.set_callback(object);
	}

	template<class _Object> static devcb_base &set_hold_wr_callback(device_t &device, _Object object)
	{
		return downcast<mainboard8_device &>(device).m_hold_line.set_callback(object);
	}

	void set_paddress(int address);

	// Ready lines from GROMs
	DECLARE_WRITE_LINE_MEMBER( system_grom_ready );
	DECLARE_WRITE_LINE_MEMBER( ptts_grom_ready );
	DECLARE_WRITE_LINE_MEMBER( p8_grom_ready );
	DECLARE_WRITE_LINE_MEMBER( p3_grom_ready );
	DECLARE_WRITE_LINE_MEMBER( sound_ready );
	DECLARE_WRITE_LINE_MEMBER( speech_ready );
	DECLARE_WRITE_LINE_MEMBER( pbox_ready );

protected:
	void device_start() override;
	void device_reset() override;
	virtual void device_add_mconfig(machine_config &config) override;

private:
	// Holds the state of the A14 line
	bool    m_A14_set;

	// Propagates the end of the memory cycle
	void cycle_end();

	// Original logical address.
	int     m_logical_address;

	// Mapped physical address.
	int     m_physical_address;

	// Hold the address space value so that we can use it in other methods.
	address_space*  m_space;

	// Indicates that a byte is waiting on the data bus (see m_latched_data)
	bool    m_pending_write;

	// Hold the value of the data bus. In a real machine, the data bus continues
	// to show that value, but in this emulation we have a push mechanism.
	uint8_t   m_latched_data;

	// Hold the level of the GROMCLK line
	int m_gromclk;

	// Selecting GROM libraries
	void select_groms();

	// Previous select state
	int m_prev_grom;

	// Ready states
	bool m_speech_ready;
	bool m_sound_ready;
	bool m_pbox_ready;

	// Keeps the recent DBIN level
	int m_dbin_level;

	// Ready line to the CPU
	devcb_write_line m_ready;

	// Reset line to the main system
	devcb_write_line m_console_reset;

	// Hold line to the main system
	devcb_write_line m_hold_line;

	// Custom chips
	required_device<vaquerro_device> m_vaquerro;
	required_device<mofetta_device>  m_mofetta;
	required_device<amigo_device>    m_amigo;
	required_device<oso_device>       m_oso;

	// More devices
	required_device<tms9928a_device>        m_video;
	required_device<sn76496_base_device>    m_sound;
	required_device<cd2501ecd_device>       m_speech;
	required_device<bus::ti99::gromport::gromport_device>   m_gromport;
	required_device<bus::ti99::internal::ioport_device>     m_ioport;

	required_device<ram_device>             m_sram;
	required_device<ram_device>             m_dram;

	// Debugging
	int m_last_ready;
	line_state m_crus_debug;

	// System GROM library
	tmc0430_device* m_sgrom[3];

	// Text-to-speech GROM library
	tmc0430_device* m_tsgrom[8];

	// Pascal 8 GROM library
	tmc0430_device* m_p8grom[8];

	// Pascal 3 GROM library
	tmc0430_device* m_p3grom[3];

	// Idle flags for GROMs
	bool m_sgrom_idle;
	bool m_tsgrom_idle;
	bool m_p8grom_idle;
	bool m_p3grom_idle;

	// ROM area of the system.
	uint8_t*   m_rom0;
	uint8_t*   m_rom1;
	uint8_t*   m_pascalrom;
};

} } } // end namespace bus::ti99::internal

#define MCFG_MAINBOARD8_READY_CALLBACK(_write) \
	devcb = &bus::ti99::internal::mainboard8_device::set_ready_wr_callback(*device, DEVCB_##_write);

#define MCFG_MAINBOARD8_RESET_CALLBACK(_write) \
	devcb = &bus::ti99::internal::mainboard8_device::set_reset_wr_callback(*device, DEVCB_##_write);

#define MCFG_MAINBOARD8_HOLD_CALLBACK(_write) \
	devcb = &bus::ti99::internal::mainboard8_device::set_hold_wr_callback(*device, DEVCB_##_write);

#define MCFG_OSO_INT_CALLBACK(_int) \
	devcb = &bus::ti99::internal::oso_device::set_int_callback(*device, DEVCB##_int);

DECLARE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device)
DECLARE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device)
DECLARE_DEVICE_TYPE_NS(TI99_MOFETTA,  bus::ti99::internal, mofetta_device)
DECLARE_DEVICE_TYPE_NS(TI99_AMIGO,    bus::ti99::internal, amigo_device)
DECLARE_DEVICE_TYPE_NS(TI99_OSO,      bus::ti99::internal, oso_device)

#endif // MAME_BUS_TI99_INTERNAL_998BOARD_H