summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/zx8301.cpp
blob: a23679a1b974b34fef2fd8c76564a088f6b011d7 (plain) (tree)
1
2
3
4
5
6

                               



                                                                       











                                                                       
                

                   
                   












                                                                            
                                     
 







                                           


  





                                                                            
                                                                      


                      

                                            

                                            
 
 
 




                                                   
                                                                                       
 
                                    

                                                  


 








                                                                            
                                                      
 
                                          






                                                   
                                                                  
 
                                          











                                                                            
                                                                                                             
                                                      

                                                 
                                                                                                                             







                                              









                                                   
                            
                                     




























                                                                                            
                                       
















                                                   
                               
 







                                        
 
          























                                                             
                                                                        















                                                                           
                                                                        









                                                   
                                                                             




                                             

                                                   






                                                       
                                                                                         











                                                   
                                                                             


                  


                                  

                                             

                                                   









                                                                     




                                                    

                                             

                                                             

                         

                                                                     








                                                   
                   

                                                   
                                                                                                             


                       
                                           
















                                                               
                                                      
         

                 
 
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************

    Sinclair ZX8301 emulation

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

/*

    TODO:

    - wait state on memory access during video update
    - proper video timing
    - get rid of flash timer

*/

#include "emu.h"
#include "zx8301.h"

#include "screen.h"


//**************************************************************************
//  MACROS / CONSTANTS
//**************************************************************************

#define LOG 0


// low resolution palette
static const int ZX8301_COLOR_MODE4[] = { 0, 2, 4, 7 };


static const rgb_t PALETTE_ZX8301[] =
{
	rgb_t(0x00, 0x00, 0x00), // black
	rgb_t(0x00, 0x00, 0xff), // blue
	rgb_t(0xff, 0x00, 0x00), // red
	rgb_t(0xff, 0x00, 0xff), // magenta
	rgb_t(0x00, 0xff, 0x00), // green
	rgb_t(0x00, 0xff, 0xff), // cyan
	rgb_t(0xff, 0xff, 0x00), // yellow
	rgb_t(0xff, 0xff, 0xff) // white
};



//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

// devices
DEFINE_DEVICE_TYPE(ZX8301, zx8301_device, "zx8301", "Sinclair ZX8301")


// default address map
void zx8301_device::zx8301(address_map &map)
{
	if (!has_configured_map(0))
		map(0x00000, 0x1ffff).ram();
}


//-------------------------------------------------
//  memory_space_config - return a description of
//  any address spaces owned by this device
//-------------------------------------------------

device_memory_interface::space_config_vector zx8301_device::memory_space_config() const
{
	return space_config_vector {
		std::make_pair(0, &m_space_config)
	};
}



//**************************************************************************
//  INLINE HELPERS
//**************************************************************************

//-------------------------------------------------
//  readbyte - read a byte at the given address
//-------------------------------------------------

inline uint8_t zx8301_device::readbyte(offs_t address)
{
	return space().read_byte(address);
}


//-------------------------------------------------
//  writebyte - write a byte at the given address
//-------------------------------------------------

inline void zx8301_device::writebyte(offs_t address, uint8_t data)
{
	space().write_byte(address, data);
}



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

//-------------------------------------------------
//  zx8301_device - constructor
//-------------------------------------------------

zx8301_device::zx8301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, ZX8301, tag, owner, clock)
	, device_memory_interface(mconfig, *this)
	, device_video_interface(mconfig, *this)
	, m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, address_map_constructor(FUNC(zx8301_device::zx8301), this))
	, m_cpu(*this, finder_base::DUMMY_TAG)
	, m_write_vsync(*this)
	, m_dispoff(1)
	, m_mode8(0)
	, m_base(0)
	, m_flash(1)
	, m_vsync(1)
	, m_vda(0)
{
}


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

void zx8301_device::device_start()
{
	// resolve callbacks
	m_write_vsync.resolve_safe();

	// allocate timers
	m_vsync_timer = timer_alloc(TIMER_VSYNC);
	m_flash_timer = timer_alloc(TIMER_FLASH);

	// adjust timer periods
	m_vsync_timer->adjust(attotime::zero, 0, attotime::from_hz(50));
	m_flash_timer->adjust(attotime::from_hz(2), 0, attotime::from_hz(2));

	// register for state saving
	save_item(NAME(m_dispoff));
	save_item(NAME(m_mode8));
	save_item(NAME(m_base));
	save_item(NAME(m_flash));
	save_item(NAME(m_vsync));
	save_item(NAME(m_vda));
}


//-------------------------------------------------
//  device_timer - handler timer events
//-------------------------------------------------

void zx8301_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id)
	{
	case TIMER_VSYNC:
		//m_vsync = !m_vsync;
		m_write_vsync(m_vsync);
		break;

	case TIMER_FLASH:
		m_flash = !m_flash;
		break;
	}
}


//-------------------------------------------------
//  control_w - display control register
//-------------------------------------------------

WRITE8_MEMBER( zx8301_device::control_w )
{
	/*

	    bit     description

	    0
	    1       display off
	    2
	    3       graphics mode
	    4
	    5
	    6
	    7       display base address

	*/

	if (LOG) logerror("ZX8301 Control: %02x\n", data);

	// display off
	m_dispoff = BIT(data, 1);

	// graphics mode
	m_mode8 = BIT(data, 3);

	// display base address
	m_base = BIT(data, 7);
}


//-------------------------------------------------
//  data_r - RAM read
//-------------------------------------------------

READ8_MEMBER( zx8301_device::data_r )
{
	if (LOG) logerror("ZX8301 RAM Read: %06x\n", offset);

	if (m_vda)
	{
		m_cpu->spin_until_time(screen().time_until_pos(256, 0));
	}

	return readbyte(offset);
}


//-------------------------------------------------
//  data_w - RAM write
//-------------------------------------------------

WRITE8_MEMBER( zx8301_device::data_w )
{
	if (LOG) logerror("ZX8301 RAM Write: %06x = %02x\n", offset, data);

	if (m_vda)
	{
		m_cpu->spin_until_time(screen().time_until_pos(256, 0));
	}

	writebyte(offset, data);
}


//-------------------------------------------------
//  draw_line_mode4 - draw mode 4 line
//-------------------------------------------------

void zx8301_device::draw_line_mode4(bitmap_rgb32 &bitmap, int y, uint16_t da)
{
	int x = 0;

	for (int word = 0; word < 64; word++)
	{
		uint8_t byte_high = readbyte(da++);
		uint8_t byte_low = readbyte(da++);

		for (int pixel = 0; pixel < 8; pixel++)
		{
			int red = BIT(byte_low, 7);
			int green = BIT(byte_high, 7);
			int color = (green << 1) | red;

			bitmap.pix32(y, x++) = PALETTE_ZX8301[ZX8301_COLOR_MODE4[color]];

			byte_high <<= 1;
			byte_low <<= 1;
		}
	}
}


//-------------------------------------------------
//  draw_line_mode8 - draw mode 8 line
//-------------------------------------------------

void zx8301_device::draw_line_mode8(bitmap_rgb32 &bitmap, int y, uint16_t da)
{
	int x = 0;

	bool flash_active = false;
	int flash_color = 0;

	for (int word = 0; word < 64; word++)
	{
		uint8_t byte_high = readbyte(da++);
		uint8_t byte_low = readbyte(da++);

		for (int pixel = 0; pixel < 4; pixel++)
		{
			int red = BIT(byte_low, 7);
			int green = BIT(byte_high, 7);
			int blue = BIT(byte_low, 6);
			int flash = BIT(byte_high, 6);

			int color = (green << 2) | (red << 1) | blue;

			if (flash_active)
			{
				color = flash_color;
			}

			if (flash && m_flash)
			{
				flash_active = !flash_active;
				flash_color = color;
			}

			bitmap.pix32(y, x++) = PALETTE_ZX8301[color];
			bitmap.pix32(y, x++) = PALETTE_ZX8301[color];

			byte_high <<= 2;
			byte_low <<= 2;
		}
	}
}


//-------------------------------------------------
//  screen_update -
//-------------------------------------------------

uint32_t zx8301_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	if (!m_dispoff)
	{
		uint32_t da = m_base << 15;

		for (int y = 0; y < 256; y++)
		{
			if (m_mode8)
			{
				draw_line_mode8(bitmap, y, da);
			}
			else
			{
				draw_line_mode4(bitmap, y, da);
			}

			da += 128;
		}
	}
	else
	{
		bitmap.fill(rgb_t::black(), cliprect);
	}

	return 0;
}