// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************

    Microtanic Video 80/82 Board

    http://www.microtan.ukpc.net/pageProducts.html#VIDEO

    TODO:
    - implement the communication between the 8212's

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


#include "emu.h"
#include "tug8082.h"


//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(TANBUS_TUG8082, tanbus_tug8082_device, "tanbus_vid8082", "Microtanic Video 80/82 Board")

//-------------------------------------------------
//  ADDRESS_MAP( vid8082_map )
//-------------------------------------------------

void tanbus_tug8082_device::vid8082_map(address_map &map)
{
	map(0x0000, 0x07ff).ram();
	map(0x4000, 0x7fff).ram().share(m_videoram);
	map(0x8000, 0x8000).w(m_iop[0], FUNC(i8212_device::write));
	map(0x8001, 0x8001).r(m_iop[1], FUNC(i8212_device::read));
	map(0xe000, 0xffff).rom().region("rom", 0);
}

//-------------------------------------------------
//  ROM( tug8082 )
//-------------------------------------------------

ROM_START(tug8082)
	ROM_REGION(0x2000, "rom", 0)
	ROM_LOAD("vdu80.ic28", 0x0000, 0x2000, CRC(e9df89c3) SHA1(1db8b055306067eb62940c0e9e63d97a2fab20f9))
ROM_END

//-------------------------------------------------
//  INPUT_PORTS( tug8082 )
//-------------------------------------------------

INPUT_PORTS_START(tug8082)
	PORT_START("DSW0")
	PORT_DIPNAME(0x01, 0x01, "VDU Interrupt Request") PORT_DIPLOCATION("DSWA:1")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x01, DEF_STR(On))
	PORT_DIPNAME(0x02, 0x00, "VDU Non Maskable Interrupt") PORT_DIPLOCATION("DSWA:2")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x02, DEF_STR(On))
	PORT_DIPNAME(0x04, 0x00, "Not used") PORT_DIPLOCATION("DSWA:3")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x04, DEF_STR(On))
	PORT_DIPNAME(0x08, 0x00, "Not used") PORT_DIPLOCATION("DSWA:4")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x08, DEF_STR(On))
	PORT_DIPNAME(0xf0, 0x00, "I/O Address") PORT_DIPLOCATION("DSWA:5,6,7,8")
	PORT_DIPSETTING(0x60, "$BE60 - $BE61")
	PORT_DIPSETTING(0x40, "$BE40 - $BE41")
	PORT_DIPSETTING(0x20, "$BE20 - $BE21")
	PORT_DIPSETTING(0x00, "$BE00 - $BE01")

	PORT_START("DSW1")
	PORT_DIPNAME(0x01, 0x00, "Not used") PORT_DIPLOCATION("DSWB:1")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x01, DEF_STR(On))
	PORT_DIPNAME(0x02, 0x00, "Not used") PORT_DIPLOCATION("DSWB:2")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x02, DEF_STR(On))
	PORT_DIPNAME(0x04, 0x04, "80 Column Mode 16K Ram") PORT_DIPLOCATION("DSWB:3")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x04, DEF_STR(On))
	PORT_DIPNAME(0x08, 0x00, "Not used") PORT_DIPLOCATION("DSWB:4")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x08, DEF_STR(On))
	PORT_DIPNAME(0x10, 0x00, "Not used") PORT_DIPLOCATION("DSWB:5")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x10, DEF_STR(On))
	PORT_DIPNAME(0x20, 0x20, "Write Protect") PORT_DIPLOCATION("DSWB:6")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x20, DEF_STR(On))
	PORT_DIPNAME(0x40, 0x00, "40 Column Mode 8K Ram") PORT_DIPLOCATION("DSWB:7")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x40, DEF_STR(On))
	PORT_DIPNAME(0x80, 0x80, "Video Select Disable") PORT_DIPLOCATION("DSWB:8")
	PORT_DIPSETTING(0x00, DEF_STR(Off))
	PORT_DIPSETTING(0x80, DEF_STR(On))
INPUT_PORTS_END

//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor tanbus_tug8082_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(tug8082);
}

//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------

void tanbus_tug8082_device::device_add_mconfig(machine_config &config)
{
	M6502(config, m_maincpu, DERIVED_CLOCK(1, 4));
	m_maincpu->set_addrmap(AS_PROGRAM, &tanbus_tug8082_device::vid8082_map);

	I8212(config, m_iop[0], 0);
	//m_iop[0]->md_rd_callback().set(CONSTANT(0));
	m_iop[0]->int_wr_callback().set(FUNC(tanbus_tug8082_device::bus_irq_w));
	//m_iop->do_wr_callback().set(FUNC(tanbus_tug8082_device::write));

	I8212(config, m_iop[1], 0);
	//m_iop[1]->md_rd_callback().set(CONSTANT(0));
	m_iop[1]->int_wr_callback().set(FUNC(tanbus_tug8082_device::vdu_irq_w));
	//m_iop->di_rd_callback().set(FUNC(tanbus_tug8082_device::read));

	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
	m_screen->set_refresh_hz(50);
	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
	m_screen->set_size(512, 256);
	m_screen->set_visarea(0, 512 - 1, 0, 256 - 1);
	m_screen->set_screen_update(FUNC(tanbus_tug8082_device::screen_update));

	PALETTE(config, "palette", palette_device::MONOCHROME);
}

//-------------------------------------------------
//  rom_region - device-specific ROM region
//-------------------------------------------------

const tiny_rom_entry *tanbus_tug8082_device::device_rom_region() const
{
	return ROM_NAME(tug8082);
}

//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  tanbus_tug8082_device - constructor
//-------------------------------------------------

tanbus_tug8082_device::tanbus_tug8082_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, TANBUS_TUG8082, tag, owner, clock)
	, device_tanbus_interface(mconfig, *this)
	, m_maincpu(*this, "maincpu")
	, m_iop(*this, "iop%u", 0)
	, m_dips(*this, "DSW%u", 0)
	, m_rom(*this, "rom")
	, m_screen(*this, "screen")
	, m_palette(*this, "palette")
	, m_videoram(*this, "videoram")
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void tanbus_tug8082_device::device_start()
{
}

//-------------------------------------------------
//  read - card read
//-------------------------------------------------

uint8_t tanbus_tug8082_device::read(offs_t offset, int inhrom, int inhram, int be)
{
	uint8_t data = 0xff;

	offs_t addr = 0xbe00 | (m_dips[0]->read() & 0xf0);

	if (offset == addr)
	{
			data = m_iop[0]->read();
	}

	return data;
}

//-------------------------------------------------
//  write - card write
//-------------------------------------------------

void tanbus_tug8082_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
	offs_t addr = 0xbe01 | (m_dips[0]->read() & 0xf0);

	if (offset == addr)
	{
		m_iop[1]->write(data);
	}
}

//**************************************************************************
//  IMPLEMENTATION
//**************************************************************************

WRITE_LINE_MEMBER(tanbus_tug8082_device::bus_irq_w)
{
	/* Manual says these DIPs are not used but schematic suggests they are */
	//switch (m_dips[0]->read() >> 2)
	//{
	//case 0x01:
		m_tanbus->irq_w(state);
	//  break;
	//case 0x02:
	//  m_tanbus->nmi_w(state);
	//  break;
	//}
}

WRITE_LINE_MEMBER(tanbus_tug8082_device::vdu_irq_w)
{
	switch (m_dips[0]->read() & 0x03)
	{
	case 0x01:
		m_maincpu->set_input_line(M6502_IRQ_LINE, state);
		break;
	case 0x02:
		m_maincpu->set_input_line(M6502_NMI_LINE, state);
		break;
	case 0x03:
		m_maincpu->set_input_line(M6502_IRQ_LINE, state);
		m_maincpu->set_input_line(M6502_NMI_LINE, state);
		break;
	}
}

uint32_t tanbus_tug8082_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	pen_t const *const pen = m_palette->pens();

	for (int y = 0; y < 256; y++)
	{
		uint32_t *scanline = &bitmap.pix(y);
		for (int x = 0; x < 64; x++)
		{
			uint8_t const pixels = m_videoram[(y * 64) + x];

			for (int i = 0; i < 8; ++i)
				*scanline++ = pen[BIT(pixels, 7 - i)];
		}
	}

	return 0;
}
