summaryrefslogblamecommitdiffstatshomepage
path: root/src/mess/video/abc1600.c
blob: 2a312cb3ae7e0c2d9f51554ddbde5b61a84507d3 (plain) (tree)
1
2
3
4
5
6
7
8

                               



                                                                       

                                                                       











                                                                            


                                     
            


                                   


                







                                  

 


















































                                                                                                                


                                                                                                                               



                                                                                                                     


                                                                                                                           










                                                                                                                                                       
 




                                                   
          























                                                                                
 



                                        
 


                                                                    
                                                        
 
                  
                                             
 


                                                           
 



                                                                                       
 

                                                          
                                                                                        
 
                                                                              
 





                                           



                                                                  













                                                                          

                                                    



                                                                        
                                                                      













                                                                                 

                                                                            
               


                                                                            


                                                   








                                                                                                                           





























































                                                                                                      


                                                   
                                                                
 
                                                                  






                                                   
                                                                                         
 
                                                
 
                                                                                                          






                                                   
                                                 
 
                                                     



                          
                                                  


            
                                                









                                                   
                                                  
 
                                                     

















                                                                                  
                                                                                                    

















                                                                                  
                                                                                                    







                                                   
                                             


          
                               
 







                             
 
          













                                                               
               

                                                   
                                                
 
          
 
                               
 







                          
 
          
 
                                                                                    
 



                                                          
 
 


                                                   
 


                                                
 
                               
 







                          
 
          
 
                                                                                    
 

                                           
 
 


                                                   
 


                                                
 
                               
 







                           
 
          
 
                                                                                    
 

                                                          
 
 


                                                   
 


                                                
 
                               
 







                          
 
          
 
                                                                                    
 

                                           
 
 


                                                   
 


                                                
 
                               
 







                              
 
          
 
                                                                                    
 


                                                         
 
 


                                                   
 


                                                
 
                               
 







                              
 
          
 
                                                                                    
 


                                                
 
 






















                                                                                    

                        


                                                         



                                                   
               

                                                   
                                                
 
















                                                                                    

                        








                                                   
 


                                                
 
                               
 







                                
 
          
 
                                                                                    
 


                                                          
 
 


                                                   
 


                                                
 
                               
 







                                
 
          
 
                                                                                    
 


                                                
 
 


                                                   
 


                                                
 
                               
 







                         
 
          
 
                                                                                    
 

                                                         
 
 


                                                   
 


                                                
 
                               
 







                         
 
          
 
                                                                                    
 
                                                
 

                
 
 


                                                   
 


                                             
 
                               
 















                                                                        




                                                   
            

                                                   
                                             
 
          
 











                                                                 
 






                                                                        
 
 


                                                   
 














                                                            
 
 


                                                   
 












                                                            



         















































                                                      








                                                                            
                                               

















                                                   
                                               

















                                                   
                                               














                                                   
                                               














                                                   
                                              











                                                   
                                              











                                                   
                                               














                                                   
                                                 
















                                                          
                                                 














                                                   
                                             


          
                               
 








                          
 
          

                                                                                    
                                              









                                                   
                                               


          
                               
 




                          
 
          

                                                         
                                       






                                                   
                                               


          
                               
 











                               
 
          

                                                                                                                                                        
                                                






                                                   
                                                             

















                                                   
                                                          


















                                                                  
                                  






















































                                                                                                                                                                                 
                                                                                                                  
 

                     
                                                                 



                                                                
                                                    



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

    Luxor ABC 1600 Mover emulation

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

#include "includes/abc1600.h"
#include "abc1600.lh"



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

#define LOG 0


#define SY6845E_TAG         "sy6845e"


// video RAM
#define VIDEORAM_SIZE       0x40000
#define VIDEORAM16_MASK     0x3ffff
#define VIDEORAM8_MASK      0x7fffe


// flag register
#define L_P         BIT(m_flag, 0)
#define BLANK       BIT(m_flag, 1)
#define PIX_POL     BIT(m_flag, 2)
#define FRAME_POL   BIT(m_flag, 3)
#define HOLD_FY     BIT(m_flag, 4)
#define HOLD_FX     BIT(m_flag, 5)
#define COMP_MOVE   BIT(m_flag, 6)
#define REPLACE     BIT(m_flag, 7)



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

const device_type ABC1600_MOVER = &device_creator<abc1600_mover_device>;


DEVICE_ADDRESS_MAP_START( vram_map, 8, abc1600_mover_device )
	AM_RANGE(0x00000, 0x7ffff) AM_READWRITE(video_ram_r, video_ram_w)
ADDRESS_MAP_END

DEVICE_ADDRESS_MAP_START( crtc_map, 8, abc1600_mover_device )
	AM_RANGE(0x00, 0x00) AM_MIRROR(0xfe) AM_DEVREADWRITE(SY6845E_TAG, mc6845_device, status_r, address_w)
	AM_RANGE(0x01, 0x01) AM_MIRROR(0xfe) AM_DEVREADWRITE(SY6845E_TAG, mc6845_device, register_r, register_w)
ADDRESS_MAP_END

DEVICE_ADDRESS_MAP_START( io_map, 8, abc1600_mover_device )
	AM_RANGE(0x000, 0x000) AM_MIRROR(0xff) AM_READ(iord0_r)
	AM_RANGE(0x000, 0x000) AM_MIRROR(0xf8) AM_WRITE(ldsx_hb_w)
	AM_RANGE(0x001, 0x001) AM_MIRROR(0xf8) AM_WRITE(ldsx_lb_w)
	AM_RANGE(0x002, 0x002) AM_MIRROR(0xf8) AM_WRITE(ldsy_hb_w)
	AM_RANGE(0x003, 0x003) AM_MIRROR(0xf8) AM_WRITE(ldsy_lb_w)
	AM_RANGE(0x004, 0x004) AM_MIRROR(0xf8) AM_WRITE(ldtx_hb_w)
	AM_RANGE(0x005, 0x005) AM_MIRROR(0xf8) AM_WRITE(ldtx_lb_w)
	AM_RANGE(0x006, 0x006) AM_MIRROR(0xf8) AM_WRITE(ldty_hb_w)
	AM_RANGE(0x007, 0x007) AM_MIRROR(0xf8) AM_WRITE(ldty_lb_w)
	AM_RANGE(0x100, 0x100) AM_MIRROR(0xf8) AM_WRITE(ldfx_hb_w)
	AM_RANGE(0x101, 0x101) AM_MIRROR(0xf8) AM_WRITE(ldfx_lb_w)
	AM_RANGE(0x102, 0x102) AM_MIRROR(0xf8) AM_WRITE(ldfy_hb_w)
	AM_RANGE(0x103, 0x103) AM_MIRROR(0xf8) AM_WRITE(ldfy_lb_w)
	AM_RANGE(0x105, 0x105) AM_MIRROR(0xf8) AM_WRITE(wrml_w)
	AM_RANGE(0x107, 0x107) AM_MIRROR(0xf8) AM_WRITE(wrdl_w)
	AM_RANGE(0x200, 0x200) AM_MIRROR(0xf8) AM_WRITE(wrmask_strobe_hb_w)
	AM_RANGE(0x201, 0x201) AM_MIRROR(0xf8) AM_WRITE(wrmask_strobe_lb_w)
	AM_RANGE(0x202, 0x202) AM_MIRROR(0xf8) AM_WRITE(enable_clocks_w)
	AM_RANGE(0x203, 0x203) AM_MIRROR(0xf8) AM_WRITE(flag_strobe_w)
	AM_RANGE(0x204, 0x204) AM_MIRROR(0xf8) AM_WRITE(endisp_w)
ADDRESS_MAP_END


static ADDRESS_MAP_START( mover_map, AS_0, 16, abc1600_mover_device )
	AM_RANGE(0x00000, 0x7ffff) AM_RAM
ADDRESS_MAP_END


//-------------------------------------------------
//  ROM( abc1600_mover )
//-------------------------------------------------

ROM_START( abc1600_mover )
	ROM_REGION16_BE( 0x2000, "wrmsk", 0 )
	ROM_LOAD16_BYTE( "wrmskl 6490362-01.1g", 0x0001, 0x1000, CRC(bc737538) SHA1(80e2c3757eb7f713018808d6e41ebef612425028) )
	ROM_LOAD16_BYTE( "wrmskh 6490363-01.1j", 0x0000, 0x1000, CRC(6b7c9f0b) SHA1(7155a993adcf08a5a8a2f22becf9fd66fda698be) )

	ROM_REGION( 0x200, "shinf", 0 )
	ROM_LOAD( "shinf 6490361-01.1f", 0x000, 0x200, CRC(20260f8f) SHA1(29bf49c64e7cc7592e88cde2768ac57c7ce5e085) )

	ROM_REGION16_BE( 0x40, "drmsk", 0 )
	ROM_LOAD16_BYTE( "drmskl 6490359-01.1k", 0x01, 0x20, CRC(6e71087c) SHA1(0acf67700d6227f4b315cf8fb0fb31c0e7fb9496) )
	ROM_LOAD16_BYTE( "drmskh 6490358-01.1l", 0x00, 0x20, CRC(a4a9a9dc) SHA1(d8575c0335d6021cbb5f7bcd298b41c35294a80a) )

	ROM_REGION( 0x104, "plds", 0 )
	ROM_LOAD( "drmsk 6490360-01.1m", 0x000, 0x104, CRC(5f7143c1) SHA1(1129917845f8e505998b15288f02bf907487e4ac) ) // mover word mixer @ 1m,1n,1t,2t
ROM_END


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

const rom_entry *abc1600_mover_device::device_rom_region() const
{
	return ROM_NAME( abc1600_mover );
}


//-------------------------------------------------
//  mc6845
//-------------------------------------------------

inline UINT16 abc1600_mover_device::get_crtca(UINT16 ma, UINT8 ra, UINT8 column)
{
	/*

	    bit         description

	    CRTCA0      0
	    CRTCA1      0
	    CRTCA2      CC1/MA1
	    CRTCA3      CC2/MA2
	    CRTCA4      CC3/MA3
	    CRTCA5      CC4/MA4
	    CRTCA6      RA0
	    CRTCA7      RA1
	    CRTCA8      RA2
	    CRTCA9      RA3
	    CRTCA10     CR0/MA8
	    CRTCA11     CR1/MA9
	    CRTCA12     CR2/MA10
	    CRTCA13     CR3/MA11
	    CRTCA14     CR4/MA12
	    CRTCA15     CR5/MA13

	*/

	UINT8 cc = (ma & 0xff) + column;
	UINT8 cr = ma >> 8;

	return (cr << 10) | ((ra & 0x0f) << 6) | ((cc << 1) & 0x3c);
}

MC6845_UPDATE_ROW(abc1600_mover_device::crtc_update_row)
{
	int x = 0;
	const pen_t *pen = m_palette->pens();

	for (int column = 0; column < x_count; column += 2)
	{
		UINT16 dma = get_crtca(ma, ra, column);

		// data is read out of video RAM in nibble mode by strobing CAS 4 times
		for (int cas = 0; cas < 4; cas++)
		{
			UINT16 data = read_videoram(dma + cas);

			for (int bit = 0; bit < 16; bit++)
			{
				int color = ((BIT(data, 15) ^ PIX_POL) && !BLANK) && de;

				bitmap.pix32(vbp + y, hbp + x++) = pen[color];

				data <<= 1;
			}
		}
	}
}

MC6845_ON_UPDATE_ADDR_CHANGED( abc1600_mover_device::crtc_update )
{
}

//-------------------------------------------------
//  MACHINE_CONFIG_FRAGMENT( abc1600_mover )
//-------------------------------------------------

static MACHINE_CONFIG_FRAGMENT( abc1600_mover )
	MCFG_DEFAULT_LAYOUT(layout_abc1600)

	MCFG_SCREEN_ADD(SCREEN_TAG, RASTER)
	MCFG_SCREEN_REFRESH_RATE(60)
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate
	MCFG_SCREEN_UPDATE_DRIVER(abc1600_mover_device, screen_update)
	MCFG_SCREEN_SIZE(958, 1067)
	MCFG_SCREEN_VISIBLE_AREA(0, 958-1, 0, 1067-1)

	MCFG_PALETTE_ADD_MONOCHROME_GREEN("palette")

	MCFG_MC6845_ADD(SY6845E_TAG, SY6845E, SCREEN_TAG, XTAL_64MHz/32)
	MCFG_MC6845_SHOW_BORDER_AREA(true)
	MCFG_MC6845_CHAR_WIDTH(32)
	MCFG_MC6845_UPDATE_ROW_CB(abc1600_mover_device, crtc_update_row)
	MCFG_MC6845_ADDR_CHANGED_CB(abc1600_mover_device, crtc_update)
MACHINE_CONFIG_END


//-------------------------------------------------
//  machine_config_additions - device-specific
//  machine configurations
//-------------------------------------------------

machine_config_constructor abc1600_mover_device::device_mconfig_additions() const
{
	return MACHINE_CONFIG_NAME( abc1600_mover );
}



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

//-------------------------------------------------
//  abc1600_mover_device - constructor
//-------------------------------------------------

abc1600_mover_device::abc1600_mover_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
	device_t(mconfig, ABC1600_MOVER, "ABC 1600 Mover", tag, owner, clock, "abc1600mover", __FILE__),
	device_memory_interface(mconfig, *this),
	m_space_config("vram", ENDIANNESS_BIG, 16, 18, -1, *ADDRESS_MAP_NAME(mover_map)),
	m_crtc(*this, SY6845E_TAG),
	m_palette(*this, "palette"),
	m_wrmsk_rom(*this, "wrmsk"),
	m_shinf_rom(*this, "shinf"),
	m_drmsk_rom(*this, "drmsk")
{
}


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

void abc1600_mover_device::device_start()
{
	// state saving
	save_item(NAME(m_endisp));
	save_item(NAME(m_clocks_disabled));
	save_item(NAME(m_gmdi));
	save_item(NAME(m_wrm));
	save_item(NAME(m_ms));
	save_item(NAME(m_ds));
	save_item(NAME(m_flag));
	save_item(NAME(m_xsize));
	save_item(NAME(m_ysize));
	save_item(NAME(m_udx));
	save_item(NAME(m_udy));
	save_item(NAME(m_xfrom));
	save_item(NAME(m_xto));
	save_item(NAME(m_yto));
	save_item(NAME(m_ty));
	save_item(NAME(m_mfa));
	save_item(NAME(m_mta));
	save_item(NAME(m_sh));
	save_item(NAME(m_mdor));
	save_item(NAME(m_hold_1w_cyk));
	save_item(NAME(m_wrms0));
	save_item(NAME(m_wrms1));
	save_item(NAME(m_rmc));
	save_item(NAME(m_cmc));
}


//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void abc1600_mover_device::device_reset()
{
	// disable display
	m_clocks_disabled = 1;
	m_endisp = 0;
}


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

const address_space_config *abc1600_mover_device::memory_space_config(address_spacenum spacenum) const
{
	return (spacenum == AS_0) ? &m_space_config : NULL;
}


//-------------------------------------------------
//  read_videoram -
//-------------------------------------------------

inline UINT16 abc1600_mover_device::read_videoram(offs_t offset)
{
	return space().read_word((offset & VIDEORAM16_MASK) << 1);
}


//-------------------------------------------------
//  write_videoram -
//-------------------------------------------------

inline void abc1600_mover_device::write_videoram(offs_t offset, UINT16 data, UINT16 mask)
{
	UINT16 old_data = read_videoram(offset);

	space().write_word((offset & VIDEORAM16_MASK) << 1, (data & mask) | (old_data & (mask ^ 0xffff)));
}


//-------------------------------------------------
//  video_ram_r -
//-------------------------------------------------

READ8_MEMBER( abc1600_mover_device::video_ram_r )
{
	offs_t addr = (offset & VIDEORAM8_MASK) >> 1;
	UINT8 data = 0;

	if (offset & 0x01)
	{
		data = read_videoram(addr) & 0xff;
	}
	else
	{
		data = read_videoram(addr) >> 8;
	}

	return data;
}


//-------------------------------------------------
//  video_ram_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::video_ram_w )
{
	offs_t addr = (offset & VIDEORAM8_MASK) >> 1;

	if (offset & 0x01)
	{
		if (REPLACE)
		{
			// WRPORT_LB
			m_wrm = (m_wrm & 0xff00) | data;
			if (LOG) logerror("WRM LB %02x -> %04x\n", data, m_wrm);
		}
		else
		{
			// DATAPORT_LB
			m_gmdi = (m_gmdi & 0xff00) | data;
			if (LOG) logerror("GMDI LB %02x -> %04x\n", data, m_gmdi);
		}

		write_videoram(addr, m_gmdi, m_wrm & 0x00ff);

		if (LOG) logerror("Video RAM write LB to %05x : %04x\n", addr, read_videoram(addr));
	}
	else
	{
		if (REPLACE)
		{
			// WRPORT_HB
			m_wrm = (data << 8) | (m_wrm & 0xff);
			if (LOG) logerror("WRM HB %02x -> %04x\n", data, m_wrm);
		}
		else
		{
			// DATAPORT_HB
			m_gmdi = (data << 8) | (m_gmdi & 0xff);
			if (LOG) logerror("GMDI HB %02x -> %04x\n", data, m_gmdi);
		}

		write_videoram(addr, m_gmdi, m_wrm & 0xff00);

		if (LOG) logerror("Video RAM write HB to %05x : %04x\n", addr, read_videoram(addr));
	}
}


//-------------------------------------------------
//  iord0_r -
//-------------------------------------------------

READ8_MEMBER( abc1600_mover_device::iord0_r )
{
	/*

	    bit     description

	    0       0
	    1       SCREENPOS
	    2
	    3
	    4
	    5
	    6       VSYNC
	    7       BUSY

	*/

	UINT8 data = 0;

	// monitor orientation (portrait/landscape)
	data |= machine().render().first_target()->view() << 1;

	// vertical sync
	data |= m_crtc->vsync_r() << 6;

	return data;
}


//-------------------------------------------------
//  ldsx_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldsx_hb_w )
{
	/*

	    bit     description

	    0       XSIZE8
	    1       XSIZE9
	    2       U/D* Y
	    3       U/D* X
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDSX HB: %02x\n", machine().describe_context(), data);

	m_xsize = ((data & 0x03) << 8) | (m_xsize & 0xff);
	m_udy = BIT(data, 2);
	m_udx = BIT(data, 3);
}


//-------------------------------------------------
//  ldsx_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldsx_lb_w )
{
	/*

	    bit     description

	    0       XSIZE0
	    1       XSIZE1
	    2       XSIZE2
	    3       XSIZE3
	    4       XSIZE4
	    5       XSIZE5
	    6       XSIZE6
	    7       XSIZE7

	*/

	if (LOG) logerror("%s LDSX LB: %02x\n", machine().describe_context(), data);

	m_xsize = (m_xsize & 0x300) | data;
}


//-------------------------------------------------
//  ldsy_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldsy_hb_w )
{
	/*

	    bit     description

	    0       YSIZE8
	    1       YSIZE9
	    2       YSIZE10
	    3       YSIZE11
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDSY HB: %02x\n", machine().describe_context(), data);

	m_ysize = ((data & 0x0f) << 8) | (m_ysize & 0xff);
}


//-------------------------------------------------
//  ldsy_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldsy_lb_w )
{
	/*

	    bit     description

	    0       YSIZE0
	    1       YSIZE1
	    2       YSIZE2
	    3       YSIZE3
	    4       YSIZE4
	    5       YSIZE5
	    6       YSIZE6
	    7       YSIZE7

	*/

	if (LOG) logerror("%s LDSY LB: %02x\n", machine().describe_context(), data);

	m_ysize = (m_ysize & 0xf00) | data;
}


//-------------------------------------------------
//  ldtx_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldtx_hb_w )
{
	/*

	    bit     description

	    0       XTO8, MTA4
	    1       XTO9, MTA5
	    2
	    3
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDTX HB: %02x\n", machine().describe_context(), data);

	m_xto = ((data & 0x03) << 8) | (m_xto & 0xff);
	m_mta = (m_mta & 0x3ffcf) | ((data & 0x03) << 4);
}


//-------------------------------------------------
//  ldtx_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldtx_lb_w )
{
	/*

	    bit     description

	    0       XTO0
	    1       XTO1
	    2       XTO2
	    3       XTO3
	    4       XTO4, MTA0
	    5       XTO5, MTA1
	    6       XTO6, MTA2
	    7       XTO7, MTA3

	*/

	if (LOG) logerror("%s LDTX LB: %02x\n", machine().describe_context(), data);

	m_xto = (m_xto & 0x300) | data;
	m_mta = (m_mta & 0x3fff0) | (data >> 4);
}


//-------------------------------------------------
//  ldty_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldty_hb_w )
{
	/*

	    bit     description

	    0       YTO8, MTA14
	    1       YTO9, MTA15
	    2       YTO10, MTA16
	    3       YTO11, MTA17
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDTY HB: %02x\n", machine().describe_context(), data);

	if (L_P) return;

	m_ty = ((data & 0x0f) << 8) | (m_yto & 0xff);
	m_yto = ((data & 0x0f) << 8) | (m_yto & 0xff);
	m_mta = ((data & 0x0f) << 14) | (m_mta & 0x3fff);
}


//-------------------------------------------------
//  ldty_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldty_lb_w )
{
	/*

	    bit     description

	    0       YTO0, MTA6
	    1       YTO1, MTA7
	    2       YTO2, MTA8
	    3       YTO3, MTA9
	    4       YTO4, MTA10
	    5       YTO5, MTA11
	    6       YTO6, MTA12
	    7       YTO7, MTA13

	*/

	if (LOG) logerror("%s LDTY LB: %02x\n", machine().describe_context(), data);

	if (L_P) return;

	m_ty = (m_ty & 0xf00) | data;
	m_yto = (m_yto & 0xf00) | data;
	m_mta = (m_mta & 0x3c03f) | (data << 6);
}


//-------------------------------------------------
//  ldfx_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldfx_hb_w )
{
	/*

	    bit     description

	    0       XFROM8, MFA4
	    1       XFROM9, MFA5
	    2
	    3
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDFX HB: %02x\n", machine().describe_context(), data);

	m_xfrom = ((data & 0x03) << 8) | (m_xfrom & 0xff);
	m_mfa = (m_mfa & 0x3ffcf) | ((data & 0x03) << 4);
}


//-------------------------------------------------
//  ldfx_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldfx_lb_w )
{
	/*

	    bit     description

	    0       XFROM0
	    1       XFROM1
	    2       XFROM2
	    3       XFROM3
	    4       XFROM4, MFA0
	    5       XFROM5, MFA1
	    6       XFROM6, MFA2
	    7       XFROM7, MFA3

	*/

	if (LOG) logerror("%s LDFX LB: %02x\n", machine().describe_context(), data);

	m_xfrom = (m_xfrom & 0x300) | data;
	m_mfa = (m_mfa & 0x3fff0) | (data >> 4);
}


//-------------------------------------------------
//  ldfy_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldfy_hb_w )
{
	/*

	    bit     description

	    0       MFA14
	    1       MFA15
	    2       MFA16
	    3       MFA17
	    4
	    5
	    6
	    7

	*/

	if (LOG) logerror("%s LDFY HB: %02x\n", machine().describe_context(), data);

	m_mfa = ((data & 0x0f) << 14) | (m_mfa & 0x3fff);
}


//-------------------------------------------------
//  ldfy_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::ldfy_lb_w )
{
	/*

	    bit     description

	    0       MFA6
	    1       MFA7
	    2       MFA8
	    3       MFA9
	    4       MFA10
	    5       MFA11
	    6       MFA12
	    7       MFA13

	*/

	if (LOG) logerror("%s LDFY LB: %02x\n", machine().describe_context(), data);

	m_mfa = (m_mfa & 0x3c03f) | (data << 6);

	mover();
}


//-------------------------------------------------
//  wrml_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::wrml_w )
{
	/*

	    bit     description

	    0       MOVE CYK CLK
	    1       DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK)
	    2       DATA CLK
	    3       _DISP MEM WE
	    4       _CAS HB
	    5       DTACK CLK / BLANK TEST (+2 PIXCLK)
	    6       DISPREC CLK
	    7       _RAS HB

	*/

	if (LOG) logerror("MS %u : %02x\n", (offset >> 4) & 0x0f, data);

	if (m_clocks_disabled)
	{
		m_ms[(offset >> 4) & 0x0f] = data;
	}
}


//-------------------------------------------------
//  wrdl_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::wrdl_w )
{
	/*

	    bit     description

	    0       MOVE CYK CLK
	    1       DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK)
	    2       DATA CLK
	    3       _DISP MEM WE
	    4       _CAS HB
	    5       DTACK CLK / BLANK TEST (+2 PIXCLK)
	    6       DISPREC CLK
	    7       _RAS HB

	*/

	if (LOG) logerror("WS %u : %02x\n", (offset >> 4) & 0x0f, data);

	if (m_clocks_disabled)
	{
		m_ds[(offset >> 4) & 0x0f] = data;
	}
}


//-------------------------------------------------
//  wrmask_strobe_hb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::wrmask_strobe_hb_w )
{
	if (REPLACE)
	{
		// DATAPORT_HB
		m_gmdi = (data << 8) | (m_gmdi & 0xff);
		if (LOG) logerror("GMDI HB %04x\n", m_gmdi);
	}
	else
	{
		// WRPORT_HB
		m_wrm = (data << 8) | (m_wrm & 0xff);
		if (LOG) logerror("WRM HB %04x\n", m_gmdi);
	}
}


//-------------------------------------------------
//  wrmask_strobe_lb_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::wrmask_strobe_lb_w )
{
	if (REPLACE)
	{
		// DATAPORT_LB
		m_gmdi = (m_gmdi & 0xff00) | data;
		if (LOG) logerror("GMDI LB %04x\n", m_gmdi);
	}
	else
	{
		// WRPORT_LB
		m_wrm = (m_wrm & 0xff00) | data;
		if (LOG) logerror("WRM LB %04x\n", m_gmdi);
	}
}


//-------------------------------------------------
//  enable_clocks_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::enable_clocks_w )
{
	if (LOG) logerror("ENABLE CLOCKS\n");
	m_clocks_disabled = 0;
}


//-------------------------------------------------
//  flag_strobe_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::flag_strobe_w )
{
	/*

	    bit     description

	    0       L/_P FLAG
	    1       BLANK FLAG
	    2       PIX POL
	    3       FRAME POL
	    4       HOLD FY
	    5       HOLD FX
	    6       COMP MOVE FLAG
	    7       REPLACE/SET & RESET

	*/

	m_flag = data;
	if (LOG) logerror("FLAG %02x\n", m_flag);
}


//-------------------------------------------------
//  endisp_w -
//-------------------------------------------------

WRITE8_MEMBER( abc1600_mover_device::endisp_w )
{
	m_endisp = 1;
	if (LOG) logerror("ENDISP\n");
}



//**************************************************************************
//  MOVER
//**************************************************************************

//-------------------------------------------------
//  clock_mfa_x -
//-------------------------------------------------

inline void abc1600_mover_device::clock_mfa_x()
{
	UINT16 mfa_y = m_mfa >> 6;
	UINT8 mfa_x = m_mfa & 0x3f;

	if (!HOLD_FX)
	{
		mfa_x += m_udx ? 1 : -1;
		mfa_x &= 0x3f;
	}

	m_mfa = (mfa_y << 6) | mfa_x;
}


//-------------------------------------------------
//  clock_mfa_y -
//-------------------------------------------------

inline void abc1600_mover_device::clock_mfa_y()
{
	UINT16 mfa_y = m_mfa >> 6;
	UINT8 mfa_x = m_mfa & 0x3f;

	if (!HOLD_FY)
	{
		mfa_y += m_udy ? 1 : -1;
		mfa_y &= 0xfff;
	}

	m_mfa = (mfa_y << 6) | mfa_x;
}


//-------------------------------------------------
//  clock_mta_x -
//-------------------------------------------------

inline void abc1600_mover_device::clock_mta_x()
{
	UINT16 mta_y = m_mta >> 6;
	UINT8 mta_x = m_mta & 0x3f;

	mta_x += m_udx ? 1 : -1;
	mta_x &= 0x3f;

	m_mta = (mta_y << 6) | mta_x;
}


//-------------------------------------------------
//  clock_mta_y -
//-------------------------------------------------

inline void abc1600_mover_device::clock_mta_y()
{
	UINT16 mta_y = m_mta >> 6;
	UINT8 mta_x = m_mta & 0x3f;

	mta_y += m_udy ? 1 : -1;
	mta_y &= 0xfff;

	m_mta = (mta_y << 6) | mta_x;
}


//-------------------------------------------------
//  load_mfa_x -
//-------------------------------------------------

inline void abc1600_mover_device::load_mfa_x()
{
	UINT16 mfa_y = m_mfa >> 6;
	UINT8 mfa_x = m_xfrom >> 4;

	m_mfa = (mfa_y << 6) | mfa_x;
}


//-------------------------------------------------
//  load_mta_x -
//-------------------------------------------------

inline void abc1600_mover_device::load_mta_x()
{
	UINT16 mta_y = m_mta >> 6;
	UINT8 mta_x = m_xto >> 4;

	m_mta = (mta_y << 6) | mta_x;
}


//-------------------------------------------------
//  load_xy_reg -
//-------------------------------------------------

inline void abc1600_mover_device::load_xy_reg()
{
	if (L_P) return;

	UINT16 sum = m_xto + m_xsize;

	m_xto = sum & 0x3ff;
	m_yto = m_ty & 0xfff;
	m_mta = (m_ty << 6) | (sum >> 4);
}


//-------------------------------------------------
//  compare_mta_x -
//-------------------------------------------------

inline void abc1600_mover_device::compare_mta_x()
{
	UINT8 mta_x_end = ((m_xto + m_xsize) >> 4) & 0x3f;
	UINT8 mta_x = m_mta & 0x3f;

	if (mta_x == mta_x_end)
	{
		m_cmc = 0;
	}

	m_wrms1 = m_cmc & m_amm;
}


//-------------------------------------------------
//  compare_mta_y -
//-------------------------------------------------

inline void abc1600_mover_device::compare_mta_y()
{
	int mta_y_end = (m_yto + m_ysize) & 0xfff;
	UINT16 mta_y = m_mta >> 6;

	if (mta_y == mta_y_end)
	{
		m_rmc = 0;
	}
}


//-------------------------------------------------
//  get_shinf -
//-------------------------------------------------

inline void abc1600_mover_device::get_shinf()
{
	/*

	    bit     description

	    A0      XFROM0
	    A1      XFROM1
	    A2      XFROM2
	    A3      XFROM3
	    A4      XTO0
	    A5      XTO1
	    A6      XTO2
	    A7      XTO3
	    A8      U/D* X

	*/

	UINT16 shinf_addr = (m_udx << 8) | ((m_xto & 0x0f) << 4) | (m_xfrom & 0x0f);
	UINT8 shinf = m_shinf_rom[shinf_addr];

	m_sh = shinf & 0x0f;
	m_hold_1w_cyk = BIT(shinf, 5);
}


//-------------------------------------------------
//  get_drmsk -
//-------------------------------------------------

inline UINT16 abc1600_mover_device::get_drmsk()
{
	/*

	    bit     description

	    A0      SH0
	    A1      SH1
	    A2      SH2
	    A3      SH3
	    A4      U/D* X

	*/

	UINT16 drmsk_addr = (m_udx << 4) | (m_sh & 0x0f);
	return m_drmsk_rom[drmsk_addr];
}


//-------------------------------------------------
//  get_wrmsk - get mover write mask
//-------------------------------------------------

inline UINT16 abc1600_mover_device::get_wrmsk()
{
	/*

	    bit     description

	    A0      XTO0
	    A1      XTO1
	    A2      XTO2
	    A3      XTO3
	    A4      XSIZE0
	    A5      XSIZE1
	    A6      XSIZE2
	    A7      XSIZE3
	    A8      U/D* X
	    A9      ANDED MASKS
	    A10     WRMS0
	    A11     WRMS1

	*/

	UINT16 wrmsk_addr = (m_wrms1 << 11) | (m_wrms0 << 10) | ((!m_wrms1 && !m_wrms0) << 9) | (m_udx << 8) | ((m_xsize & 0x0f) << 4) | (m_xto & 0x0f);
	return m_wrmsk_rom[wrmsk_addr] ^ 0xffff;
}


//-------------------------------------------------
//  barrel_shift -
//-------------------------------------------------

inline UINT16 abc1600_mover_device::barrel_shift(UINT16 gmdr)
{
	UINT16 rot = gmdr;

	for (int sh = 0; sh < m_sh; sh++)
	{
		int msb = BIT(rot, 15);
		rot <<= 1;
		rot |= msb;
	}

	return rot;
}


//-------------------------------------------------
//  word_mixer -
//-------------------------------------------------

inline UINT16 abc1600_mover_device::word_mixer(UINT16 rot)
{
	UINT16 drmsk = get_drmsk();
	UINT16 gmdi = (rot & drmsk) | (m_mdor & (drmsk ^ 0xffff));

	if (COMP_MOVE)
	{
		gmdi ^= 0xffff;
	}

	m_mdor = rot;

	return gmdi;
}


//-------------------------------------------------
//  mover -
//-------------------------------------------------

void abc1600_mover_device::mover()
{
	if (LOG) logerror("XFROM %u XSIZE %u YSIZE %u XTO %u YTO %u MFA %05x MTA %05x U/D*X %u U/D*Y %u\n", m_xfrom, m_xsize, m_ysize, m_xto, m_yto, m_mfa, m_mta, m_udx, m_udy);

	m_amm = 1;

	m_rmc = 1;
	get_shinf();

	do
	{
		compare_mta_y();

		load_mfa_x();
		load_mta_x();
		m_cmc = 1;
		m_wrms0 = 0;

		if (m_hold_1w_cyk)
		{
			// read one word in advance
			UINT16 gmdr = read_videoram(m_mfa);
			UINT16 rot = barrel_shift(gmdr);
			word_mixer(rot);

			clock_mfa_x();
		}

		do
		{
			compare_mta_x();

			UINT16 gmdr = read_videoram(m_mfa);
			UINT16 rot = barrel_shift(gmdr);
			UINT16 gmdi = word_mixer(rot);
			UINT16 mask = get_wrmsk();

			write_videoram(m_mta, gmdi, mask);

			clock_mfa_x();
			clock_mta_x();

			m_wrms0 = 1;
		}
		while (m_cmc);

		clock_mfa_y();
		clock_mta_y();
	}
	while (m_rmc);

	load_xy_reg();

	m_amm = 0;
}

UINT32 abc1600_mover_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	if (m_endisp)
	{
		bitmap.fill(m_palette->pen(FRAME_POL), cliprect);
		m_crtc->screen_update(screen, bitmap, cliprect);
	}
	else
	{
		bitmap.fill(rgb_t::black, cliprect);
	}

	return 0;
}