summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/intv.cpp
blob: ff8943aebbd30f984aa16331852f11ab2f4a9165 (plain) (tree)
1
2
                       
                                                 


















































                                                                                                                                                                                                                

                          

                              
                         
                   
                     

                    




























                                            
                                     

                  
                        

                                             
                                    
         

                                           
                                           

                                                                   

         
                                    
         
                                            
                 

                                                         


                 
                                    
         
                                             
                 

                                                         



                 

                     










                                                   
                                     


                                                                     

















































                                                                                                                                 




                                                                                                             
                                                                    
                                                                                              

                          





                                                                                                                              



                                                                                                                                     





                                                                                                                              
                                                                    
                                                                                               


                                                                                                                




                                                                                              
                                                                    
                                                                                              

                          





                                                                                                                       
                                                                    
                                                                                                             

                          
                                                                                                             
                                                                                                             
                                                                                                             
                                                                                                              

                                                                                                             




                                                                                                                                                                         




                                                                                                                             
                                                                    
                                                                                                                                                                           


                                                                                                               




                                                                                                              
                                                                    
                                                                                              
 
                                                           







                                                                              

               





















































































                                                                                                                                     
                                                                                    




























































                                                                                                                                                
 













                                                                                         
                                                                               



         


                                                                           
                                                           
 
                                                  

 
                                                 
 
                                                   
                                                                                       

 
                                      
                                    


                                                                                       

                                                
                            
                                                      
                                       
 


                                                                               
                                                                 

                                                                                                                           
                                      
 
                                          
                                         
                                                 
 

                                                                                            
 
                            
                                               


                                                                                              

                                                   
                       
                                                               
 
                            

                                                                

                  

                                       

                                          

                  

                                          

                                             




                                                   

                                         

                                            
 


                                               
                                                  

                                                                                                                       
 
                      
                                         
 




                                                              

                  

                                         

                                            
 


                                                                             



                                                  
                                                                       

                                                 
 
                            
                                                           
                                  

                                                                                                                                                                                                  
 
                                    
                                                                    
 


                                                                                 




                                                                                                                         

       

                             


                                                                                                                                                                
                                                                                                                                     
                                             




                                                                                                                                                    




                                                                                                                         
 
                                             

                                                                                                                    

       








                                                             
 







                                                                           
                                             




                                                             


                                                                                                                     











                                                                                                                         


                                                                                                       
                                                                                                       

       
                            
 

                                          
                       

 
                               
 

                                             
                       


 





                                                                            




                                                                                                                                                                                           

                                                                        

                                                                                                                                                                                               
// license:BSD-3-Clause
// copyright-holders:Nathan Woods,Frank Palazzolo
/************************************************************************
 *  Mattel Intellivision + Keyboard Component Drivers
 *
 *  Frank Palazzolo
 *  Kyle Davis
 *
 *  TBD:
 *          Add tape support (intvkbd)
 *          Add runtime tape loading
 *          Fix memory system workaround
 *            (memory handler stuff in CP1610, debugger, and shared mem)
 *          STIC
 *            reenable dirty support
 *          Cleanup
 *            Separate stic & video better, get rid of *2 for kbd comp
 *          Add better runtime cart loading
 *          Switch to tilemap system
 * Note from kevtris about IntelliVoice Hookup:
<kevtris> the intv uses a special chip
<kevtris> called the SPB640
<kevtris> it is really cool and lame at the same time
<kevtris> it holds 64 10 bit words, which it simply serializes and sends to the SP0256
<kevtris> the SP0256-012 just blindly jumps to 02000h or something when you try to play one of the samples
<kevtris> the SPB640 sits at 2000h and when it sees that address come up, it will send out the 640 bits to the '256
<kevtris> this means you cannot use any gotos/gosubs in your speech data, but that is OK
<kevtris> it's just a single serial stream.  the intv simply watches the buffer state and refills it periodically.  there's enough buffer to keep it full for 1 frame
<kevtris> that's about it
<kevtris> the samples are stored in the game ROMs, and are easy to extract

9502, 9503 and 9504 are the chips used in the intv1 (the sears one may use different chips)
9505 is used in some carts
9503 and 9506 are the chips used in the intv2

Known roms so far:
RO-3-9502-011 = 4KiB(2Kiw) self-decoding mask rom with decoder & bus, (DIP40 containing 1/2 of EXEC, maps at words 0000-0fff or 1000-1fff [unclear which, guess is 0000], i/o maps at ?), located at U5 on intv1
RO-3-9503-003 = 2KiB(1Kiw) self-decoding mask rom with decoder & bus, (DIP40 containing GROM, maps at words 0x3000-0x37FF, i/o maps at ?), located at U21 in intv1, U5 in intv2
RO-3-9504-021 = 4KiB(2Kiw) self-decoding mask rom without decoder or bus, (DIP28 containing 1/2 of EXEC, maps at words 0000-0fff or 1000-1fff [unclear which, guess is 1000]), located at U6 in intv1
RO-3-9506-010 = 8KiB(4Kiw)+512B(256W) self-decoding mask rom with decoder & bus, (DIP40 containing EXEC2, maps at words 0000-1fff and 0400-04FF, i/o maps at ?) located at U6 in intv2

rom types (suspected, not proven yet):
RO-3-9502 = 4KiB (2Kiw) self decoding address mask rom with external address decoder & bus (DIP40)
RO-3-9503 = 2KiB (1Kiw) self decoding address mask rom with external address decoder & bus (DIP40)
RO-3-9504 = 4KiB (2Kiw) self decoding address mask rom without external address decoder or bus (DIP28)
RO-3-9505 = 8KiB (4Kiw) self decoding address mask rom without external address decoder or bus (DIP28)
RO-3-9506 = 8KiB (4Kiw) self decoding address mask rom with external address decoder & bus (DIP40)

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


#include "emu.h"
#include "includes/intv.h"

#include "cpu/m6502/m6502.h"
#include "cpu/cp1610/cp1610.h"
#include "sound/ay8910.h"
#include "screen.h"
#include "softlist.h"
#include "speaker.h"


#ifndef VERBOSE
#ifdef MAME_DEBUG
#define VERBOSE 1
#else
#define VERBOSE 0
#endif
#endif

static const unsigned char intv_colors[] =
{
	0x00, 0x00, 0x00, /* BLACK */
	0x00, 0x2D, 0xFF, /* BLUE */
	0xFF, 0x3D, 0x10, /* RED */
	0xC9, 0xCF, 0xAB, /* TAN */
	0x38, 0x6B, 0x3F, /* DARK GREEN */
	0x00, 0xA7, 0x56, /* GREEN */
	0xFA, 0xEA, 0x50, /* YELLOW */
	0xFF, 0xFC, 0xFF, /* WHITE */
	0xBD, 0xAC, 0xC8, /* GRAY */
	0x24, 0xB8, 0xFF, /* CYAN */
	0xFF, 0xB4, 0x1F, /* ORANGE */
	0x54, 0x6E, 0x00, /* BROWN */
	0xFF, 0x4E, 0x57, /* PINK */
	0xA4, 0x96, 0xFF, /* LIGHT BLUE */
	0x75, 0xCC, 0x80, /* YELLOW GREEN */
	0xB5, 0x1A, 0x58  /* PURPLE */
};

PALETTE_INIT_MEMBER(intv_state, intv)
{
	int k = 0;
	uint8_t r, g, b;
	/* Two copies of everything (why?) */

	for (int i = 0; i < 16; i++)
	{
		r = intv_colors[i * 3 + 0];
		g = intv_colors[i * 3 + 1];
		b = intv_colors[i * 3 + 2];
		palette.set_indirect_color(i, rgb_t(r, g, b));
		palette.set_indirect_color(i + 16, rgb_t(r, g, b));
	}

	for (int i = 0; i < 16; i++)
	{
		for (int j = 0; j < 16; j++)
		{
			palette.set_pen_indirect(k++, i);
			palette.set_pen_indirect(k++, j);
		}
	}

	for (int i = 0; i < 16; i++)
	{
		for (int j = 16; j < 32; j++)
		{
			palette.set_pen_indirect(k++, i);
			palette.set_pen_indirect(k++, j);
		}
	}
}

/* graphics output */

static const gfx_layout intvkbd_charlayout =
{
	8, 8,
	256,
	1,
	{ 0 },
	{ 0, 1, 2, 3, 4, 5, 6, 7 },
	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
	8 * 8
};

static GFXDECODE_START( gfx_intvkbd )
	GFXDECODE_ENTRY( "gfx1", 0x0000, intvkbd_charlayout, 0, 256 )
GFXDECODE_END


/*
        Bit 7   Bit 6   Bit 5   Bit 4   Bit 3   Bit 2   Bit 1   Bit 0

 Row 0  NC      NC      NC      NC      NC      NC      CTRL    SHIFT
 Row 1  NC      NC      NC      NC      NC      NC      RPT     LOCK
 Row 2  NC      /       ,       N       V       X       NC      SPC
 Row 3  (right) .       M       B       C       Z       NC      CLS
 Row 4  (down)  ;       K       H       F       S       NC      TAB
 Row 5  ]       P       I       Y       R       W       NC      Q
 Row 6  (up)    -       9       7       5       3       NC      1
 Row 7  =       0       8       6       4       2       NC      [
 Row 8  (return)(left)  O       U       T       E       NC      ESC
 Row 9  DEL     '       L       J       G       D       NC      A

2008-05 FP:
The keyboard layout is quite strange, with '[' and ']' at the two ends of the 1st row,
'Esc' in the 2nd row (between 'Tab' and 'Q'), and with Cursor keys and 'Enter' where
you would expect the braces. Moreover, Shift + Cursor keys produce characters.
The emulated layout moves 'Esc', '[' and ']' to their usual position.

Moreover, a small note on natural keyboard support: currently
- "Clear Screen" is mapped to 'Left Alt'
- "Repeat" is mapped to 'F1'
- "Lock" is mapped to 'F2'
*/

static INPUT_PORTS_START( intvkbd )
	PORT_START("ROW0")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)

	PORT_START("ROW1")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("REPEAT") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(F1))
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LOCK") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(F2))

	PORT_START("ROW2")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH)   PORT_CHAR('/') PORT_CHAR('?')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA)   PORT_CHAR(',')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N)       PORT_CHAR('N')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V)       PORT_CHAR('V')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X)       PORT_CHAR('X')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE)   PORT_CHAR(' ')

	PORT_START("ROW3")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT)   PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR('>')
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP)    PORT_CHAR('.')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M)       PORT_CHAR('M')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B)       PORT_CHAR('B')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C)       PORT_CHAR('C')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z)       PORT_CHAR('Z')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clear Screen") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))

	PORT_START("ROW4")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN)    PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR('\\')
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON)   PORT_CHAR(';') PORT_CHAR(':')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K)       PORT_CHAR('K')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H)       PORT_CHAR('H')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F)       PORT_CHAR('F')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S)       PORT_CHAR('S')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB)     PORT_CHAR('\t')

	PORT_START("ROW5")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P)       PORT_CHAR('P')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I)       PORT_CHAR('I')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y)       PORT_CHAR('Y')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R)       PORT_CHAR('R')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W)       PORT_CHAR('W')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q)       PORT_CHAR('Q')

	PORT_START("ROW6")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP)  PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR('|')
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS)   PORT_CHAR('_') PORT_CHAR('-')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)       PORT_CHAR('9') PORT_CHAR('(')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)       PORT_CHAR('7') PORT_CHAR('&')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)       PORT_CHAR('5') PORT_CHAR('%')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)       PORT_CHAR('3') PORT_CHAR('#')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)       PORT_CHAR('1') PORT_CHAR('!')

	PORT_START("ROW7")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS)  PORT_CHAR('=') PORT_CHAR('+')
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0)       PORT_CHAR('0') PORT_CHAR(')')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)       PORT_CHAR('8') PORT_CHAR('*')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)       PORT_CHAR('6') PORT_CHAR(0xA2)
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)       PORT_CHAR('4') PORT_CHAR('$')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)       PORT_CHAR('2') PORT_CHAR('@')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') // this one would be 1st row, 1st key (at 'Esc' position)

	PORT_START("ROW8")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT)    PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR('<')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O)       PORT_CHAR('O')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U)       PORT_CHAR('U')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T)       PORT_CHAR('T')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E)       PORT_CHAR('E')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC)     PORT_CHAR(UCHAR_MAMEKEY(ESC)) // this one would be 2nd row, 2nd key (between 'Tab' and 'Q')

	PORT_START("ROW9")
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE)   PORT_CHAR('\'') PORT_CHAR('"')
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L)       PORT_CHAR('L')
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J)       PORT_CHAR('J')
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G)       PORT_CHAR('G')
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D)       PORT_CHAR('D')
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("NC")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A)       PORT_CHAR('A')

	PORT_START("TEST")  /* For tape drive testing... */
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD)
	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD)
	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD)
	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD)
	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD)
	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)
	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)
	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)
INPUT_PORTS_END

void intv_state::intv_mem(address_map &map)
{
	map(0x0000, 0x003f).rw(this, FUNC(intv_state::intv_stic_r), FUNC(intv_state::intv_stic_w));
	map(0x0100, 0x01ef).rw(this, FUNC(intv_state::intv_ram8_r), FUNC(intv_state::intv_ram8_w));
	map(0x01f0, 0x01ff).rw(m_sound, FUNC(ay8914_device::read), FUNC(ay8914_device::write)).umask16(0x00ff);
	map(0x0200, 0x035f).rw(this, FUNC(intv_state::intv_ram16_r), FUNC(intv_state::intv_ram16_w));
	map(0x0400, 0x04ff).r(m_cart, FUNC(intv_cart_slot_device::read_rom04));
	map(0x1000, 0x1fff).rom().region("maincpu", 0x1000 << 1);   // Exec ROM, 10-bits wide
	map(0x2000, 0x2fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom20));
	map(0x3000, 0x37ff).r(m_stic, FUNC(stic_device::grom_read)); // GROM,     8-bits wide
	map(0x3800, 0x39ff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));     // GRAM,     8-bits wide
	map(0x3a00, 0x3bff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));     // GRAM Alias, 8-bits wide
	map(0x4000, 0x47ff).r(m_cart, FUNC(intv_cart_slot_device::read_rom40));
	map(0x4800, 0x4fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom48));
	map(0x5000, 0x5fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom50));
	map(0x6000, 0x6fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom60));
	map(0x7000, 0x7fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom70));
	map(0x8000, 0x8fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom80));
	map(0x9000, 0x9fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom90));
	map(0xa000, 0xafff).r(m_cart, FUNC(intv_cart_slot_device::read_roma0));
	map(0xb000, 0xbfff).r(m_cart, FUNC(intv_cart_slot_device::read_romb0));
	map(0xc000, 0xcfff).r(m_cart, FUNC(intv_cart_slot_device::read_romc0));
	map(0xd000, 0xdfff).r(m_cart, FUNC(intv_cart_slot_device::read_romd0));
	map(0xe000, 0xefff).r(m_cart, FUNC(intv_cart_slot_device::read_rome0));
	map(0xf000, 0xffff).r(m_cart, FUNC(intv_cart_slot_device::read_romf0));
}

void intv_state::intvoice_mem(address_map &map)
{
	map(0x0000, 0x003f).rw(this, FUNC(intv_state::intv_stic_r), FUNC(intv_state::intv_stic_w));
	map(0x0080, 0x0081).rw("voice", FUNC(intv_voice_device::read_speech), FUNC(intv_voice_device::write_speech)); // Intellivoice
	map(0x0100, 0x01ef).rw(this, FUNC(intv_state::intv_ram8_r), FUNC(intv_state::intv_ram8_w));
	map(0x01f0, 0x01ff).rw(m_sound, FUNC(ay8914_device::read), FUNC(ay8914_device::write)).umask16(0x00ff);
	map(0x0200, 0x035f).rw(this, FUNC(intv_state::intv_ram16_r), FUNC(intv_state::intv_ram16_w));
	map(0x0400, 0x04ff).r("voice", FUNC(intv_voice_device::read_rom04));
	map(0x1000, 0x1fff).rom().region("maincpu", 0x1000 << 1);   // Exec ROM, 10-bits wide
	map(0x2000, 0x2fff).r("voice", FUNC(intv_voice_device::read_rom20));
	map(0x3000, 0x37ff).r(m_stic, FUNC(stic_device::grom_read)); // GROM,     8-bits wide
	map(0x3800, 0x39ff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));     // GRAM,     8-bits wide
	map(0x3a00, 0x3bff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));     // GRAM Alias, 8-bits wide
	map(0x4000, 0x47ff).r("voice", FUNC(intv_voice_device::read_rom40));
	map(0x4800, 0x4fff).r("voice", FUNC(intv_voice_device::read_rom48));
	map(0x5000, 0x5fff).r("voice", FUNC(intv_voice_device::read_rom50));
	map(0x6000, 0x6fff).r("voice", FUNC(intv_voice_device::read_rom60));
	map(0x7000, 0x7fff).r("voice", FUNC(intv_voice_device::read_rom70));
	map(0x8000, 0x8fff).r("voice", FUNC(intv_voice_device::read_rom80));
	map(0x9000, 0x9fff).r("voice", FUNC(intv_voice_device::read_rom90));
	map(0xa000, 0xafff).r("voice", FUNC(intv_voice_device::read_roma0));
	map(0xb000, 0xbfff).r("voice", FUNC(intv_voice_device::read_romb0));
	map(0xc000, 0xcfff).r("voice", FUNC(intv_voice_device::read_romc0));
	map(0xd000, 0xdfff).r("voice", FUNC(intv_voice_device::read_romd0));
	map(0xe000, 0xefff).r("voice", FUNC(intv_voice_device::read_rome0));
	map(0xf000, 0xffff).r("voice", FUNC(intv_voice_device::read_romf0));
}

void intv_state::intv2_mem(address_map &map)
{
	map(0x0000, 0x003f).rw(this, FUNC(intv_state::intv_stic_r), FUNC(intv_state::intv_stic_w));
	map(0x0100, 0x01ef).rw(this, FUNC(intv_state::intv_ram8_r), FUNC(intv_state::intv_ram8_w));
	map(0x01f0, 0x01ff).rw(m_sound, FUNC(ay8914_device::read), FUNC(ay8914_device::write)).umask16(0x00ff);
	map(0x0200, 0x035f).rw(this, FUNC(intv_state::intv_ram16_r), FUNC(intv_state::intv_ram16_w));
	map(0x0400, 0x04ff).rom().region("maincpu", 0x400 << 1);    // Exec ROM, 10-bits wide
	map(0x1000, 0x1fff).rom().region("maincpu", 0x1000 << 1);   // Exec ROM, 10-bits wide
	map(0x2000, 0x2fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom20));
	map(0x3000, 0x37ff).r(m_stic, FUNC(stic_device::grom_read)); // GROM,     8-bits wide
	map(0x3800, 0x39ff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w)); // GRAM,     8-bits wide
	map(0x3a00, 0x3bff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w)); // GRAM Alias, 8-bits wide
	map(0x4000, 0x47ff).r(m_cart, FUNC(intv_cart_slot_device::read_rom40));
	map(0x4800, 0x4fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom48));
	map(0x5000, 0x5fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom50));
	map(0x6000, 0x6fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom60));
	map(0x7000, 0x7fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom70));
	map(0x8000, 0x8fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom80));
	map(0x9000, 0x9fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom90));
	map(0xa000, 0xafff).r(m_cart, FUNC(intv_cart_slot_device::read_roma0));
	map(0xb000, 0xbfff).r(m_cart, FUNC(intv_cart_slot_device::read_romb0));
	map(0xc000, 0xcfff).r(m_cart, FUNC(intv_cart_slot_device::read_romc0));
	map(0xd000, 0xdfff).r(m_cart, FUNC(intv_cart_slot_device::read_romd0));
	map(0xe000, 0xefff).r(m_cart, FUNC(intv_cart_slot_device::read_rome0));
	map(0xf000, 0xffff).r(m_cart, FUNC(intv_cart_slot_device::read_romf0));
}

void intv_state::intvecs_mem(address_map &map)
{
	map(0x0000, 0x003f).rw(this, FUNC(intv_state::intv_stic_r), FUNC(intv_state::intv_stic_w));
	map(0x0080, 0x0081).rw("speech", FUNC(sp0256_device::spb640_r), FUNC(sp0256_device::spb640_w)); /* Intellivoice */
	// AM_RANGE(0x00E0, 0x00E3) AM_READWRITE( intv_ecs_uart_r, intv_ecs_uart_w )
	map(0x00f0, 0x00ff).rw("ecs", FUNC(intv_ecs_device::read_ay), FUNC(intv_ecs_device::write_ay)); /* ecs psg */
	map(0x0100, 0x01ef).rw(this, FUNC(intv_state::intv_ram8_r), FUNC(intv_state::intv_ram8_w));
	map(0x01f0, 0x01ff).rw(m_sound, FUNC(ay8914_device::read), FUNC(ay8914_device::write)).umask16(0x00ff);
	map(0x0200, 0x035f).rw(this, FUNC(intv_state::intv_ram16_r), FUNC(intv_state::intv_ram16_w));
	map(0x0400, 0x04ff).r("ecs", FUNC(intv_ecs_device::read_rom04));
	map(0x1000, 0x1fff).rom().region("maincpu", 0x1000<<1); /* Exec ROM, 10-bits wide */
	map(0x2000, 0x2fff).rw("ecs", FUNC(intv_ecs_device::read_rom20), FUNC(intv_ecs_device::write_rom20));
	map(0x3000, 0x37ff).r(m_stic, FUNC(stic_device::grom_read)); /* GROM,     8-bits wide */
	map(0x3800, 0x39ff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));       /* GRAM,     8-bits wide */
	map(0x3a00, 0x3bff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));       /* GRAM Alias,     8-bits wide */
	map(0x4000, 0x47ff).rw("ecs", FUNC(intv_ecs_device::read_ram), FUNC(intv_ecs_device::write_ram));
	map(0x4800, 0x4fff).r("ecs", FUNC(intv_ecs_device::read_rom48));
	map(0x5000, 0x5fff).r("ecs", FUNC(intv_ecs_device::read_rom50));
	map(0x6000, 0x6fff).r("ecs", FUNC(intv_ecs_device::read_rom60));
	map(0x7000, 0x7fff).rw("ecs", FUNC(intv_ecs_device::read_rom70), FUNC(intv_ecs_device::write_rom70));
	map(0x8000, 0x8fff).r("ecs", FUNC(intv_ecs_device::read_rom80));
	map(0x9000, 0x9fff).r("ecs", FUNC(intv_ecs_device::read_rom90));
	map(0xa000, 0xafff).r("ecs", FUNC(intv_ecs_device::read_roma0));
	map(0xb000, 0xbfff).r("ecs", FUNC(intv_ecs_device::read_romb0));
	map(0xc000, 0xcfff).r("ecs", FUNC(intv_ecs_device::read_romc0));
	map(0xd000, 0xdfff).r("ecs", FUNC(intv_ecs_device::read_romd0));
	map(0xe000, 0xefff).rw("ecs", FUNC(intv_ecs_device::read_rome0), FUNC(intv_ecs_device::write_rome0));
	map(0xf000, 0xffff).rw("ecs", FUNC(intv_ecs_device::read_romf0), FUNC(intv_ecs_device::write_romf0));
}

void intv_state::intvkbd_mem(address_map &map)
{
	map(0x0000, 0x003f).rw(this, FUNC(intv_state::intv_stic_r), FUNC(intv_state::intv_stic_w));
	map(0x0100, 0x01ef).rw(this, FUNC(intv_state::intv_ram8_r), FUNC(intv_state::intv_ram8_w));
	map(0x01f0, 0x01ff).rw(m_sound, FUNC(ay8914_device::read), FUNC(ay8914_device::write)).umask16(0x00ff);
	map(0x0200, 0x035f).rw(this, FUNC(intv_state::intv_ram16_r), FUNC(intv_state::intv_ram16_w));
	map(0x0400, 0x04ff).r(m_cart, FUNC(intv_cart_slot_device::read_rom04));
	map(0x1000, 0x1fff).rom().region("maincpu", 0x1000<<1); /* Exec ROM, 10-bits wide */
	map(0x2000, 0x2fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom20));
	map(0x3000, 0x37ff).r(m_stic, FUNC(stic_device::grom_read)); /* GROM,     8-bits wide */
	map(0x3800, 0x39ff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));       /* GRAM,     8-bits wide */
	map(0x3a00, 0x3bff).rw(this, FUNC(intv_state::intv_gram_r), FUNC(intv_state::intv_gram_w));       /* GRAM Alias,     8-bits wide */
	map(0x4000, 0x47ff).r(m_cart, FUNC(intv_cart_slot_device::read_rom40));
	map(0x4800, 0x4fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom48));
	map(0x5000, 0x5fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom50));
	map(0x6000, 0x6fff).r(m_cart, FUNC(intv_cart_slot_device::read_rom60));
	map(0x7000, 0x7fff).rom().region("maincpu", 0x7000<<1); /* Keyboard ROM */
	map(0x8000, 0xbfff).ram().w(this, FUNC(intv_state::intvkbd_dualport16_w)).share("dualport_ram");  /* Dual-port RAM */
	map(0xc000, 0xcfff).r(m_cart, FUNC(intv_cart_slot_device::read_romc0));
	map(0xd000, 0xdfff).r(m_cart, FUNC(intv_cart_slot_device::read_romd0));
	map(0xe000, 0xefff).r(m_cart, FUNC(intv_cart_slot_device::read_rome0));
	map(0xf000, 0xffff).r(m_cart, FUNC(intv_cart_slot_device::read_romf0));
}

void intv_state::intvkbd2_mem(address_map &map)
{
	map.unmap_value_high();  /* Required because of probing */
	map(0x0000, 0x3fff).rw(this, FUNC(intv_state::intvkbd_dualport8_lsb_r), FUNC(intv_state::intvkbd_dualport8_lsb_w));  /* Dual-port RAM */
	map(0x4000, 0x40bf).rw(this, FUNC(intv_state::intvkbd_io_r), FUNC(intv_state::intvkbd_io_w));
	map(0x40c0, 0x40cf).rw(m_crtc, FUNC(tms9927_device::read), FUNC(tms9927_device::write));
	map(0x4200, 0x7fff).rw(this, FUNC(intv_state::intvkbd_dualport8_msb_r), FUNC(intv_state::intvkbd_dualport8_msb_w));  /* Dual-port RAM */
	map(0xb7f8, 0xb7ff).rw(this, FUNC(intv_state::intvkbd_periph_r), FUNC(intv_state::intvkbd_periph_w));
	map(0xb800, 0xbfff).ram().share("videoram"); /* Text Display */
	map(0xc000, 0xdfff).rom();
	map(0xe000, 0xffff).r(this, FUNC(intv_state::intvkb_iocart_r));
}

void intv_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id)
	{
	case TIMER_INTV_INTERRUPT2_COMPLETE:
		intv_interrupt2_complete(ptr, param);
		break;
	case TIMER_INTV_INTERRUPT_COMPLETE:
		intv_interrupt_complete(ptr, param);
		break;
	case TIMER_INTV_BTB_FILL:
		intv_btb_fill(ptr, param);
		break;
	default:
		assert_always(false, "Unknown id in intv_state::device_timer");
	}
}


/* This is needed because MAME core does not allow PULSE_LINE.
    The time interval is not critical, although it should be below 1000. */

TIMER_CALLBACK_MEMBER(intv_state::intv_interrupt2_complete)
{
	m_keyboard->set_input_line(0, CLEAR_LINE);
}

INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt2)
{
	m_keyboard->set_input_line(0, ASSERT_LINE);
	timer_set(m_keyboard->cycles_to_attotime(100), TIMER_INTV_INTERRUPT2_COMPLETE);
}

MACHINE_CONFIG_START(intv_state::intv)
	/* basic machine hardware */
	MCFG_DEVICE_ADD("maincpu", CP1610, XTAL(3'579'545)/4)        /* Colorburst/4 */
	MCFG_DEVICE_PROGRAM_MAP(intv_mem)
	MCFG_DEVICE_VBLANK_INT_DRIVER("screen", intv_state,  intv_interrupt)
	MCFG_QUANTUM_TIME(attotime::from_hz(60))

	/* video hardware */
	MCFG_DEVICE_ADD("stic", STIC, XTAL(3'579'545))
	MCFG_VIDEO_SET_SCREEN("screen")

	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(59.92)
	//MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2400)) /* not accurate */
	MCFG_SCREEN_UPDATE_DRIVER(intv_state, screen_update_intv)
	MCFG_SCREEN_SIZE(stic_device::SCREEN_WIDTH*INTV_X_SCALE, stic_device::SCREEN_HEIGHT*INTV_Y_SCALE)
	MCFG_SCREEN_VISIBLE_AREA(0, stic_device::SCREEN_WIDTH*INTV_X_SCALE-1, 0, stic_device::SCREEN_HEIGHT*INTV_Y_SCALE-1)
	MCFG_SCREEN_PALETTE("palette")

	MCFG_PALETTE_ADD("palette", 0x400)
	MCFG_PALETTE_INDIRECT_ENTRIES(32)
	MCFG_PALETTE_INIT_OWNER(intv_state, intv)

	MCFG_INTV_CONTROL_PORT_ADD("iopt_right_ctrl", intv_control_port_devices, "handctrl")
	MCFG_INTV_CONTROL_PORT_ADD("iopt_left_ctrl", intv_control_port_devices, "handctrl")

	/* sound hardware */
	SPEAKER(config, "mono").front_center();
	MCFG_DEVICE_ADD("ay8914", AY8914, XTAL(3'579'545)/2)
	MCFG_AY8910_PORT_A_READ_CB(READ8("iopt_right_ctrl", intv_control_port_device, ctrl_r))
	MCFG_AY8910_PORT_B_READ_CB(READ8("iopt_left_ctrl",  intv_control_port_device, ctrl_r))
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.33)

	/* cartridge */
	MCFG_INTV_CARTRIDGE_ADD("cartslot", intv_cart, nullptr)

	/* software lists */
	MCFG_SOFTWARE_LIST_ADD("cart_list", "intv")
	MCFG_SOFTWARE_LIST_COMPATIBLE_ADD("ecs_list", "intvecs")
MACHINE_CONFIG_END

MACHINE_CONFIG_START(intv_state::intv2)
	intv(config);
	MCFG_DEVICE_MODIFY( "maincpu" )
	MCFG_DEVICE_PROGRAM_MAP(intv2_mem)
MACHINE_CONFIG_END

MACHINE_CONFIG_START(intv_state::intvoice)
	intv(config);
	MCFG_DEVICE_MODIFY( "maincpu" )
	MCFG_DEVICE_PROGRAM_MAP(intvoice_mem)

	MCFG_DEVICE_REMOVE("cartslot")
	MCFG_DEVICE_ADD("voice", INTV_ROM_VOICE, 0)
MACHINE_CONFIG_END

MACHINE_CONFIG_START(intv_state::intvecs)
	intv(config);
	MCFG_DEVICE_MODIFY( "maincpu" )
	MCFG_DEVICE_PROGRAM_MAP(intvecs_mem)

	MCFG_DEVICE_REMOVE("cartslot")
	MCFG_DEVICE_ADD("ecs", INTV_ROM_ECS, 0)

	MCFG_DEVICE_ADD("speech", SP0256, 3120000)
	/* The Intellivoice uses a speaker with its own volume control so the relative volumes to use are subjective */
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)

	/* cassette */
	//MCFG_CASSETTE_ADD( "cassette" )

	/* software lists */
	MCFG_DEVICE_REMOVE("cart_list")
	MCFG_DEVICE_REMOVE("ecs_list")
	MCFG_SOFTWARE_LIST_ADD("cart_list", "intvecs")
	MCFG_SOFTWARE_LIST_COMPATIBLE_ADD("intv_list", "intv")
MACHINE_CONFIG_END

MACHINE_CONFIG_START(intv_state::intvkbd)
	intv(config);
	MCFG_DEVICE_MODIFY( "maincpu" )
	MCFG_DEVICE_PROGRAM_MAP(intvkbd_mem)

	MCFG_DEVICE_ADD("keyboard", M6502, XTAL(7'159'090)/8)
	MCFG_DEVICE_PROGRAM_MAP(intvkbd2_mem)
	MCFG_DEVICE_VBLANK_INT_DRIVER("screen", intv_state,  intv_interrupt2)

	MCFG_QUANTUM_TIME(attotime::from_hz(6000))

	/* video hardware */
	MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_intvkbd)
	MCFG_PALETTE_MODIFY("palette")
	MCFG_PALETTE_INIT_OWNER(intv_state, intv)

	/* crt controller */
	MCFG_DEVICE_ADD("crtc", TMS9927, XTAL(7'159'090)/8)
	MCFG_TMS9927_CHAR_WIDTH(8)
	MCFG_TMS9927_OVERSCAN(stic_device::OVERSCAN_LEFT_WIDTH*stic_device::X_SCALE*INTVKBD_X_SCALE, stic_device::OVERSCAN_RIGHT_WIDTH*stic_device::X_SCALE*INTVKBD_X_SCALE,
						  stic_device::OVERSCAN_TOP_HEIGHT*stic_device::Y_SCALE*INTVKBD_Y_SCALE, stic_device::OVERSCAN_BOTTOM_HEIGHT*stic_device::Y_SCALE*INTVKBD_Y_SCALE)

	MCFG_SCREEN_MODIFY("screen")
	MCFG_SCREEN_UPDATE_DRIVER(intv_state, screen_update_intvkbd)

	/* I/O cartslots for BASIC */
	MCFG_GENERIC_CARTSLOT_ADD("ioslot1", generic_plain_slot, "intbasic_cart")
	MCFG_GENERIC_CARTSLOT_ADD("ioslot2", generic_plain_slot, "intbasic_cart")
MACHINE_CONFIG_END

ROM_START(intv) // the intv1 exec rom should be two roms: RO-3-9502-011.U5 and RO-3-9504-021.U6
	ROM_REGION(0x10000<<1,"maincpu", ROMREGION_ERASEFF)
	ROM_LOAD16_WORD( "exec.bin", (0x1000<<1)+0, 0x2000, CRC(cbce86f7) SHA1(5a65b922b562cb1f57dab51b73151283f0e20c7a))
ROM_END

#define rom_intvoice rom_intv

// the later intellivision 2's exec rom is a single ro-3-9506-010 at location ic6 holding 8k plus 512 bytes; the 1st 512 bytes are at 0x400 and the 8k at 0x1000
ROM_START(intv2)
	ROM_REGION(0x10000<<1,"maincpu", ROMREGION_ERASEFF)
	ROM_LOAD16_WORD_SWAP( "ro-3-9506-010.ic6", (0x400<<1)+0, 0x200, CRC(dd7e1237) SHA1(fb821a643b7714ed4c812553cd3f668766fd44ab))
	ROM_CONTINUE( (0x1000<<1)+0, 0x2000 )
ROM_END

ROM_START(intvsrs) // the intv1 sears exec rom should be two roms: RO-3-9502-???.U5 and RO-3-9504-???.U6 but the correct names are unknown as of yet
	ROM_REGION(0x10000<<1,"maincpu", ROMREGION_ERASEFF)
	ROM_LOAD16_WORD( "searsexc.bin", (0x1000<<1)+0, 0x2000, CRC(ea552a22) SHA1(834339de056d42a35571cae7fd5b04d1344001e9))
ROM_END

ROM_START(intvecs) // the intv1 exec rom should be two roms: RO-3-9502-011.U5 and RO-3-9504-021.U6
	ROM_REGION(0x10000<<1,"maincpu", ROMREGION_ERASEFF)
	ROM_LOAD16_WORD( "exec.bin", (0x1000<<1)+0, 0x2000, CRC(cbce86f7) SHA1(5a65b922b562cb1f57dab51b73151283f0e20c7a))

	ROM_REGION( 0x10000<<1, "speech", 0 )
	/* SP0256-012 Speech chip w/2KiB mask rom */
	ROM_LOAD( "sp0256-012.bin",   0x1000, 0x0800, CRC(0de7579d) SHA1(618563e512ff5665183664f52270fa9606c9d289) )
ROM_END

/*
Intellivision Keyboard Component - Prototype
-------------------------------------------------------------

GI    9333B-0104         0104.U20  4Kx8  Mask ROM, 6502 code
Intel 2732 "CPU 2D"     CPU2D.U21  4Kx8  EPROM, 6502 code

TI    8S030N  1149-0360  0360.U58  32x8  Timing prom?
TI    8S030N  1149-0370  0370.U74  32x8  Timing prom?

GI    RO-3-9502-024       024.U60  2Kx10 Mask ROM+Addr Decoder, CP1600 code
GI    9316B-4D72         4D72.U62  2Kx8  Mask ROM, CP1600 code (upper)
GI    9316B-4D71         4D71.U63  2Kx8  Mask ROM, CP1600 code (lower)
GI    9316B-4C52         4C52.U34  2Kx8  Mask ROM, Alphanumerics

Main board also includes:

    2  2114 DRAMS        1Kx4  Character memory
    10 MM5290J DRAMS    16Kx10 CP1600 memory?
    1  6502
    1  Mystery 40-pin chip (under heat sink)
       (actually a SMC CRT5027 aka TI TMS9927 CRT controller)
*/

ROM_START(intvkbd) // the intv1 exec rom should be two roms: RO-3-9502-011.U5 and RO-3-9504-021.U6
	ROM_REGION(0x10000<<1,"maincpu", ROMREGION_ERASEFF)
	ROM_LOAD16_WORD( "exec.bin", 0x1000<<1, 0x2000, CRC(cbce86f7) SHA1(5a65b922b562cb1f57dab51b73151283f0e20c7a))
	ROM_LOAD16_WORD( "024.u60",  0x7000<<1, 0x1000, CRC(4f7998ec) SHA1(ec006d0ae9002e9d56d83a71f5f2eddd6a456a40))
	ROM_LOAD16_BYTE( "4d72.u62", 0x7800<<1, 0x0800, CRC(aa57c594) SHA1(741860d489d90f5882ca53daa3169b6abacdf130))
	ROM_LOAD16_BYTE( "4d71.u63", (0x7800<<1)+1, 0x0800, CRC(069b2f0b) SHA1(070850bb32f8474107cc52c5183cfaa32d640f9a))

	ROM_REGION(0x10000,"keyboard",0)
	ROM_LOAD( "0104.u20",  0xc000, 0x1000, CRC(5c6f1256) SHA1(271931fb354dfae6a1a5697ee888924a89a15ca8))
	ROM_RELOAD( 0xe000, 0x1000 )
	ROM_LOAD("cpu2d.u21",  0xd000, 0x1000, CRC(2c2dba33) SHA1(0db5d177fec3f8ae89abeef2e6900ad4f3460266))
	ROM_RELOAD( 0xf000, 0x1000 )

	ROM_REGION(0x00800,"gfx1",0)
	ROM_LOAD( "4c52.u34",  0x0000, 0x0800, CRC(cbeb2e96) SHA1(f0e17adcd278fb376c9f90833c7fbbb60193dbe3))

	ROM_REGION(0x0100,"proms",0)
	ROM_LOAD( "0360.u58", 0x00, 0x20, CRC(1295528a) SHA1(b35e598891f1185e02cbacb4811d2334357abd79))
	ROM_LOAD( "0370.u74", 0x20, 0x20, CRC(19da5096) SHA1(76af50e4fd29649fc4837120c245321a8fc84cd3))
ROM_END

void intv_state::init_intv()
{
	m_stic->set_x_scale(INTV_X_SCALE);
	m_stic->set_y_scale(INTV_Y_SCALE);
	m_is_keybd = 0;
}

void intv_state::init_intvkbd()
{
	m_stic->set_x_scale(INTVKBD_X_SCALE);
	m_stic->set_y_scale(INTVKBD_Y_SCALE);
	m_is_keybd = 1;
}


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

  Game driver(s)

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

/*    YEAR  NAME      PARENT  COMPAT  MACHINE   INPUT    CLASS       INIT          COMPANY   FULLNAME */
CONS( 1979, intv,     0,      0,      intv,     0,       intv_state, init_intv,    "Mattel", "Intellivision", MACHINE_SUPPORTS_SAVE )
CONS( 1981, intvsrs,  intv,   0,      intv,     0,       intv_state, init_intv,    "Sears",  "Super Video Arcade", MACHINE_SUPPORTS_SAVE )
COMP( 1981, intvkbd,  intv,   0,      intvkbd,  intvkbd, intv_state, init_intvkbd, "Mattel", "Intellivision Keyboard Component (Unreleased)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
CONS( 1982, intv2,    intv,   0,      intv2,    0,       intv_state, init_intv,    "Mattel", "Intellivision II", MACHINE_SUPPORTS_SAVE )

// made up, user friendlier machines with pre-mounted passthu expansions
COMP( 1982, intvoice, intv,   0,      intvoice, 0,       intv_state, init_intv,    "Mattel", "Intellivision w/IntelliVoice expansion", MACHINE_SUPPORTS_SAVE )
COMP( 1983, intvecs,  intv,   0,      intvecs,  0,       intv_state, init_intv,    "Mattel", "Intellivision w/Entertainment Computer System + Intellivoice expansions", MACHINE_SUPPORTS_SAVE )