summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/argo.cpp
blob: 090172d407f40d905b209ec996b8e568c0af5069 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                             
                                                                                        
 
    
 
                           
 
                                                                 
                                                                          
 


                                                                     
 
                       
 
     
                                          
                                        


                                                                   

                                                                                   
 
                                                                                         


                        
                          


                            


                              

                          
                   
 



                                       
                                                                                    

                                                   

                                         
                                               
                                       


                                       
                                           

                                                
           
 

                                          
        

                                              


                                                     


                                                         
                                

                                                    
 

                                       
 



                                                     
                                            
                                             


                                              
                                                      

                                                  
                      
                        
                         

                                            

                                     


                                                                                        
                                                        
 
                       
                                      
            
                                      

 
                                       
 
                           


                       





                                                             
 





                                             
 


                             
                                              

                                               
                 
                                                 


                                                                                                   






                                                                            
                                                  
 
                       
         





                                             

                      








                                                           

                                                          

                      


                             
                                              

                      

                                                          
                 
                                                                      
                                          
                 
                                      


                      
                                                                                     


         
                                                    
 









                                                                     
                                                       
 


















                                                          
                                 



                                                             
 
                                 
 
 
                                   



                                                                      
                                              













                                                                      
                                                                 













                                                            
                           
















                                                                                     
                                    












                                                               
                                                              
             
 


                                          

                                                                                            



                                         




                                                                                                                   
 




























































































                                                                                                                                      
                         







                                                                                                                                                                        


               
 
                                
 















                                                                                                                               

 
                                
 











                                                 

 
 

                                             
                                    
                                                             

                                                                 

                            

                                                                            
                                  
                                  


                                                                            







                                                                                                        
                                                                                                           




                                                                              














                                                                                               
                                                                    

                                                                       
 


                    

                                                                                                            







                                                                                                                        

                                                                                                                                                                 
// license:BSD-3-Clause
// copyright-holders:Robbbert
/***************************************************************************************

Argo

2011-03-16 Skeleton driver.

There are no manuals, diagrams, or anything else available afaik.
The entire driver is guesswork, however it appears to be related to UNIOR.

The monitor will only allow certain characters to be typed, thus the
modifier keys appear to do nothing. There is no need to use the enter
key; using spacebar and the correct parameters is enough.

Commands: same as UNIOR

ToDo:
- Add remaining devices, most likely 8255.
- There is no obvious evidence of sound.
- Need dump of the correct chargen.
- Find out if "m_eram" is supposed to exist, if so, what is it for?
- What character should show in the top left corner?
- our dma doesn't emulate the update_flag, so had to use a hack for the L command
- cursor is one character further to the right than it should be, used another hack

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

#include "emu.h"
#include "cpu/z80/z80.h"
#include "machine/i8251.h"
#include "machine/pit8253.h"
#include "machine/i8257.h"
#include "video/i8275.h"
#include "imagedev/cassette.h"
//#include "sound/spkrdev.h"
#include "speaker.h"
#include "machine/timer.h"
#include "emupal.h"
#include "screen.h"


class argo_state : public driver_device
{
public:
	argo_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag)
		, m_maincpu(*this, "maincpu")
		, m_rom(*this, "maincpu")
		, m_ram(*this, "mainram")
		, m_p_chargen(*this, "chargen")
		, m_uart(*this, "uart")
		, m_pit(*this, "pit")
		, m_dma(*this, "dma")
		, m_crtc(*this, "crtc")
		, m_cass(*this, "cassette")
		, m_palette(*this, "palette")
		, m_io_keyboard(*this, "X%d", 0)
	{ }

	void argo(machine_config &config);

private:
	virtual void machine_reset() override;
	virtual void machine_start() override;
	void argo_videoram_w(offs_t offset, u8 data);
	u8 argo_io_r(offs_t offset);
	void argo_io_w(offs_t offset, u8 data);
	DECLARE_WRITE_LINE_MEMBER(z0_w);
	DECLARE_WRITE_LINE_MEMBER(hrq_w);
	void argo_palette(palette_device &palette) const;
	u8 dma_r(offs_t offset);
	I8275_DRAW_CHARACTER_MEMBER(display_pixels);
	TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);

	void io_map(address_map &map);
	void mem_map(address_map &map);

	memory_passthrough_handler *m_rom_shadow_tap;
	required_device<z80_device> m_maincpu;
	required_region_ptr<u8> m_rom;
	required_shared_ptr<u8> m_ram;
	required_region_ptr<u8> m_p_chargen;
	required_device<i8251_device> m_uart;
	required_device<pit8253_device> m_pit;
	required_device<i8257_device> m_dma;
	required_device<i8275_device> m_crtc;
	required_device<cassette_image_device> m_cass;
	required_device<palette_device> m_palette;
	required_ioport_array<11> m_io_keyboard;
	u8 m_framecnt;
	bool m_ram_ctrl;
	u8 m_scroll_ctrl;
	bool m_txe, m_txd, m_rts, m_casspol;
	u8 m_cass_data[4];
	std::unique_ptr<u8[]> m_vram;
	std::unique_ptr<u8[]> m_eram;
};

// write to videoram if following 'out b9,61' otherwise write to the unknown 'extra' ram
void argo_state::argo_videoram_w(offs_t offset, u8 data)
{
	if (m_ram_ctrl)
		m_vram[offset] = data;
	else
		m_eram[offset] = data;
}

u8 argo_state::argo_io_r(offs_t offset)
{
	u8 low_io = offset;

	switch (low_io)
	{
	case 0xA1: // keyboard
		offset >>= 8;
		if (offset < 11)
			return m_io_keyboard[offset]->read();
		else
			return 0xff;

	case 0xA0:
	case 0xA2:
	case 0xA4:
	case 0xA6:
		offset >>= 1;
		return m_pit->read(offset&3);

	case 0xC0:
	case 0xC4:
		offset >>= 2;
		return m_crtc->read(offset&1);

	case 0xE8: // wants bit 4 low then high
		{
			u8 data = m_dma->read(8);
			data |= (m_framecnt << 4);  // hack because dma update_flag is not emulated
			return data;
		}

	default:
		logerror("%s: In %X\n",machine().describe_context(),low_io);
		return 0xff;
	}
}

void argo_state::argo_io_w(offs_t offset, u8 data)
{
	switch (offset)
	{
	case 0xA0:
	case 0xA2:
	case 0xA4:
	case 0xA6:
		offset >>= 1;
		m_pit->write(offset&3, data);
		break;

	case 0xA1: // prep scroll step 1
		m_scroll_ctrl = (data == 0x61);
		break;

	case 0xA9: // prep scroll step 2
		if ((m_scroll_ctrl == 1) && (data == 0x61))
			m_scroll_ctrl++;
		break;

	case 0xB9: // switch between videoram and extraram
		m_ram_ctrl = (data == 0x61);
		break;

	case 0xC0:
	case 0xC4:
		offset >>= 2;
		m_crtc->write(offset&1, data);
		break;

	case 0xE8: // hardware scroll
		if ((m_scroll_ctrl == 2) & (data == 0xe3))
		{
			memmove(m_vram.get(), m_vram.get()+80, 24*80);
			m_scroll_ctrl = 0;
		}
		m_dma->write(8, data);
		break;

	default:
		logerror("%s: Out %X,%X\n",machine().describe_context(),offset,data);
	}
}

TIMER_DEVICE_CALLBACK_MEMBER( argo_state::kansas_r )
{
	if (m_rts)
	{
		m_cass_data[1] = m_cass_data[2] = m_cass_data[3] = 0;
		m_casspol = 1;
		return;
	}

	m_cass_data[1]++;
	m_cass_data[2]++;

	u8 cass_ws = (m_cass->input() > +0.04) ? 1 : 0;

	if (cass_ws != m_cass_data[0])
	{
		m_cass_data[0] = cass_ws;
		if (m_cass_data[1] > 13)
			m_casspol ^= 1;
		m_cass_data[1] = 0;
		m_cass_data[2] = 0;
		m_uart->write_rxd(m_casspol);
	}
	if ((m_cass_data[2] & 7)==2)
	{
		m_cass_data[3]++;
		m_uart->write_rxc(BIT(m_cass_data[3], 0));
	}
}

WRITE_LINE_MEMBER(argo_state::z0_w)
{
	// write - incoming 2400Hz
	m_uart->write_txc(state);
	if (!m_txe)
	{
		m_cass->output((m_txd ^ state) ? -1.0 : 1.0);
	}

	// read - incoming 2514Hz
}

u8 argo_state::dma_r(offs_t offset)
{
	if (offset < 0xf800)
		return m_maincpu->space(AS_PROGRAM).read_byte(offset);
	else
		return m_vram[offset & 0x7ff];
}

WRITE_LINE_MEMBER( argo_state::hrq_w )
{
	m_maincpu->set_input_line(INPUT_LINE_HALT, state);
	m_dma->hlda_w(state);
}

I8275_DRAW_CHARACTER_MEMBER(argo_state::display_pixels)
{
	if ((x == 0) && (y == 0))
		m_framecnt++;

	const rgb_t *palette = m_palette->palette()->entry_list_raw();
	u8 gfx = m_p_chargen[(linecount & 15) | (charcode << 4)];

	if (vsp)
		gfx = 0;

	if (lten)
	{
		gfx = 0xff;
		if (x > 6)
			x-=6; // hack to fix cursor position
	}

	if (rvv)
		gfx ^= 0xff;

	for(u8 i=0;i<7;i++)
		bitmap.pix32(y, x + i) = palette[BIT(gfx, 6-i) ? (hlgt ? 2 : 1) : 0];
}

static constexpr rgb_t argo_pens[3] =
{
	{ 0x00, 0x00, 0x00 }, // black
	{ 0xa0, 0xa0, 0xa0 }, // white
	{ 0xff, 0xff, 0xff }  // highlight
};

void argo_state::argo_palette(palette_device &palette) const
{
	palette.set_pen_colors(0, argo_pens);
}


/* F4 Character Displayer */
static const gfx_layout charlayout =
{
	8, 9,                   /* 8 x 9 characters */
	512,                    /* 512 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 0, 1, 2, 3, 4, 5, 6, 7 },
	/* y offsets */
	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8 },
	8*16                    /* every char takes 16 bytes */
};

static GFXDECODE_START( gfx_argo )
	GFXDECODE_ENTRY( "chargen", 0x0000, charlayout, 0, 1 )
GFXDECODE_END

void argo_state::mem_map(address_map &map)
{
	map.unmap_value_high();
	map(0x0000, 0xf7ff).ram().share("mainram");
	map(0xf800, 0xffff).rom().region("maincpu", 0).w(FUNC(argo_state::argo_videoram_w));
}

void argo_state::io_map(address_map &map)
{
	map(0x0000, 0xFFFF).r(FUNC(argo_state::argo_io_r));
	map(0x0000, 0x00ff).mirror(0xff00).w(FUNC(argo_state::argo_io_w));
	map(0x00c1, 0x00c1).mirror(0xff00).rw(m_uart, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w));
	map(0x00c3, 0x00c3).mirror(0xff00).rw(m_uart, FUNC(i8251_device::status_r), FUNC(i8251_device::control_w));
	map(0x00e0, 0x00e7).mirror(0xff00).rw(m_dma, FUNC(i8257_device::read), FUNC(i8257_device::write));
}

/* Input ports */
static INPUT_PORTS_START( argo ) // Keyboard was worked out by trial & error;'F' keys produce symbols
	PORT_START("X0")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-")           PORT_CODE(KEYCODE_MINUS_PAD)  PORT_CHAR('-')
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) // J
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // nothing
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // nothing
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LShift")      PORT_CODE(KEYCODE_LSHIFT)
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7")           PORT_CODE(KEYCODE_7_PAD)      PORT_CHAR('7')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8")           PORT_CODE(KEYCODE_8_PAD)      PORT_CHAR('8')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9")           PORT_CODE(KEYCODE_9_PAD)      PORT_CHAR('9')
	PORT_START("X1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc")         PORT_CODE(KEYCODE_ESC)        PORT_CHAR(27)
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab")         PORT_CODE(KEYCODE_TAB)        PORT_CHAR(9)
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl")        PORT_CODE(KEYCODE_LCONTROL)   PORT_CODE(KEYCODE_RCONTROL)
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RShift")      PORT_CODE(KEYCODE_RSHIFT)
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("??")          PORT_CODE(KEYCODE_F2)
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0")           PORT_CODE(KEYCODE_0_PAD)      PORT_CHAR('0')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".")           PORT_CODE(KEYCODE_DEL_PAD)    PORT_CHAR('.')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("+")           PORT_CODE(KEYCODE_PLUS_PAD)   PORT_CHAR('+')
	PORT_START("X2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1")           PORT_CODE(KEYCODE_1)          PORT_CHAR('1')
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q")           PORT_CODE(KEYCODE_Q)          PORT_CHAR('Q')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A")           PORT_CODE(KEYCODE_A)          PORT_CHAR('A')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z")           PORT_CODE(KEYCODE_Z)          PORT_CHAR('Z')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("??")          PORT_CODE(KEYCODE_F12)
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1")           PORT_CODE(KEYCODE_1_PAD)      PORT_CHAR('1')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2")           PORT_CODE(KEYCODE_2_PAD)      PORT_CHAR('2')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3")           PORT_CODE(KEYCODE_3_PAD)      PORT_CHAR('3')
	PORT_START("X3")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) // A
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2")           PORT_CODE(KEYCODE_2)          PORT_CHAR('2')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W")           PORT_CODE(KEYCODE_W)          PORT_CHAR('W')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S")           PORT_CODE(KEYCODE_S)          PORT_CHAR('S')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X")           PORT_CODE(KEYCODE_X)          PORT_CHAR('X')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4")           PORT_CODE(KEYCODE_4_PAD)      PORT_CHAR('4')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5")           PORT_CODE(KEYCODE_5_PAD)      PORT_CHAR('5')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6")           PORT_CODE(KEYCODE_6_PAD)      PORT_CHAR('6')
	PORT_START("X4")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) // B
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3")           PORT_CODE(KEYCODE_3)          PORT_CHAR('3')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E")           PORT_CODE(KEYCODE_E)          PORT_CHAR('E')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D")           PORT_CODE(KEYCODE_D)          PORT_CHAR('M')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C")           PORT_CODE(KEYCODE_C)          PORT_CHAR('C')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) // K
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) // H
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) // I
	PORT_START("X5")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) // C
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4")           PORT_CODE(KEYCODE_4)          PORT_CHAR('4')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R")           PORT_CODE(KEYCODE_R)          PORT_CHAR('R')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F")           PORT_CODE(KEYCODE_F)          PORT_CHAR('F')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V")           PORT_CODE(KEYCODE_V)          PORT_CHAR('V')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BS")          PORT_CODE(KEYCODE_BACKSPACE)  PORT_CHAR(8)
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) // G
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) // F
	PORT_START("X6")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5")           PORT_CODE(KEYCODE_5)          PORT_CHAR('5')
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T")           PORT_CODE(KEYCODE_T)          PORT_CHAR('T')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G")           PORT_CODE(KEYCODE_G)          PORT_CHAR('G')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B")           PORT_CODE(KEYCODE_B)          PORT_CHAR('B')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space")       PORT_CODE(KEYCODE_SPACE)      PORT_CHAR(' ')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT)
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter")       PORT_CODE(KEYCODE_ENTER)      PORT_CHAR(13)
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("*")           PORT_CODE(KEYCODE_ASTERISK)   PORT_CHAR('*')
	PORT_START("X7")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) // D
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6")           PORT_CODE(KEYCODE_6)          PORT_CHAR('6')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y")           PORT_CODE(KEYCODE_Y)          PORT_CHAR('Y')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H")           PORT_CODE(KEYCODE_H)          PORT_CHAR('H')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N")           PORT_CODE(KEYCODE_N)          PORT_CHAR('N')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN)
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP)
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\")          PORT_CODE(KEYCODE_BACKSLASH)  PORT_CHAR('\\')
	PORT_START("X8")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) // E
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7")           PORT_CODE(KEYCODE_7)          PORT_CHAR('7')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U")           PORT_CODE(KEYCODE_U)          PORT_CHAR('U')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J")           PORT_CODE(KEYCODE_J)          PORT_CHAR('J')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M")           PORT_CODE(KEYCODE_M)          PORT_CHAR('M')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("`")           PORT_CODE(KEYCODE_TILDE)      PORT_CHAR('`')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]")           PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=")           PORT_CODE(KEYCODE_EQUALS)     PORT_CHAR('=')
	PORT_START("X9")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8")           PORT_CODE(KEYCODE_8)          PORT_CHAR('8')
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I")           PORT_CODE(KEYCODE_I)          PORT_CHAR('I')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K")           PORT_CODE(KEYCODE_K)          PORT_CHAR('K')
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",")           PORT_CODE(KEYCODE_COMMA)      PORT_CHAR(',')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT)
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\'")          PORT_CODE(KEYCODE_QUOTE)      PORT_CHAR('\'')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[")           PORT_CODE(KEYCODE_OPENBRACE)  PORT_CHAR('[')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-")           PORT_CODE(KEYCODE_MINUS)      PORT_CHAR('-')
	PORT_START("X10")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9")           PORT_CODE(KEYCODE_9)          PORT_CHAR('9')
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O")           PORT_CODE(KEYCODE_O)          PORT_CHAR('O')
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L")           PORT_CODE(KEYCODE_L)          PORT_CHAR('L') // if L is the first character, computer hangs
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".")           PORT_CODE(KEYCODE_STOP)       PORT_CHAR('.') PORT_CHAR('>')
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/")           PORT_CODE(KEYCODE_SLASH)      PORT_CHAR('/')
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";")           PORT_CODE(KEYCODE_COLON)      PORT_CHAR(';')
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P")           PORT_CODE(KEYCODE_P)          PORT_CHAR('P')
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0")           PORT_CODE(KEYCODE_0)          PORT_CHAR('0')
INPUT_PORTS_END



void argo_state::machine_reset()
{
	address_space &program = m_maincpu->space(AS_PROGRAM);
	program.install_rom(0x0000, 0x07ff, m_rom);   // do it here for F3
	m_rom_shadow_tap = program.install_read_tap(0xf800, 0xffff, "rom_shadow_r",[this](offs_t offset, u8 &data, u8 mem_mask)
	{
		if (!machine().side_effects_disabled())
		{
			// delete this tap
			m_rom_shadow_tap->remove();

			// reinstall ram over the rom shadow
			m_maincpu->space(AS_PROGRAM).install_ram(0x0000, 0x07ff, m_ram);
		}

		// return the original data
		return data;
	});
}

void argo_state::machine_start()
{
	m_vram = make_unique_clear<u8[]>(0x0800);
	m_eram = make_unique_clear<u8[]>(0x0800);
	save_pointer(NAME(m_vram), 0x0800);
	save_pointer(NAME(m_eram), 0x0800);
	save_item(NAME(m_framecnt));
	save_item(NAME(m_ram_ctrl));
	save_item(NAME(m_scroll_ctrl));
	save_item(NAME(m_txe));
	save_item(NAME(m_txd));
	save_item(NAME(m_rts));
	save_item(NAME(m_casspol));
	save_item(NAME(m_cass_data));
}


void argo_state::argo(machine_config &config)
{
	/* basic machine hardware */
	Z80(config, m_maincpu, 3500000); // unknown frequency
	m_maincpu->set_addrmap(AS_PROGRAM, &argo_state::mem_map);
	m_maincpu->set_addrmap(AS_IO, &argo_state::io_map);

	/* video hardware */
	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
	screen.set_refresh_hz(50);
	screen.set_size(640, 200);
	screen.set_visarea_full();
	screen.set_screen_update("crtc", FUNC(i8275_device::screen_update));
	GFXDECODE(config, "gfxdecode", m_palette, gfx_argo);
	PALETTE(config, m_palette, FUNC(argo_state::argo_palette), 3);

	/* sound hardware */
	SPEAKER(config, "mono").front_center();
	//SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.50);

	CASSETTE(config, m_cass);
	m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
	m_cass->add_route(ALL_OUTPUTS, "mono", 0.15);
	TIMER(config, "kansas_r").configure_periodic(FUNC(argo_state::kansas_r), attotime::from_hz(38400));

	/* Devices */
	I8251(config, m_uart, 0);
	m_uart->txd_handler().set([this] (bool state) { m_txd = state; });
	m_uart->txempty_handler().set([this] (bool state) { m_txe = state; });
	m_uart->rts_handler().set([this] (bool state) { m_rts = state; });

	PIT8253(config, m_pit, 0);
	m_pit->set_clk<0>(1689600); // this gives the 2400Hz required by the cassette
	m_pit->out_handler<0>().set(FUNC(argo_state::z0_w));
	m_pit->set_clk<1>(0);
	m_pit->set_clk<2>(0);

	I8257(config, m_dma, XTAL(20'000'000) / 9);  // unknown frequency
	m_dma->out_hrq_cb().set(FUNC(argo_state::hrq_w));
	m_dma->in_memr_cb().set(FUNC(argo_state::dma_r));
	m_dma->out_iow_cb<2>().set("crtc", FUNC(i8275_device::dack_w));

	i8275_device &crtc(I8275(config, "crtc", XTAL(20'000'000) / 12));  // unknown frequency
	crtc.set_character_width(6);
	crtc.set_display_callback(FUNC(argo_state::display_pixels));
	crtc.drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq2_w));
	crtc.set_screen("screen");
}

/* ROM definition */
ROM_START( argo )
	ROM_REGION( 0x0800, "maincpu", 0 )
	ROM_LOAD( "argo.rom", 0x0000, 0x0800, CRC(4c4c045b) SHA1(be2b97728cc190d4a8bd27262ba9423f252d31a3) )

	/* character generator not dumped, using the one from 'c10' for now */
	ROM_REGION( 0x2000, "chargen", 0 )
	ROM_LOAD( "c10_char.bin", 0x0000, 0x2000, BAD_DUMP CRC(cb530b6f) SHA1(95590bbb433db9c4317f535723b29516b9b9fcbf))
ROM_END

/* Driver */

/*    YEAR  NAME  PARENT  COMPAT  MACHINE  INPUT  CLASS       INIT         COMPANY      FULLNAME  FLAGS */
COMP( 1986, argo, unior,  0,      argo,    argo,  argo_state, empty_init, "<unknown>", "Argo",   MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )