summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/tia.cpp
blob: 6fe49fb13e7b11639c60fc6861579f7765bc1859 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                                               





                                                                            
                
                
                   
 











                              


                                       
         
                                                 


                                                
 
                                             
                 
                                                         


                                                        
 
                                                             






                                                        
                                          
 












































































                                                                             















                                   

                        















                                   

                        















                                   

                        















                                   

                        















                                   

                        















                                   





                                              

                                   














                                   

          
                                    
         

                                             
 
                                           
                 
                                                 




                                                             



                                         



                                        



                                         
                                      



                                                                

                 
                         


 
                                         
 
                                              


















                                   
                                    
         

                                             
 
                                           
                 
                                                 




                                                             



                                         



                                        



                                         
                                      



                                                                

                 
                         

 


                                                                                                                                     
                                                  


                                      
                                      
                                              


 
                         
                                                                                           

                                                   
                                      

                                                   
                                                                                                                           
                                                                     


 
                         
                                                                                               




                                                   
                                                                                                                             
                                                                      


 
                                                   

                                                   
 
                                     
 
                            


                                        
 
                       
 
                                  
 
                                          


                                                      
 
                              


 



                                                   
                                                                                                                
 
                                        
                                                         



                 

                                                                                           






                     
                                                              






















                                                                                      

                                                                                                                   





























































                                                                                                           

                                                                                
 
                     


                                                                   





                  
                                  































                                                      
                                                                                         

















                                                      
                                                       




                                                                                          
                                                       




                                                                                          
                                                       




                                                                                                             
                                                       




                                                                                                             
                                                       




                                                                           
                                                       








                                                                
                                                                               














                                                   
                                 
 
                                                                          


 
                                 
 
                                                               


 
                                        









                                                                                               
                                                                                                                                                   


















                                                                                               
                                                                                                                                                   















                                                                                              
                                                            



              





                            
 
                          










































                                                 
                            








































                                                                                                                 
                                                                                            

























































































































































                                                                                         
                                                                         






                                                                              
                                



                                                                                      
                                        
                                                                             

                                                                          
                                                                                                  
                                                
                                                                       











                                            
                                          
 
                                                              


                        
                                                           



         
                                          




                                 
                                                 


                                              

                                                           
 

                                                               




                                   
                                                         






                     
                                           


                        
                                                         








                                    
                                           
 
                                 






                                     
                                         
 
                                 






                                                           
                                                                                                            


                                                                                
                                                                                                                 
















                                                              
                                         
 
                                 






                                                           
                                                                                                            


                                                                                
                                                                                                                 
















                                                              
                                         
 
                                 






                                                           
                                                                                                            


                                                                                
                                                                                                                 















                                                              
                                         
 
                                 






                                                           
                                                                                                            


                                                                                
                                                                                                                 















                                                              
                                         
 
                                 






                                                           
                                                                                                            


                                                                                
                                                                                                                 















                                                              
                                          
 

                                 




































































































                                                                                                       
                                                 










                                                    
                                                                                 






                           
                                          




                                                  
                                           
 
                                 













                                                                                                                                               
                                                                                                     








                                                                                                                                
                                                                                                     























                                                                                                                                    
                                                                                                          
























                                                                                                                                 
                                           
 
                                 













                                                                                                                                               
                                                                                                     








                                                                                                                                
                                                                                                     























                                                                                                                                    
                                                                                                          
























                                                                                                                                 
                                          
 




                                   


 
                                          











                   
                                                                                         
                                                                                                  






                                                                                                         

         


                                                                                                 
                                                                                                       

                                                                                                     
                                                                                                           

                                                                                                         

         
                                          
 
                                 
































                                                                                                                            
                                                                                                          






















                                                                                                                                   
                                          
 
                                 
































                                                                                                                            
                                                                                                          






















                                                                                                                                   
                                          
 
                                 


















                                                                                               
                                          
 
                                 


















                                                                                               
                                          
 
                                 












                                                                                            
                                           




















                                                                       
                                           




















                                                                       
                                         






                        
                                         








                          
                                        
 
                                                                    
                                                  
                                             
         
                                                                 






                                                 
                                            
                                                     


 
                                      
 




                                                                          
                                     
 
                                              
         
                                                            



                            
                                                        




















                                     
                                              
                 
                                              
                 
                                              
                 
                                              

                 
                                                                                                                       




                                                                               
                                                                                                                       








                                                                               
                                        


                                      












































                                     
          

                                 















                                                              
                                             

                      
                                              

                      
                                             

                      
                                             

                      
                                              

                      
                                              













                              
                                              
















                             
                                             

                      
                                             

                      
                                             

                      
                                             

                      
                                             







                              
                                                        


                      
                                            

                      
                                            










                             
                                            

                      
                                            

                      
                                            

                      
                                            

                      
                                            










                              
                                              

                      
                                              

                      
                                             

                      
                                             

                      
                                          




                      




                                                   








































                                       


                   







                                               

                           
                           






























                       


                   
 





















































































                                                


                                   
 
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol,Stefan Jokisch
/***************************************************************************

  Atari TIA video emulation

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

#include "emu.h"
#include "tia.h"
#include "screen.h"

static const int nusiz[8][3] =
{
	{ 1, 1, 0 },
	{ 2, 1, 1 },
	{ 2, 1, 3 },
	{ 3, 1, 1 },
	{ 2, 1, 7 },
	{ 1, 2, 0 },
	{ 3, 1, 3 },
	{ 1, 4, 0 }
};

void tia_video_device::extend_palette()
{
	for (int i = 0; i < 128; i++)
	{
		rgb_t   new_rgb = pen_color( i );
		uint8_t   new_r =  new_rgb .r();
		uint8_t   new_g =  new_rgb .g();
		uint8_t   new_b =  new_rgb .b();

		for (int j = 0; j < 128; j++)
		{
			rgb_t   old_rgb = pen_color( j );
			uint8_t   old_r =  old_rgb .r();
			uint8_t   old_g =  old_rgb .g();
			uint8_t   old_b =  old_rgb .b();

			set_pen_color(( ( i + 1 ) << 7 ) | j,
				( new_r + old_r ) / 2,
				( new_g + old_g ) / 2,
				( new_b + old_b ) / 2 );
		}
	}
}

void tia_ntsc_video_device::init_palette()
{
	/********************************************************************
	Atari 2600 NTSC Palette Notes:

	Palette on a modern flat panel display (LCD, LED, Plasma, etc.)
	appears different from a traditional CRT. The most outstanding
	difference is Hue 1x, the hue begin point. Hue 1x looks very
	'green' (~-60 to -45 degrees - depending on how poor or well it
	handles the signal conversion and its calibration) on a modern
	flat panel display, as opposed to 'gold' (~-33 degrees) on a CRT.

	The official technical documents: "Television Interface Adaptor
	[TIA] (Model 1A)", "Atari VCS POP Field Service Manual", and
	"Stella Programmer's Guide" stipulate Hue 1x to be gold.

	The system's pot adjustment manually manipulates the degree of
	phase shift, while the system 'warming-up' will automatically
	push whatever degrees has been manually set, higher.  According
	to the Atari VCS POP Field Service Manual and system diagnostic
	and test (color) cart, instructions are provide to set the pot
	adjustment having Hue 1x and Hue 15x (F$) match or within one
	shade of each other, both a 'goldenrod'.

	At power on, the system's phase shift appears as low as ~23
	degrees and after a considerable consistent runtime, can be as
	high as ~28 degrees.

	In general, the low end of ~23 degrees lasts for several seconds,
	whereas higher values such as ~25-27 degrees are the most
	dominant during system run time.  180 degrees colorburst takes
	place at ~25.7 degrees (A near exact match of Hue 1x and 15x -
	To the naked eye they appear to be the same).

	However, if the system is adjusted within the first several
	minutes of running, the warm up, consistent system run time,
	causes Hue 15x (F$) to become stronger/darker gold (More brown
	then ultimately red-brown); as well as leans Hue 14x (E$) more
	brown than green.  Once achieving a phase shift of 27.7 degrees,
	Hue 14x (E$) and Hue 15x (F$) near-exact match Hue 1x and 2x
	respectively.

	Therefore, an ideal phase shift while accounting for properly
	calibrating a system's color palette within the first several
	minutes of it running via the pot adjustment, the reality of
	shifting while warming up, as well as maintaining differences
	between Hues 1x, 2x and 14x, 15x, would likely fall between 25.7
	and 27.7 degrees.  Phase shifts 26.2 and 26.7 places Hue 15x/F$
	between Hue 1x and Hue 2x, having 26.2 degrees leaning closer to
	Hue 1x and 26.7 degrees leaning closer to Hue 2x.

	The above notion would also harmonize with what has been
	documented within "Stella Programmer's Guide" for the colors of
	1x, 2x, 14x, 15x on the 2600 and 7800.  1x = Gold, 2x = Orange,
	14x (E$) = Orange-Green. 15x (F$) = Light Orange.  Color
	descriptions are best measured in the middle of the brightness
	scale.  It should be mentioned that Green-Yellow is referenced
	at Hue 13x (D$), nowhere near Hue 1x.  A Green-Yellow Hue 1x is
	how the palette is manipulated and modified (in part) under a
	modern flat panel display.

	Additionally, the blue to red (And consequently blue to green)
	ratio proportions may appear different on a modern flat panel
	display than a CRT in some instances for the Atari 2600 system.
	Furthermore, you may have some variation of proportions even
	within the same display type.

	One side effect of this on the console's palette is that some
	values of red may appear too pinkish - Too much blue to red.
	This is not the same as a traditional tint-hue control adjustment;
	rather, can be demonstrated by changing the blue ratio values
	via MESS HLSL settings.

	Lastly, the Atari 5200 & 7800 NTSC color palettes hold the same
	hue structure order and have similar appearance differences that
	are dependent upon display type.
	********************************************************************/
	/*********************************
	Phase Shift 24.7
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.239, -0.052 },
	        {  0.244,  0.030 },
	        {  0.201,  0.108 },
	        {  0.125,  0.166 },
	        {  0.026,  0.194 },
	        { -0.080,  0.185 },
	        { -0.169,  0.145 },
	        { -0.230,  0.077 },
	        { -0.247, -0.006 },
	        { -0.220, -0.087 },
	        { -0.152, -0.153 },
	        { -0.057, -0.189 },
	        {  0.049, -0.193 },
	        {  0.144, -0.161 }

	Phase Shift 25.2
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.239, -0.052 },
	        {  0.244,  0.033 },
	        {  0.200,  0.113 },
	        {  0.119,  0.169 },
	        {  0.013,  0.195 },
	        { -0.094,  0.183 },
	        { -0.182,  0.136 },
	        { -0.237,  0.062 },
	        { -0.245, -0.020 },
	        { -0.210, -0.103 },
	        { -0.131, -0.164 },
	        { -0.027, -0.193 },
	        {  0.079, -0.187 },
	        {  0.169, -0.145 }

	Phase Shift 25.7
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.243, -0.049 },
	        {  0.242,  0.038 },
	        {  0.196,  0.116 },
	        {  0.109,  0.172 },
	        {  0.005,  0.196 },
	        { -0.104,  0.178 },
	        { -0.192,  0.127 },
	        { -0.241,  0.051 },
	        { -0.244, -0.037 },
	        { -0.197, -0.115 },
	        { -0.112, -0.173 },
	        { -0.004, -0.197 },
	        {  0.102, -0.179 },
	        {  0.190, -0.128 }

	Phase Shift 26.7
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.242, -0.046 },
	        {  0.240,  0.044 },
	        {  0.187,  0.125 },
	        {  0.092,  0.180 },
	        { -0.020,  0.195 },
	        { -0.128,  0.170 },
	        { -0.210,  0.107 },
	        { -0.247,  0.022 },
	        { -0.231, -0.067 },
	        { -0.166, -0.142 },
	        { -0.064, -0.188 },
	        {  0.049, -0.193 },
	        {  0.154, -0.155 },
	        {  0.227, -0.086 }

	Phase Shift 27.2
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.243, -0.044 },
	        {  0.239,  0.047 },
	        {  0.183,  0.129 },
	        {  0.087,  0.181 },
	        { -0.029,  0.195 },
	        { -0.138,  0.164 },
	        { -0.217,  0.098 },
	        { -0.246,  0.009 },
	        { -0.223, -0.081 },
	        { -0.149, -0.153 },
	        { -0.041, -0.192 },
	        {  0.073, -0.188 },
	        {  0.173, -0.142 },
	        {  0.235, -0.067 }

	Phase Shift 27.7
	        {  0.000,  0.000 },
	        {  0.192, -0.127 },
	        {  0.243, -0.044 },
	        {  0.238,  0.051 },
	        {  0.178,  0.134 },
	        {  0.078,  0.184 },
	        { -0.041,  0.194 },
	        { -0.151,  0.158 },
	        { -0.224,  0.087 },
	        { -0.248, -0.005 },
	        { -0.214, -0.096 },
	        { -0.131, -0.164 },
	        { -0.019, -0.195 },
	        {  0.099, -0.182 },
	        {  0.194, -0.126 },
	        {  0.244, -0.042 }
	*********************************/

	/*********************************
	Phase Shift 26.2
	**********************************/
	static constexpr double color[16][2] =
	{
		{  0.000,  0.000 },
		{  0.192, -0.127 },
		{  0.241, -0.048 },
		{  0.240,  0.040 },
		{  0.191,  0.121 },
		{  0.103,  0.175 },
		{ -0.008,  0.196 },
		{ -0.116,  0.174 },
		{ -0.199,  0.118 },
		{ -0.243,  0.037 },
		{ -0.237, -0.052 },
		{ -0.180, -0.129 },
		{ -0.087, -0.181 },
		{  0.021, -0.196 },
		{  0.130, -0.169 },
		{  0.210, -0.107 }
	};

	for (int i = 0; i < 16; i++)
	{
		double const I = color[i][0];
		double const Q = color[i][1];

		for (int j = 0; j < 8; j++)
		{
			double const Y = j / 7.0;

			double R = Y + 0.956 * I + 0.621 * Q;
			double G = Y - 0.272 * I - 0.647 * Q;
			double B = Y - 1.106 * I + 1.703 * Q;

			if (R < 0) R = 0;
			if (G < 0) G = 0;
			if (B < 0) B = 0;

			R = pow(R, 0.9);
			G = pow(G, 0.9);
			B = pow(B, 0.9);

			if (R > 1) R = 1;
			if (G > 1) G = 1;
			if (B > 1) B = 1;

			set_pen_color(
					8 * i + j,
					uint8_t(255 * R + 0.5),
					uint8_t(255 * G + 0.5),
					uint8_t(255 * B + 0.5));
		}
	}
	extend_palette();
}


void tia_pal_video_device::init_palette()
{
	static constexpr double color[16][2] =
	{
		{  0.000,  0.000 },
		{  0.000,  0.000 },
		{ -0.222,  0.032 },
		{ -0.199, -0.027 },
		{ -0.173,  0.117 },
		{ -0.156, -0.197 },
		{ -0.094,  0.200 },
		{ -0.071, -0.229 },
		{  0.070,  0.222 },
		{  0.069, -0.204 },
		{  0.177,  0.134 },
		{  0.163, -0.130 },
		{  0.219,  0.053 },
		{  0.259, -0.042 },
		{  0.000,  0.000 },
		{  0.000,  0.000 }
	};

	for (int i = 0; i < 16; i++)
	{
		double const U = color[i][0];
		double const V = color[i][1];

		for (int j = 0; j < 8; j++)
		{
			double const Y = j / 7.0;

			double R = Y + 1.403 * V;
			double G = Y - 0.344 * U - 0.714 * V;
			double B = Y + 1.770 * U;

			if (R < 0) R = 0;
			if (G < 0) G = 0;
			if (B < 0) B = 0;

			R = pow(R, 1.2);
			G = pow(G, 1.2);
			B = pow(B, 1.2);

			if (R > 1) R = 1;
			if (G > 1) G = 1;
			if (B > 1) B = 1;

			set_pen_color(
					8 * i + j,
					uint8_t(255 * R + 0.5),
					uint8_t(255 * G + 0.5),
					uint8_t(255 * B + 0.5));
		}
	}
	extend_palette();
}

tia_video_device::tia_video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, type, tag, owner, clock)
	, device_video_interface(mconfig, *this)
	, device_palette_interface(mconfig, *this)
	, m_read_input_port_cb(*this)
	, m_databus_contents_cb(*this)
	, m_vsync_cb(*this)
	, m_maincpu(*this, "^maincpu")
	, m_tia(*this, finder_base::DUMMY_TAG)
{
}

// device type definition
DEFINE_DEVICE_TYPE(TIA_PAL_VIDEO, tia_pal_video_device, "tia_pal_video", "TIA Video (PAL)")

//-------------------------------------------------
//  tia_pal_video_device - constructor
//-------------------------------------------------

tia_pal_video_device::tia_pal_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: tia_video_device(mconfig, TIA_PAL_VIDEO, tag, owner, clock)
{
}

// device type definition
DEFINE_DEVICE_TYPE(TIA_NTSC_VIDEO, tia_ntsc_video_device, "tia_ntsc_video", "TIA Video (NTSC)")

//-------------------------------------------------
//  tia_ntsc_video_device - constructor
//-------------------------------------------------

tia_ntsc_video_device::tia_ntsc_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: tia_video_device(mconfig, TIA_NTSC_VIDEO, tag, owner, clock)
{
}

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

void tia_video_device::device_start()
{
	// resolve callbacks
	m_read_input_port_cb.resolve();
	m_databus_contents_cb.resolve();
	m_vsync_cb.resolve();

	init_palette();

	int cx = screen().width();

	screen_height = screen().height();
	helper[0].allocate(cx, TIA_MAX_SCREEN_HEIGHT);
	helper[1].allocate(cx, TIA_MAX_SCREEN_HEIGHT);
	buffer.allocate(cx, TIA_MAX_SCREEN_HEIGHT);

	register_save_state();
}


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

uint32_t tia_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	screen_height = screen.height();
	copybitmap(bitmap, buffer, 0, 0, 0, 0, cliprect);
	return 0;
}


void tia_video_device::draw_sprite_helper(uint8_t* p, uint8_t *col, struct player_gfx *gfx,
	uint8_t GRP, uint8_t COLUP, uint8_t REFP)
{
	int i;
	int j;
	int k;

	if (REFP & 8)
	{
		GRP = bitswap<8>(GRP, 0, 1, 2, 3, 4, 5, 6, 7);
	}

	for (i = 0; i < PLAYER_GFX_SLOTS; i++)
	{
		int start_pos = gfx->start_drawing[i];
		for (j = gfx->start_pixel[i]; j < 8; j++)
		{
			for (k = 0; k < gfx->size[i]; k++)
			{
				if (GRP & (0x80 >> j))
				{
					if ( start_pos < 160 || ! gfx->skipclip[i] ) {
						p[start_pos % 160] = COLUP >> 1;
						col[start_pos % 160] = COLUP >> 1;
					}
				}
				start_pos++;
			}
		}
	}
}


void tia_video_device::draw_missile_helper(uint8_t* p, uint8_t* col, int horz, int skipdelay, int latch, int start,
	uint8_t RESMP, uint8_t ENAM, uint8_t NUSIZ, uint8_t COLUM)
{
	int num = nusiz[NUSIZ & 7][0];
	int skp = nusiz[NUSIZ & 7][2];

	int width = 1 << ((NUSIZ >> 4) & 3);

	int i;
	int j;

	for (i = 0; i < num; i++)
	{
		if ( i == 0 )
			horz -= skipdelay;
		if ( i == 1 )
			horz += skipdelay;
		if ( i > 0 || start ) {
			for (j = 0; j < width; j++)
			{
				if ((ENAM & 2) && !(RESMP & 2))
				{
					if ( latch ) {
						switch ( horz % 4 ) {
						case 1:
							if ( horz >= 0 )
							{
								if ( horz < 156 ) {
									p[(horz + 1) % 160] = COLUM >> 1;
									col[(horz + 1) % 160] = COLUM >> 1;
								}
								p[horz % 160] = COLUM >> 1;
								col[horz % 160] = COLUM >> 1;
							}
							break;
						case 2:
						case 3:
							if ( horz >= 0 )
							{
								p[horz % 160] = COLUM >> 1;
								col[horz % 160] = COLUM >> 1;
							}
							break;
						}
					} else {
						if ( horz >= 0 )
						{
							p[horz % 160] = COLUM >> 1;
							col[horz % 160] = COLUM >> 1;
						}
					}
				}

				horz++;
			}
		} else {
			horz+= width;
		}

		horz += 8 * (skp + 1) - width;
	}
}


void tia_video_device::draw_playfield_helper(uint8_t* p, uint8_t* col, int horz,
	uint8_t COLU, uint8_t REFPF)
{
	uint32_t PF =
		(bitswap<8>(PF0, 0, 1, 2, 3, 4, 5, 6, 7) << 0x10) |
		(bitswap<8>(PF1, 7, 6, 5, 4, 3, 2, 1, 0) << 0x08) |
		(bitswap<8>(PF2, 0, 1, 2, 3, 4, 5, 6, 7) << 0x00);

	int i;
	int j;

	if (REFPF)
	{
		uint32_t swap = 0;

		for (i = 0; i < 20; i++)
		{
			swap <<= 1;

			if (PF & 1)
			{
				swap |= 1;
			}

			PF >>= 1;
		}

		PF = swap;
	}

	for (i = 0; i < 20; i++)
	{
		for (j = 0; j < 4; j++)
		{
			if (PF & (0x80000 >> i))
			{
				p[horz] = COLU >> 1;
				col[horz] = COLU >> 1;
			}

			horz++;
		}
	}
}


void tia_video_device::draw_ball_helper(uint8_t* p, uint8_t* col, int horz, uint8_t ENAB)
{
	int width = 1 << ((CTRLPF >> 4) & 3);

	int i;

	for (i = 0; i < width; i++)
	{
		if (ENAB & 2)
		{
			p[horz % 160] = COLUPF >> 1;
			col[horz % 160] = COLUPF >> 1;
		}

		horz++;
	}
}


void tia_video_device::drawS0(uint8_t* p, uint8_t* col)
{
	draw_sprite_helper(p, col, &p0gfx, (VDELP0 & 1) ? prevGRP0 : GRP0, COLUP0, REFP0);
}


void tia_video_device::drawS1(uint8_t* p, uint8_t* col)
{
	draw_sprite_helper(p, col, &p1gfx, (VDELP1 & 1) ? prevGRP1 : GRP1, COLUP1, REFP1);
}


void tia_video_device::drawM0(uint8_t* p, uint8_t* col)
{
	draw_missile_helper(p, col, horzM0, skipM0delay, HMM0_latch, startM0, RESMP0, ENAM0, NUSIZ0, COLUP0);
}


void tia_video_device::drawM1(uint8_t* p, uint8_t* col)
{
	draw_missile_helper(p, col, horzM1, skipM1delay, HMM1_latch, startM1, RESMP1, ENAM1, NUSIZ1, COLUP1);
}


void tia_video_device::drawBL(uint8_t* p, uint8_t* col)
{
	draw_ball_helper(p, col, horzBL, (VDELBL & 1) ? prevENABL : ENABL);
}


void tia_video_device::drawPF(uint8_t* p, uint8_t *col)
{
	draw_playfield_helper(p, col, 0,
		((CTRLPF & 6) == 2) ? COLUP0 : COLUPF, 0);

	draw_playfield_helper(p, col, 80,
		((CTRLPF & 6) == 2) ? COLUP1 : COLUPF, REFLECT);
}


int tia_video_device::collision_check(uint8_t* p1, uint8_t* p2, int x1, int x2)
{
	int i;

	for (i = x1; i < x2; i++)
	{
		if (p1[i] != 0xFF && p2[i] != 0xFF)
		{
			return 1;
		}
	}

	return 0;
}


int tia_video_device::current_x()
{
	return 3 * ((m_maincpu->total_cycles() - frame_cycles) % 76) - 68;
}


int tia_video_device::current_y()
{
	return (m_maincpu->total_cycles() - frame_cycles) / 76;
}


void tia_video_device::setup_pXgfx(void)
{
	int i;
	for ( i = 0; i < PLAYER_GFX_SLOTS; i++ )
	{
		if ( i < nusiz[NUSIZ0 & 7][0] && i >= ( startP0 ? 0 : 1 ) )
		{
			p0gfx.size[i] = nusiz[NUSIZ0 & 7][1];
			if ( i )
			{
				p0gfx.start_drawing[i] = ( horzP0 + (p0gfx.size[i] > 1 ? 1 : 0)
											+ i * 8 * ( nusiz[NUSIZ0 & 7][2] + p0gfx.size[i] ) ) % 160;
				p0gfx.skipclip[i] = 0;
			}
			else
			{
				p0gfx.start_drawing[i] = horzP0 + (p0gfx.size[i] > 1 ? 1 : 0 );
				p0gfx.skipclip[i] = skipclipP0;
			}
			p0gfx.start_pixel[i] = 0;
		}
		else
		{
			p0gfx.start_pixel[i] = 8;
		}
		if ( i < nusiz[NUSIZ1 & 7][0] && i >= ( startP1 ? 0 : 1 ) )
		{
			p1gfx.size[i] = nusiz[NUSIZ1 & 7][1];
			if ( i )
			{
				p1gfx.start_drawing[i] = ( horzP1 + (p1gfx.size[i] > 1 ? 1 : 0)
											+ i * 8 * ( nusiz[NUSIZ1 & 7][2] + p1gfx.size[i] ) ) % 160;
				p1gfx.skipclip[i] = 0;
			}
			else
			{
				p1gfx.start_drawing[i] = horzP1 + (p1gfx.size[i] > 1 ? 1 : 0);
				p1gfx.skipclip[i] = skipclipP1;
			}
			p1gfx.start_pixel[i] = 0;
		}
		else
		{
			p1gfx.start_pixel[i] = 8;
		}
	}
}

void tia_video_device::update_bitmap(int next_x, int next_y)
{
	int x;
	int y;

	uint8_t linePF[160];
	uint8_t lineP0[160];
	uint8_t lineP1[160];
	uint8_t lineM0[160];
	uint8_t lineM1[160];
	uint8_t lineBL[160];

	uint8_t temp[160];

	if (prev_y >= next_y && prev_x >= next_x)
	{
		return;
	}

	memset(linePF, 0xFF, sizeof linePF);
	memset(lineP0, 0xFF, sizeof lineP0);
	memset(lineP1, 0xFF, sizeof lineP1);
	memset(lineM0, 0xFF, sizeof lineM0);
	memset(lineM1, 0xFF, sizeof lineM1);
	memset(lineBL, 0xFF, sizeof lineBL);

	if (VBLANK & 2)
	{
		memset(temp, 0, 160);
	}
	else
	{
		memset(temp, COLUBK >> 1, 160);

		if (CTRLPF & 4)
		{
			drawS1(temp, lineP1);
			drawM1(temp, lineM1);
			drawS0(temp, lineP0);
			drawM0(temp, lineM0);
			drawPF(temp, linePF);
			drawBL(temp, lineBL);
		}
		else
		{
			drawPF(temp, linePF);
			drawBL(temp, lineBL);
			drawS1(temp, lineP1);
			drawM1(temp, lineM1);
			drawS0(temp, lineP0);
			drawM0(temp, lineM0);
		}
	}

	for (y = prev_y; y <= next_y; y++)
	{
		uint16_t* p;

		int x1 = prev_x;
		int x2 = next_x;
		int colx1;

		/* Check if we have crossed a line boundary */
		if ( y !=  prev_y ) {
			int redraw_line = 0;

			HMOVE_started_previous = HMOVE_INACTIVE;

			if ( HMOVE_started != HMOVE_INACTIVE ) {
				/* Apply pending motion clocks from a HMOVE initiated during the scanline */
				if ( HMOVE_started >= 97 && HMOVE_started < 157 ) {
					horzP0 -= motclkP0;
					horzP1 -= motclkP1;
					horzM0 -= motclkM0;
					horzM1 -= motclkM1;
					horzBL -= motclkBL;
					if (horzP0 < 0)
						horzP0 += 160;
					if (horzP1 < 0)
						horzP1 += 160;
					if (horzM0 < 0)
						horzM0 += 160;
					if (horzM1 < 0)
						horzM1 += 160;
					if (horzBL < 0)
						horzBL += 160;
					HMOVE_started_previous = HMOVE_started;
				}
				HMOVE_started = HMOVE_INACTIVE;
				redraw_line = 1;
			}

			/* Redraw line if the playfield reflect bit was changed after the center of the screen */
			if ( REFLECT != ( CTRLPF & 0x01 ) ) {
				REFLECT = CTRLPF & 0x01;
				redraw_line = 1;
			}

			/* Redraw line if a RESPx or NUSIZx occurred during the last line */
			if ( ! startP0 || ! startP1 || ! startM0 || ! startM1) {
				startP0 = 1;
				startP1 = 1;
				startM0 = 1;
				startM1 = 1;

				redraw_line = 1;
			}

			if ( skipclipP0 ) {
				skipclipP0--;
				redraw_line = 1;
			}

			if ( skipclipP1 ) {
				skipclipP1--;
				redraw_line = 1;
			}

			/* Redraw line if HMP0 latch is still set */
			if ( HMP0_latch ) {
				horzP0 -= 17;
				if ( horzP0 < 0 )
					horzP0 += 160;
				redraw_line = 1;
			}

			/* Redraw line if HMP1 latch is still set */
			if ( HMP1_latch ) {
				horzP1 -= 17;
				if ( horzP1 < 0 )
					horzP1 += 160;
				redraw_line = 1;
			}

			/* Redraw line if HMM0 latch is still set */
			if ( HMM0_latch ) {
				horzM0 -= 17;
				if ( horzM0 < 0 )
					horzM0 += 160;
				redraw_line = 1;
			}

			/* Redraw line if HMM1 latch is still set */
			if ( HMM1_latch ) {
				horzM1 -= 17;
				if ( horzM1 < 0 )
					horzM1 += 160;
				redraw_line = 1;
			}

			/* Redraw line if HMBL latch is still set */
			if ( HMBL_latch ) {
				horzBL -= 17;
				if ( horzBL < 0 )
					horzBL += 160;
				redraw_line = 1;
			}

			/* Redraw line if NUSIZx data was changed */
			if ( NUSIZx_changed ) {
				NUSIZx_changed = 0;
				redraw_line = 1;
			}

			if ( skipM0delay || skipM1delay ) {
				skipM0delay = 0;
				skipM1delay = 0;
				redraw_line = 1;
			}

			if ( redraw_line ) {
				if (VBLANK & 2)
				{
					setup_pXgfx();
					memset(temp, 0, 160);
				}
				else
				{
					memset(linePF, 0xFF, sizeof linePF);
					memset(lineP0, 0xFF, sizeof lineP0);
					memset(lineP1, 0xFF, sizeof lineP1);
					memset(lineM0, 0xFF, sizeof lineM0);
					memset(lineM1, 0xFF, sizeof lineM1);
					memset(lineBL, 0xFF, sizeof lineBL);

					memset(temp, COLUBK >> 1, 160);

					setup_pXgfx();

					if (CTRLPF & 4)
					{
						drawS1(temp, lineP1);
						drawM1(temp, lineM1);
						drawS0(temp, lineP0);
						drawM0(temp, lineM0);
						drawPF(temp, linePF);
						drawBL(temp, lineBL);
					}
					else
					{
						drawPF(temp, linePF);
						drawBL(temp, lineBL);
						drawS1(temp, lineP1);
						drawM1(temp, lineM1);
						drawS0(temp, lineP0);
						drawM0(temp, lineM0);
					}
				}
			}
		}
		if (y != prev_y || x1 < 0)
		{
			x1 = 0;
		}
		if (y != next_y || x2 > 160)
		{
			x2 = 160;
		}

		/* Collision detection also takes place under the extended hblank area */
		colx1 = ( x1 == 8 && HMOVE_started != HMOVE_INACTIVE ) ? 0 : x1;

		if (collision_check(lineM0, lineP1, colx1, x2))
			CXM0P |= 0x80;
		if (collision_check(lineM0, lineP0, colx1, x2))
			CXM0P |= 0x40;
		if (collision_check(lineM1, lineP0, colx1, x2))
			CXM1P |= 0x80;
		if (collision_check(lineM1, lineP1, colx1, x2))
			CXM1P |= 0x40;
		if (collision_check(lineP0, linePF, colx1, x2))
			CXP0FB |= 0x80;
		if (collision_check(lineP0, lineBL, colx1, x2))
			CXP0FB |= 0x40;
		if (collision_check(lineP1, linePF, colx1, x2))
			CXP1FB |= 0x80;
		if (collision_check(lineP1, lineBL, colx1, x2))
			CXP1FB |= 0x40;
		if (collision_check(lineM0, linePF, colx1, x2))
			CXM0FB |= 0x80;
		if (collision_check(lineM0, lineBL, colx1, x2))
			CXM0FB |= 0x40;
		if (collision_check(lineM1, linePF, colx1, x2))
			CXM1FB |= 0x80;
		if (collision_check(lineM1, lineBL, colx1, x2))
			CXM1FB |= 0x40;
		if (collision_check(lineBL, linePF, colx1, x2))
			CXBLPF |= 0x80;
		if (collision_check(lineP0, lineP1, colx1, x2))
			CXPPMM |= 0x80;
		if (collision_check(lineM0, lineM1, colx1, x2))
			CXPPMM |= 0x40;

		p = &helper[current_bitmap].pix16(y % screen_height, 34);

		for (x = x1; x < x2; x++)
		{
			p[x] = temp[x];
		}

		if ( x2 == 160 && y % screen_height == (screen_height - 1) ) {
			int t_y;
			for ( t_y = 0; t_y < buffer.height(); t_y++ ) {
				uint16_t* l0 = &helper[current_bitmap].pix16(t_y);
				uint16_t* l1 = &helper[1 - current_bitmap].pix16(t_y);
				uint32_t* l2 = &buffer.pix32(t_y);
				int t_x;
				for( t_x = 0; t_x < buffer.width(); t_x++ ) {
					if ( l0[t_x] != l1[t_x] ) {
						/* Combine both entries */
						l2[t_x] = pen(( ( l0[t_x] + 1 ) << 7 ) | l1[t_x]);
					} else {
						l2[t_x] = pen(l0[t_x]);
					}
				}
			}
			current_bitmap ^= 1;
		}
	}

	prev_x = next_x;
	prev_y = next_y;
}


WRITE8_MEMBER( tia_video_device::WSYNC_w )
{
	int cycles = m_maincpu->total_cycles() - frame_cycles;

	if (cycles % 76)
	{
		m_maincpu->adjust_icount(cycles % 76 - 76);
	}
}


WRITE8_MEMBER( tia_video_device::VSYNC_w )
{
	if (data & 2)
	{
		if (!(VSYNC & 2))
		{
			int curr_y = current_y();

			if ( curr_y > 5 )
				update_bitmap(
					screen().width(),
					screen().height());

			if ( !m_vsync_cb.isnull() ) {
				m_vsync_cb(0, curr_y, 0xFFFF );
			}

			prev_y = 0;
			prev_x = 0;

			frame_cycles += 76 * current_y();
		}
	}

	VSYNC = data;
}


WRITE8_MEMBER( tia_video_device::VBLANK_w )
{
	if (data & 0x80)
	{
		paddle_start = m_maincpu->total_cycles();
	}
	if ( ! ( VBLANK & 0x40 ) ) {
		INPT4 = 0x80;
		INPT5 = 0x80;
	}
	VBLANK = data;
}


WRITE8_MEMBER( tia_video_device::CTRLPF_w )
{
	int curr_x = current_x();

	CTRLPF = data;
	if ( curr_x < 80 ) {
		REFLECT = CTRLPF & 1;
	}
}

WRITE8_MEMBER( tia_video_device::HMP0_w )
{
	int curr_x = current_x();

	data &= 0xF0;

	if ( data == HMP0 )
		return;

	/* Check if HMOVE cycles are still being applied */
	if ( HMOVE_started != HMOVE_INACTIVE && curr_x < std::min( HMOVE_started + 6 + motclkP0 * 4, 7 ) ) {
		int new_motclkP0 = ( data ^ 0x80 ) >> 4;

		/* Check if new horizontal move can still be applied normally */
		if ( new_motclkP0 > motclkP0 || curr_x <= std::min( HMOVE_started + 6 + new_motclkP0 * 4, 7 ) ) {
			horzP0 -= ( new_motclkP0 - motclkP0 );
			motclkP0 = new_motclkP0;
		} else {
			horzP0 -= ( 15 - motclkP0 );
			motclkP0 = 15;
			if ( data != 0x70 && data != 0x80 ) {
				HMP0_latch = 1;
			}
		}
		if ( horzP0 < 0 )
			horzP0 += 160;
		horzP0 %= 160;
		setup_pXgfx();
	}
	HMP0 = data;
}

WRITE8_MEMBER( tia_video_device::HMP1_w )
{
	int curr_x = current_x();

	data &= 0xF0;

	if ( data == HMP1 )
		return;

	/* Check if HMOVE cycles are still being applied */
	if ( HMOVE_started != HMOVE_INACTIVE && curr_x < std::min( HMOVE_started + 6 + motclkP1 * 4, 7 ) ) {
		int new_motclkP1 = ( data ^ 0x80 ) >> 4;

		/* Check if new horizontal move can still be applied normally */
		if ( new_motclkP1 > motclkP1 || curr_x <= std::min( HMOVE_started + 6 + new_motclkP1 * 4, 7 ) ) {
			horzP1 -= ( new_motclkP1 - motclkP1 );
			motclkP1 = new_motclkP1;
		} else {
			horzP1 -= ( 15 - motclkP1 );
			motclkP1 = 15;
			if ( data != 0x70 && data != 0x80 ) {
				HMP1_latch = 1;
			}
		}
		if ( horzP1 < 0 )
			horzP1 += 160;
		horzP1 %= 160;
		setup_pXgfx();
	}
	HMP1 = data;
}

WRITE8_MEMBER( tia_video_device::HMM0_w )
{
	int curr_x = current_x();

	data &= 0xF0;

	if ( data == HMM0 )
		return;

	/* Check if HMOVE cycles are still being applied */
	if ( HMOVE_started != HMOVE_INACTIVE && curr_x < std::min( HMOVE_started + 6 + motclkM0 * 4, 7 ) ) {
		int new_motclkM0 = ( data ^ 0x80 ) >> 4;

		/* Check if new horizontal move can still be applied normally */
		if ( new_motclkM0 > motclkM0 || curr_x <= std::min( HMOVE_started + 6 + new_motclkM0 * 4, 7 ) ) {
			horzM0 -= ( new_motclkM0 - motclkM0 );
			motclkM0 = new_motclkM0;
		} else {
			horzM0 -= ( 15 - motclkM0 );
			motclkM0 = 15;
			if ( data != 0x70 && data != 0x80 ) {
				HMM0_latch = 1;
			}
		}
		if ( horzM0 < 0 )
			horzM0 += 160;
		horzM0 %= 160;
	}
	HMM0 = data;
}

WRITE8_MEMBER( tia_video_device::HMM1_w )
{
	int curr_x = current_x();

	data &= 0xF0;

	if ( data == HMM1 )
		return;

	/* Check if HMOVE cycles are still being applied */
	if ( HMOVE_started != HMOVE_INACTIVE && curr_x < std::min( HMOVE_started + 6 + motclkM1 * 4, 7 ) ) {
		int new_motclkM1 = ( data ^ 0x80 ) >> 4;

		/* Check if new horizontal move can still be applied normally */
		if ( new_motclkM1 > motclkM1 || curr_x <= std::min( HMOVE_started + 6 + new_motclkM1 * 4, 7 ) ) {
			horzM1 -= ( new_motclkM1 - motclkM1 );
			motclkM1 = new_motclkM1;
		} else {
			horzM1 -= ( 15 - motclkM1 );
			motclkM1 = 15;
			if ( data != 0x70 && data != 0x80 ) {
				HMM1_latch = 1;
			}
		}
		if ( horzM1 < 0 )
			horzM1 += 160;
		horzM1 %= 160;
	}
	HMM1 = data;
}

WRITE8_MEMBER( tia_video_device::HMBL_w )
{
	int curr_x = current_x();

	data &= 0xF0;

	if ( data == HMBL )
		return;

	/* Check if HMOVE cycles are still being applied */
	if ( HMOVE_started != HMOVE_INACTIVE && curr_x < std::min( HMOVE_started + 6 + motclkBL * 4, 7 ) ) {
		int new_motclkBL = ( data ^ 0x80 ) >> 4;

		/* Check if new horizontal move can still be applied normally */
		if ( new_motclkBL > motclkBL || curr_x <= std::min( HMOVE_started + 6 + new_motclkBL * 4, 7 ) ) {
			horzBL -= ( new_motclkBL - motclkBL );
			motclkBL = new_motclkBL;
		} else {
			horzBL -= ( 15 - motclkBL );
			motclkBL = 15;
			if ( data != 0x70 && data != 0x80 ) {
				HMBL_latch = 1;
			}
		}
		if ( horzBL < 0 )
			horzBL += 160;
		horzBL %= 160;
	}
	HMBL = data;
}

WRITE8_MEMBER( tia_video_device::HMOVE_w )
{
	int curr_x = current_x();
	int curr_y = current_y();

	HMOVE_started = curr_x;

	/* Check if we have to undo some of the already applied cycles from an active graphics latch */
	if ( curr_x + 68 < 17 * 4 ) {
		int cycle_fix = 17 - ( ( curr_x + 68 + 7 ) / 4 );
		if ( HMP0_latch )
			horzP0 = ( horzP0 + cycle_fix ) % 160;
		if ( HMP1_latch )
			horzP1 = ( horzP1 + cycle_fix ) % 160;
		if ( HMM0_latch )
			horzM0 = ( horzM0 + cycle_fix ) % 160;
		if ( HMM1_latch )
			horzM1 = ( horzM1 + cycle_fix ) % 160;
		if ( HMBL_latch )
			horzBL = ( horzBL + cycle_fix ) % 160;
	}

	HMP0_latch = 0;
	HMP1_latch = 0;
	HMM0_latch = 0;
	HMM1_latch = 0;
	HMBL_latch = 0;

	/* Check if HMOVE activities can be ignored */
	if ( curr_x >= -5 && curr_x < 97 ) {
		motclkP0 = 0;
		motclkP1 = 0;
		motclkM0 = 0;
		motclkM1 = 0;
		motclkBL = 0;
		HMOVE_started = HMOVE_INACTIVE;
		return;
	}

	motclkP0 = ( HMP0 ^ 0x80 ) >> 4;
	motclkP1 = ( HMP1 ^ 0x80 ) >> 4;
	motclkM0 = ( HMM0 ^ 0x80 ) >> 4;
	motclkM1 = ( HMM1 ^ 0x80 ) >> 4;
	motclkBL = ( HMBL ^ 0x80 ) >> 4;

	/* Adjust number of graphics motion clocks for active display */
	if ( curr_x >= 97 && curr_x < 151 ) {
		int skip_motclks = ( 160 - HMOVE_started - 6 ) / 4;
		motclkP0 -= skip_motclks;
		motclkP1 -= skip_motclks;
		motclkM0 -= skip_motclks;
		motclkM1 -= skip_motclks;
		motclkBL -= skip_motclks;
		if ( motclkP0 < 0 )
			motclkP0 = 0;
		if ( motclkP1 < 0 )
			motclkP1 = 0;
		if ( motclkM0 < 0 )
			motclkM0 = 0;
		if ( motclkM1 < 0 )
			motclkM1 = 0;
		if ( motclkBL < 0 )
			motclkBL = 0;
	}

	if ( curr_x >= -56 && curr_x < -5 ) {
		int max_motclks = ( 7 - ( HMOVE_started + 5 ) ) / 4;
		if ( motclkP0 > max_motclks )
			motclkP0 = max_motclks;
		if ( motclkP1 > max_motclks )
			motclkP1 = max_motclks;
		if ( motclkM0 > max_motclks )
			motclkM0 = max_motclks;
		if ( motclkM1 > max_motclks )
			motclkM1 = max_motclks;
		if ( motclkBL > max_motclks )
			motclkBL = max_motclks;
	}

	/* Apply horizontal motion */
	if ( curr_x < -5 || curr_x >= 157 ) {
		horzP0 += 8 - motclkP0;
		horzP1 += 8 - motclkP1;
		horzM0 += 8 - motclkM0;
		horzM1 += 8 - motclkM1;
		horzBL += 8 - motclkBL;

		if (horzP0 < 0)
			horzP0 += 160;
		if (horzP1 < 0)
			horzP1 += 160;
		if (horzM0 < 0)
			horzM0 += 160;
		if (horzM1 < 0)
			horzM1 += 160;
		if (horzBL < 0)
			horzBL += 160;

		horzP0 %= 160;
		horzP1 %= 160;
		horzM0 %= 160;
		horzM1 %= 160;
		horzBL %= 160;

		/* When HMOVE is triggered on CPU cycle 75, the HBlank period on the
		   next line is also extended. */
		if (curr_x >= 157)
		{
			curr_y += 1;
			update_bitmap( -8, curr_y );
		}
		else
		{
			setup_pXgfx();
		}
		if (curr_y < screen_height)
		{
			memset(&helper[current_bitmap].pix16(curr_y, 34), 0, 16);
		}

		prev_x = 8;
	}
}


WRITE8_MEMBER( tia_video_device::RSYNC_w )
{
	/* this address is used in chip testing */
}


WRITE8_MEMBER( tia_video_device::NUSIZ0_w )
{
	int curr_x = current_x();

	/* Check if relevant bits have changed */
	if ( ( data & 7 ) != ( NUSIZ0 & 7 ) ) {
		int i;
		/* Check if we are (about to start) drawing a copy of the player 0 graphics */
		for ( i = 0; i < PLAYER_GFX_SLOTS; i++ ) {
			if ( p0gfx.start_pixel[i] < 8 ) {
				int min_x = p0gfx.start_drawing[i];
				int size = ( 8 - p0gfx.start_pixel[i] ) * p0gfx.size[i];
				if ( curr_x >= ( min_x - 5 ) % 160 && curr_x < ( min_x + size ) % 160 ) {
					if ( curr_x >= min_x % 160 || p0gfx.start_pixel[i] != 0 ) {
						/* This copy has started drawing */
						if ( p0gfx.size[i] == 1 && nusiz[data & 7][1] > 1 ) {
							int delay = 1 + ( ( p0gfx.start_pixel[i] + ( curr_x - p0gfx.start_drawing[i] ) ) & 1 );
							update_bitmap( curr_x + delay, current_y() );
							p0gfx.start_pixel[i] += ( curr_x + delay - p0gfx.start_drawing[i] );
							if ( p0gfx.start_pixel[i] > 8 )
								p0gfx.start_pixel[i] = 8;
							p0gfx.start_drawing[i] = curr_x + delay;
						} else if ( p0gfx.size[1] > 1 && nusiz[data & 7][1] == 1 ) {
							int delay = ( curr_x - p0gfx.start_drawing[i] ) & ( p0gfx.size[i] - 1 );
							if ( delay ) {
								delay = p0gfx.size[i] - delay;
							}
							update_bitmap( curr_x + delay, current_y() );
							p0gfx.start_pixel[i] += ( curr_x - p0gfx.start_drawing[i] ) / p0gfx.size[i];
							p0gfx.start_drawing[i] = curr_x + delay;
						} else {
							p0gfx.start_pixel[i] += ( curr_x - p0gfx.start_drawing[i] ) / p0gfx.size[i];
							p0gfx.start_drawing[i] = curr_x;
						}
						p0gfx.size[i] = nusiz[data & 7][1];
					} else {
						/* This copy was just about to start drawing (meltdown) */
						/* Adjust for 1 clock delay between zoomed and non-zoomed sprites */
						if ( p0gfx.size[i] == 1 && nusiz[data & 7][1] > 1 ) {
							/* Check for hardware oddity */
							if ( p0gfx.start_drawing[i] - curr_x == 2 ) {
								p0gfx.start_drawing[i]--;
							} else {
								p0gfx.start_drawing[i]++;
							}
						} else if ( p0gfx.size[i] > 1 && nusiz[data & 7][1] == 1 ) {
							p0gfx.start_drawing[i]--;
						}
						p0gfx.size[i] = nusiz[data & 7][1];
					}
				} else {
					/* We are passed the copy or the copy still needs to be done. Mark
					   it as done/invalid, the data will be reset in the next loop. */
					p0gfx.start_pixel[i] = 8;
				}
			}
		}
		/* Apply NUSIZ updates to not yet drawn copies */
		for ( i = ( startP0 ? 0 : 1 ); i < nusiz[data & 7][0]; i++ ) {
			int j;
			/* Find an unused p0gfx entry */
			for ( j = 0; j < PLAYER_GFX_SLOTS; j++ ) {
				if ( p0gfx.start_pixel[j] == 8 )
					break;
			}
			p0gfx.size[j] = nusiz[data & 7][1];
			p0gfx.start_drawing[j] = ( horzP0 + (p0gfx.size[j] > 1 ? 1 : 0)
									+ i * 8 * ( nusiz[data & 7][2] + p0gfx.size[j] ) ) % 160;
			if ( curr_x < p0gfx.start_drawing[j] % 160 ) {
				p0gfx.start_pixel[j] = 0;
			}
		}
		NUSIZx_changed = 1;
	}
	NUSIZ0 = data;
}


WRITE8_MEMBER( tia_video_device::NUSIZ1_w )
{
	int curr_x = current_x();

	/* Check if relevant bits have changed */
	if ( ( data & 7 ) != ( NUSIZ1 & 7 ) ) {
		int i;
		/* Check if we are (about to start) drawing a copy of the player 1 graphics */
		for ( i = 0; i < PLAYER_GFX_SLOTS; i++ ) {
			if ( p1gfx.start_pixel[i] < 8 ) {
				int min_x = p1gfx.start_drawing[i];
				int size = ( 8 - p1gfx.start_pixel[i] ) * p1gfx.size[i];
				if ( curr_x >= ( min_x - 5 ) % 160 && curr_x < ( min_x + size ) % 160 ) {
					if ( curr_x >= min_x % 160 || p1gfx.start_pixel[i] != 0 ) {
						/* This copy has started drawing */
						if ( p1gfx.size[i] == 1 && nusiz[data & 7][1] > 1 ) {
							int delay = 1 + ( ( p0gfx.start_pixel[i] + ( curr_x - p0gfx.start_drawing[i] ) ) & 1 );
							update_bitmap( curr_x + delay, current_y() );
							p1gfx.start_pixel[i] += ( curr_x + delay - p1gfx.start_drawing[i] );
							if ( p1gfx.start_pixel[i] > 8 )
								p1gfx.start_pixel[i] = 8;
							p1gfx.start_drawing[i] = curr_x + delay;
						} else if ( p1gfx.size[1] > 1 && nusiz[data & 7][1] == 1 ) {
							int delay = ( curr_x - p1gfx.start_drawing[i] ) & ( p1gfx.size[i] - 1 );
							if ( delay ) {
								delay = p1gfx.size[i] - delay;
							}
							update_bitmap( curr_x + delay, current_y() );
							p1gfx.start_pixel[i] += ( curr_x - p1gfx.start_drawing[i] ) / p1gfx.size[i];
							p1gfx.start_drawing[i] = curr_x + delay;
						} else {
							p1gfx.start_pixel[i] += ( curr_x - p1gfx.start_drawing[i] ) / p1gfx.size[i];
							p1gfx.start_drawing[i] = curr_x;
						}
						p1gfx.size[i] = nusiz[data & 7][1];
					} else {
						/* This copy was just about to start drawing (meltdown) */
						/* Adjust for 1 clock delay between zoomed and non-zoomed sprites */
						if ( p1gfx.size[i] == 1 && nusiz[data & 7][1] > 1 ) {
							/* Check for hardware oddity */
							if ( p1gfx.start_drawing[i] - curr_x == 2 ) {
								p1gfx.start_drawing[i]--;
							} else {
								p1gfx.start_drawing[i]++;
							}
						} else if ( p1gfx.size[i] > 1 && nusiz[data & 7][1] == 1 ) {
							p1gfx.start_drawing[i]--;
						}
						p1gfx.size[i] = nusiz[data & 7][1];
					}
				} else {
					/* We are passed the copy or the copy still needs to be done. Mark
					   it as done/invalid, the data will be reset in the next loop. */
					p1gfx.start_pixel[i] = 8;
				}
			}
		}
		/* Apply NUSIZ updates to not yet drawn copies */
		for ( i = ( startP1 ? 0 : 1 ); i < nusiz[data & 7][0]; i++ ) {
			int j;
			/* Find an unused p1gfx entry */
			for ( j = 0; j < PLAYER_GFX_SLOTS; j++ ) {
				if ( p1gfx.start_pixel[j] == 8 )
					break;
			}
			p1gfx.size[j] = nusiz[data & 7][1];
			p1gfx.start_drawing[j] = ( horzP1 + (p1gfx.size[j] > 1 ? 1 : 0)
									+ i * 8 * ( nusiz[data & 7][2] + p1gfx.size[j] ) ) % 160;
			if ( curr_x < p1gfx.start_drawing[j] % 160 ) {
				p1gfx.start_pixel[j] = 0;
			}
		}
		NUSIZx_changed = 1;
	}
	NUSIZ1 = data;
}


WRITE8_MEMBER( tia_video_device::HMCLR_w )
{
	HMP0_w( space, offset, 0 );
	HMP1_w( space, offset, 0 );
	HMM0_w( space, offset, 0 );
	HMM1_w( space, offset, 0 );
	HMBL_w( space, offset, 0 );
}


WRITE8_MEMBER( tia_video_device::CXCLR_w )
{
	CXM0P = 0;
	CXM1P = 0;
	CXP0FB = 0;
	CXP1FB = 0;
	CXM0FB = 0;
	CXM1FB = 0;
	CXBLPF = 0;
	CXPPMM = 0;
}


#define RESXX_APPLY_ACTIVE_HMOVE(HORZ,MOTION,MOTCLK)                                    \
	if ( curr_x < std::min( HMOVE_started + 6 + 16 * 4, 7 ) ) {                              \
		int decrements_passed = ( curr_x - ( HMOVE_started + 4 ) ) / 4;                 \
		HORZ += 8;                                                                      \
		if ( ( MOTCLK - decrements_passed ) > 0 ) {                                     \
			HORZ -= ( MOTCLK - decrements_passed );                                     \
			if ( HORZ < 0 )                                                             \
				HORZ += 160;                                                            \
		}                                                                               \
	}

#define RESXX_APPLY_PREVIOUS_HMOVE(HORZ,MOTION)                                             \
	if ( HMOVE_started_previous != HMOVE_INACTIVE )                                         \
	{                                                                                       \
		uint8_t   motclk = ( MOTION ^ 0x80 ) >> 4;                                            \
		if ( curr_x <= HMOVE_started_previous - 228 + 5 + motclk * 4 )                      \
		{                                                                                   \
			uint8_t   motclk_passed = ( curr_x - ( HMOVE_started_previous - 228 + 6 ) ) / 4;  \
			HORZ -= ( motclk - motclk_passed );                                             \
		}                                                                                   \
	}

WRITE8_MEMBER( tia_video_device::RESP0_w )
{
	int curr_x = current_x();
	int new_horzP0;

	/* Check if HMOVE is activated during this line */
	if ( HMOVE_started != HMOVE_INACTIVE ) {
		new_horzP0 = ( curr_x < 7 ) ? 3 : ( curr_x + 5 );
		/* If HMOVE is active, adjust for remaining horizontal move clocks if any */
		RESXX_APPLY_ACTIVE_HMOVE( new_horzP0, HMP0, motclkP0 );
	} else {
		new_horzP0 = ( curr_x < -2 ) ? 3 : ( curr_x + 5 );
		RESXX_APPLY_PREVIOUS_HMOVE( new_horzP0, HMP0 );
	}

	if ( new_horzP0 != horzP0 ) {
		int i;
		horzP0 = new_horzP0;
		startP0 = 0;
		skipclipP0 = 2;
		/* Check if we are (about to start) drawing a copy of the player 0 graphics */
		for ( i = 0; i < PLAYER_GFX_SLOTS; i++ ) {
			if ( p0gfx.start_pixel[i] < 8 ) {
				int min_x = p0gfx.start_drawing[i];
				int size = ( 8 - p0gfx.start_pixel[i] ) * p0gfx.size[i];
				if ( curr_x >= ( min_x - 5 ) % 160 && curr_x < ( min_x + size ) % 160 ) {
					if ( curr_x >= min_x ) {
						/* This copy has started drawing */
						p0gfx.start_pixel[i] += ( curr_x - p0gfx.start_drawing[i] ) / p0gfx.size[i];
						p0gfx.start_drawing[i] = curr_x;
					} else {
						/* This copy is waiting to start drawing */
						p0gfx.start_drawing[i] = horzP0;
					}
				} else {
					/* We are passed the copy or the copy still needs to be done. Mark
					   it as done/invalid, the data will be reset in the next loop. */
					p0gfx.start_pixel[i] = 8;
				}
			}
		}
		/* Apply NUSIZ and position updates to not yet drawn copies */
		for ( i = 1; i < nusiz[NUSIZ0 & 7][0]; i++ ) {
			int j;
			/* Find an unused p0gfx entry */
			for ( j = 0; j < PLAYER_GFX_SLOTS; j++ ) {
				if ( p0gfx.start_pixel[j] == 8 )
					break;
			}
			p0gfx.size[j] = nusiz[NUSIZ0 & 7][1];
			p0gfx.start_drawing[j] = ( horzP0 + (p0gfx.size[j] > 1 ? 1 : 0)
									+ i * 8 * ( nusiz[NUSIZ0 & 7][2] + p0gfx.size[j] ) ) % 160;
			if ( curr_x < p0gfx.start_drawing[j] % 160 ) {
				p0gfx.start_pixel[j] = 0;
			}
		}
	}
}


WRITE8_MEMBER( tia_video_device::RESP1_w )
{
	int curr_x = current_x();
	int new_horzP1;

	/* Check if HMOVE is activated during this line */
	if ( HMOVE_started != HMOVE_INACTIVE ) {
		new_horzP1 = ( curr_x < 7 ) ? 3 : ( curr_x + 5 );
		/* If HMOVE is active, adjust for remaining horizontal move clocks if any */
		RESXX_APPLY_ACTIVE_HMOVE( new_horzP1, HMP1, motclkP1 );
	} else {
		new_horzP1 = ( curr_x < -2 ) ? 3 : ( curr_x + 5 );
		RESXX_APPLY_PREVIOUS_HMOVE( new_horzP1, HMP1 );
	}

	if ( new_horzP1 != horzP1 ) {
		int i;
		horzP1 = new_horzP1;
		startP1 = 0;
		skipclipP1 = 2;
		/* Check if we are (about to start) drawing a copy of the player 1 graphics */
		for ( i = 0; i < PLAYER_GFX_SLOTS; i++ ) {
			if ( p1gfx.start_pixel[i] < 8 ) {
				int min_x = p1gfx.start_drawing[i];
				int size = ( 8 - p1gfx.start_pixel[i] ) * p1gfx.size[i];
				if ( curr_x >= ( min_x - 5 ) % 160 && curr_x < ( min_x + size ) % 160 ) {
					if ( curr_x >= min_x ) {
						/* This copy has started drawing */
						p1gfx.start_pixel[i] += ( curr_x - p1gfx.start_drawing[i] ) / p1gfx.size[i];
						p1gfx.start_drawing[i] = curr_x;
					} else {
						/* This copy is waiting to start drawing */
						p1gfx.start_drawing[i] = horzP1;
					}
				} else {
					/* We are passed the copy or the copy still needs to be done. Mark
					   it as done/invalid, the data will be reset in the next loop. */
					p1gfx.start_pixel[i] = 8;
				}
			}
		}
		/* Apply NUSIZ and position updates to not yet drawn copies */
		for ( i = 1; i < nusiz[NUSIZ1 & 7][0]; i++ ) {
			int j;
			/* Find an unused p1gfx entry */
			for ( j = 0; j < PLAYER_GFX_SLOTS; j++ ) {
				if ( p1gfx.start_pixel[j] == 8 )
					break;
			}
			p1gfx.size[j] = nusiz[NUSIZ1 & 7][1];
			p1gfx.start_drawing[j] = ( horzP1 + (p1gfx.size[j] > 1 ? 1 : 0)
									+ i * 8 * ( nusiz[NUSIZ1 & 7][2] + p1gfx.size[j] ) ) % 160;
			if ( curr_x < p1gfx.start_drawing[j] % 160 ) {
				p1gfx.start_pixel[j] = 0;
			}
		}
	}
}


WRITE8_MEMBER( tia_video_device::RESM0_w )
{
	int curr_x = current_x();
	int new_horzM0;

	/* Check if HMOVE is activated during this line */
	if ( HMOVE_started != HMOVE_INACTIVE ) {
		new_horzM0 = ( curr_x < 7 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		/* If HMOVE is active, adjust for remaining horizontal move clocks if any */
		RESXX_APPLY_ACTIVE_HMOVE( new_horzM0, HMM0, motclkM0 );
	} else {
		new_horzM0 = ( curr_x < -1 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		skipM0delay = ( curr_x < -1 && horzM0 % 160 >= 0 && horzM0 % 160 < 1 ) ? 4 : 0;
		RESXX_APPLY_PREVIOUS_HMOVE( new_horzM0, HMM0 );
	}
	if ( new_horzM0 != horzM0 ) {
		startM0 = skipM0delay ? 1 : 0;
		horzM0 = new_horzM0;
	}
}


WRITE8_MEMBER( tia_video_device::RESM1_w )
{
	int curr_x = current_x();
	int new_horzM1;

	/* Check if HMOVE is activated during this line */
	if ( HMOVE_started != HMOVE_INACTIVE ) {
		new_horzM1 = ( curr_x < 7 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		/* If HMOVE is active, adjust for remaining horizontal move clocks if any */
		RESXX_APPLY_ACTIVE_HMOVE( new_horzM1, HMM1, motclkM1 );
	} else {
		new_horzM1 = ( curr_x < -1 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		skipM1delay = ( curr_x < -1 && horzM1 % 160 >= 0 && horzM1 % 160 < 1 ) ? 4 : 0;
		RESXX_APPLY_PREVIOUS_HMOVE( new_horzM1, HMM1 );
	}
	if ( new_horzM1 != horzM1 ){
		startM1 = skipM1delay ? 1 : 0;
		horzM1 = new_horzM1;
	}
}


WRITE8_MEMBER( tia_video_device::RESBL_w )
{
	int curr_x = current_x();

	/* Check if HMOVE is activated during this line */
	if ( HMOVE_started != HMOVE_INACTIVE ) {
		horzBL = ( curr_x < 7 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		/* If HMOVE is active, adjust for remaining horizontal move clocks if any */
		RESXX_APPLY_ACTIVE_HMOVE( horzBL, HMBL, motclkBL );
	} else {
		horzBL = ( curr_x < 0 ) ? 2 : ( ( curr_x + 4 ) % 160 );
		RESXX_APPLY_PREVIOUS_HMOVE( horzBL, HMBL );
	}
}


WRITE8_MEMBER( tia_video_device::RESMP0_w )
{
	if (RESMP0 & 2)
	{
		if ( nusiz[NUSIZ0 & 7][1] > 1 ) {
			horzM0 = horzP0 + 3 * nusiz[NUSIZ0 & 7][1] - 1;
		} else {
			horzM0 = horzP0 + 4 * nusiz[NUSIZ0 & 7][1];
		}
		if ( HMOVE_started != HMOVE_INACTIVE ) {
			horzM0 -= ( 8 - motclkP0 );
			horzM0 += 8 - motclkM0;
			if ( horzM0 < 0 )
				horzM0 += 160;
		}
		horzM0 %= 160;
	}

	RESMP0 = data;
}


WRITE8_MEMBER( tia_video_device::RESMP1_w )
{
	if (RESMP1 & 2)
	{
		if ( nusiz[NUSIZ1 & 7][1] > 1 ) {
			horzM1 = horzP1 + 3 * nusiz[NUSIZ1 & 7][1] - 1;
		} else {
			horzM1 = horzP1 + 4 * nusiz[NUSIZ1 & 7][1];
		}
		if ( HMOVE_started != HMOVE_INACTIVE ) {
			horzM1 -= ( 8 - motclkP1 );
			horzM1 += 8 - motclkM1;
			if ( horzM1 < 0 )
				horzM1 += 160;
		}
		horzM1 %= 160;
	}

	RESMP1 = data;
}


WRITE8_MEMBER( tia_video_device::GRP0_w )
{
	prevGRP1 = GRP1;

	GRP0 = data;
}


WRITE8_MEMBER( tia_video_device::GRP1_w )
{
	prevGRP0 = GRP0;

	GRP1 = data;

	prevENABL = ENABL;
}


READ8_MEMBER( tia_video_device::INPT_r )
{
	uint64_t elapsed = m_maincpu->total_cycles() - paddle_start;
	uint16_t input = TIA_INPUT_PORT_ALWAYS_ON;
	if ( !m_read_input_port_cb.isnull() )
	{
		input = m_read_input_port_cb(offset & 3, 0xFFFF);
	}

	if ( input == TIA_INPUT_PORT_ALWAYS_ON )
		return 0x80;
	if ( input == TIA_INPUT_PORT_ALWAYS_OFF )
		return 0x00;

	uint16_t paddle_cycles = input * 76;
	return elapsed > paddle_cycles ? 0x80 : 0x00;
}


READ8_MEMBER( tia_video_device::read )
{
		/* lower bits 0 - 5 seem to depend on the last byte on the
		 data bus. If the driver supplied a routine to retrieve
		 that we will call that, otherwise we will use the lower
		 bit of the offset.
	*/
	uint8_t data = offset & 0x3f;

	if ( !m_databus_contents_cb.isnull() )
	{
		data = m_databus_contents_cb(offset) & 0x3f;
	}

	if (!(offset & 0x8))
	{
		update_bitmap(current_x(), current_y());
	}

	switch (offset & 0xF)
	{
	case 0x0:
		return data | CXM0P;
	case 0x1:
		return data | CXM1P;
	case 0x2:
		return data | CXP0FB;
	case 0x3:
		return data | CXP1FB;
	case 0x4:
		return data | CXM0FB;
	case 0x5:
		return data | CXM1FB;
	case 0x6:
		return data | CXBLPF;
	case 0x7:
		return data | CXPPMM;
	case 0x8:
		return data | INPT_r(space,0);
	case 0x9:
		return data | INPT_r(space,1);
	case 0xA:
		return data | INPT_r(space,2);
	case 0xB:
		return data | INPT_r(space,3);
	case 0xC:
		{
			int button = !m_read_input_port_cb.isnull() ? ( m_read_input_port_cb(4,0xFFFF) & 0x80 ) : 0x80;
			INPT4 = ( VBLANK & 0x40) ? ( INPT4 & button ) : button;
		}
		return data | INPT4;
	case 0xD:
		{
			int button = !m_read_input_port_cb.isnull() ? ( m_read_input_port_cb(5,0xFFFF) & 0x80 ) : 0x80;
			INPT5 = ( VBLANK & 0x40) ? ( INPT5 & button ) : button;
		}
		return data | INPT5;
	}

	return data;
}


WRITE8_MEMBER( tia_video_device::write )
{
	static const int delay[0x40] =
	{
			0,  // VSYNC
			0,  // VBLANK
			0,  // WSYNC
			0,  // RSYNC
			0,  // NUSIZ0
			0,  // NUSIZ1
			0,  // COLUP0
			0,  // COLUP1
			0,  // COLUPF
			0,  // COLUBK
			0,  // CTRLPF
			1,  // REFP0
			1,  // REFP1
			4,  // PF0
			4,  // PF1
			4,  // PF2
			0,  // RESP0
			0,  // RESP1
			0,  // RESM0
			0,  // RESM1
			0,  // RESBL
		-1, // AUDC0
		-1, // AUDC1
		-1, // AUDF0
		-1, // AUDF1
		-1, // AUDV0
		-1, // AUDV1
			1,  // GRP0
			1,  // GRP1
			1,  // ENAM0
			1,  // ENAM1
			1,  // ENABL
			0,  // HMP0
			0,  // HMP1
			0,  // HMM0
			0,  // HMM1
			0,  // HMBL
			0,  // VDELP0
			0,  // VDELP1
			0,  // VDELBL
			0,  // RESMP0
			0,  // RESMP1
			3,  // HMOVE
			0,  // HMCLR
			0,  // CXCLR
	};
	int curr_x = current_x();
	int curr_y = current_y();

	offset &= 0x3F;

	if (offset >= 0x0D && offset <= 0x0F)
	{
		curr_x = ( curr_x + 1 ) & ~3;
	}

	if (delay[offset] >= 0)
	{
		update_bitmap(curr_x + delay[offset], curr_y);
	}

	switch (offset)
	{
	case 0x00:
		VSYNC_w(space, offset, data);
		break;
	case 0x01:
		VBLANK_w(space, offset, data);
		break;
	case 0x02:
		WSYNC_w(space, offset, data);
		break;
	case 0x03:
		RSYNC_w(space, offset, data);
		break;
	case 0x04:
		NUSIZ0_w(space, offset, data);
		break;
	case 0x05:
		NUSIZ1_w(space, offset, data);
		break;
	case 0x06:
		COLUP0 = data;
		break;
	case 0x07:
		COLUP1 = data;
		break;
	case 0x08:
		COLUPF = data;
		break;
	case 0x09:
		COLUBK = data;
		break;
	case 0x0A:
		CTRLPF_w(space, offset, data);
		break;
	case 0x0B:
		REFP0 = data;
		break;
	case 0x0C:
		REFP1 = data;
		break;
	case 0x0D:
		PF0 = data;
		break;
	case 0x0E:
		PF1 = data;
		break;
	case 0x0F:
		PF2 = data;
		break;
	case 0x10:
		RESP0_w(space, offset, data);
		break;
	case 0x11:
		RESP1_w(space, offset, data);
		break;
	case 0x12:
		RESM0_w(space, offset, data);
		break;
	case 0x13:
		RESM1_w(space, offset, data);
		break;
	case 0x14:
		RESBL_w(space, offset, data);
		break;

	case 0x15: /* AUDC0 */
	case 0x16: /* AUDC1 */
	case 0x17: /* AUDF0 */
	case 0x18: /* AUDF1 */
	case 0x19: /* AUDV0 */
	case 0x1A: /* AUDV1 */
		m_tia->tia_sound_w(space, offset, data);
		break;

	case 0x1B:
		GRP0_w(space, offset, data);
		break;
	case 0x1C:
		GRP1_w(space, offset, data);
		break;
	case 0x1D:
		ENAM0 = data;
		break;
	case 0x1E:
		ENAM1 = data;
		break;
	case 0x1F:
		ENABL = data;
		break;
	case 0x20:
		HMP0_w(space, offset, data);
		break;
	case 0x21:
		HMP1_w(space, offset, data);
		break;
	case 0x22:
		HMM0_w(space, offset, data);
		break;
	case 0x23:
		HMM1_w(space, offset, data);
		break;
	case 0x24:
		HMBL_w(space, offset, data);
		break;
	case 0x25:
		VDELP0 = data;
		break;
	case 0x26:
		VDELP1 = data;
		break;
	case 0x27:
		VDELBL = data;
		break;
	case 0x28:
		RESMP0_w(space, offset, data);
		break;
	case 0x29:
		RESMP1_w(space, offset, data);
		break;
	case 0x2A:
		HMOVE_w(space, offset, data);
		break;
	case 0x2B:
		HMCLR_w(space, offset, data);
		break;
	case 0x2C:
		CXCLR_w(space, offset, 0);
		break;
	}
}


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

void tia_video_device::device_reset()
{
	int i;

	frame_cycles = 0;

	INPT4 = 0x80;
	INPT5 = 0x80;

	HMP0 = 0;
	HMP1 = 0;
	HMM0 = 0;
	HMM1 = 0;
	HMBL = 0;

	startP0 = 1;
	startP1 = 1;

	HMP0_latch = 0;
	HMP1_latch = 0;
	HMM0_latch = 0;
	HMM1_latch = 0;
	HMBL_latch = 0;

	startM0 = 1;
	startM1 = 1;
	skipM0delay = 0;
	skipM1delay = 0;

	REFLECT = 0;

	prev_x = 0;
	prev_y = 0;

	HMOVE_started = HMOVE_INACTIVE;

	motclkP0 = 0;
	motclkP1 = 0;
	motclkM0 = 0;
	motclkM1 = 0;
	motclkBL = 0;

	horzP0 = 0;
	horzP1 = 0;

	for( i = 0; i < PLAYER_GFX_SLOTS; i++ )
	{
		p0gfx.start_pixel[i] = 8;
		p0gfx.size[i] = 1;
		p1gfx.start_pixel[i] = 8;
		p1gfx.size[i] = 1;
	}

	current_bitmap = 0;

	NUSIZx_changed = 0;

	VBLANK = 0;
	CTRLPF = 0;
	PF0 = 0;
	PF1 = 0;
	PF2 = 0;
	VDELBL = 0;
	prevENABL = 0;
	ENABL = 0;
	VDELP0 = 0;
	VDELP1 = 0;
	prevGRP0 = 0;
	GRP0 = 0;
	prevGRP1 = 0;
	GRP1 = 0;
	COLUP0 = 0;
	COLUP1 = 0;
	REFP0 = 0;
	REFP1 = 0;
	NUSIZ0 = 0;
	NUSIZ1 = 0;
	horzM0 = 0;
	horzM1 = 0;
	RESMP0 = 0;
	RESMP1 = 0;
	ENAM0 = 0;
	ENAM1 = 0;
	skipclipP0 = 0;
	skipclipP1 = 0;
	horzBL = 0;
	VSYNC = 0;
	CXM0P = 0;
	COLUBK = 0;
	COLUPF = 0;
}


void tia_video_device::register_save_state()
{
	save_item(NAME(p0gfx.start_pixel));
	save_item(NAME(p0gfx.start_drawing));
	save_item(NAME(p0gfx.size));
	save_item(NAME(p0gfx.skipclip));
	save_item(NAME(p1gfx.start_pixel));
	save_item(NAME(p1gfx.start_drawing));
	save_item(NAME(p1gfx.size));
	save_item(NAME(p1gfx.skipclip));
	save_item(NAME(frame_cycles));
	save_item(NAME(paddle_start));
	save_item(NAME(horzP0));
	save_item(NAME(horzP1));
	save_item(NAME(horzM0));
	save_item(NAME(horzM1));
	save_item(NAME(horzBL));
	save_item(NAME(motclkP0));
	save_item(NAME(motclkP1));
	save_item(NAME(motclkM0));
	save_item(NAME(motclkM1));
	save_item(NAME(motclkBL));
	save_item(NAME(startP0));
	save_item(NAME(startP1));
	save_item(NAME(startM0));
	save_item(NAME(startM1));
	save_item(NAME(skipclipP0));
	save_item(NAME(skipclipP1));
	save_item(NAME(skipM0delay));
	save_item(NAME(skipM1delay));
	save_item(NAME(current_bitmap));
	save_item(NAME(prev_x));
	save_item(NAME(prev_y));
	save_item(NAME(VSYNC));
	save_item(NAME(VBLANK));
	save_item(NAME(COLUP0));
	save_item(NAME(COLUP1));
	save_item(NAME(COLUBK));
	save_item(NAME(COLUPF));
	save_item(NAME(CTRLPF));
	save_item(NAME(GRP0));
	save_item(NAME(GRP1));
	save_item(NAME(REFP0));
	save_item(NAME(REFP1));
	save_item(NAME(HMP0));
	save_item(NAME(HMP1));
	save_item(NAME(HMM0));
	save_item(NAME(HMM1));
	save_item(NAME(HMBL));
	save_item(NAME(VDELP0));
	save_item(NAME(VDELP1));
	save_item(NAME(VDELBL));
	save_item(NAME(NUSIZ0));
	save_item(NAME(NUSIZ1));
	save_item(NAME(ENAM0));
	save_item(NAME(ENAM1));
	save_item(NAME(ENABL));
	save_item(NAME(CXM0P));
	save_item(NAME(CXM1P));
	save_item(NAME(CXP0FB));
	save_item(NAME(CXP1FB));
	save_item(NAME(CXM0FB));
	save_item(NAME(CXM1FB));
	save_item(NAME(CXBLPF));
	save_item(NAME(CXPPMM));
	save_item(NAME(RESMP0));
	save_item(NAME(RESMP1));
	save_item(NAME(PF0));
	save_item(NAME(PF1));
	save_item(NAME(PF2));
	save_item(NAME(INPT4));
	save_item(NAME(INPT5));
	save_item(NAME(prevGRP0));
	save_item(NAME(prevGRP1));
	save_item(NAME(prevENABL));
	save_item(NAME(HMOVE_started));
	save_item(NAME(HMOVE_started_previous));
	save_item(NAME(HMP0_latch));
	save_item(NAME(HMP1_latch));
	save_item(NAME(HMM0_latch));
	save_item(NAME(HMM1_latch));
	save_item(NAME(HMBL_latch));
	save_item(NAME(REFLECT));
	save_item(NAME(NUSIZx_changed));
	save_item(NAME(helper[0]));
	save_item(NAME(helper[1]));
	save_item(NAME(buffer));
}