summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/video/vic4567.cpp
blob: a599f56f88507811dab1d7e646290f0e7c2a549d (plain) (tree)
1
2

                                  















                                                                                 
                    
 

                   

                    
 









                                                                              
                                                                                                      



                                     
                                  
 






                                                                                                 


                                                                              


                                                     

                                                                                                           





                                                                                                  

                                                                                                


                                                                                        


                                                    
 




                                                                          

                                        
                                                    

                    

                                                         
                                                                   
                                                         
                                                                   
























                                                                                                        

                                               
                                                                                    


                                                 

                                                                  

                                                 
                                                                       
 




                                                    

 


                                                                                                        
                                                                   

                                                                                                            

                                                                         
                                         


                                                                                
                                                                      
                                                                                                              
                                                                      


                                                                                                                
                                                                 
 
                                                                                                         
                                                    
                                                  


                                                

                                       

                                  



                                        
 
 
 
                                                   



                                                   
 

                                       
 
                                                                 
 

                                                                   
 
                                     
                                                              
 











                                                
 



















                                               
 



















                                                     
 
                               
 
                              
 
                                    
 
                                 
 


                                       
 



                                   
 






                                       
 


                                      
 

                                   
 


                                           
 



                                         
 























                                                             
                                                         
 
                 
 



                             
 
                                                 
 


                          
 



                      
 





                                    
 






                                     
 

                         
 

                                                                                 





                                                                              
 
                            

 
 



                                                                              
                                                     
 
                                                                                                 

 
                                                       
 
                                                                                                                                        

 
                                           
 
                                                       
         
                                          

                                                                         
                                            
                                          

                 
                            

 
                                             
 

                                                                       

                                                               
                                     
                                  


         
                                                   
 



                                                             
                                                      


                                                    

                                                   
                 
                                 


                      
 
                                                                                                                             
 
                                            
         
                                                                     
                                                        







                                                                                                                                       


         
                                                                                                                  
 
                                            
         
                                                                     
                                                                      







                                                                                                                                         


         
                                                                                                         
 
                                            
         
                                                                                
                                                        







                                                                                                                                              


         
                                                                                                               
 
                                            
         
                                                                                
                                                                      







                                                                                                                                               


         
                                                                                                    
 


                                                                                                                                                               
                                                            



                                                                           
                                                                                 



                 
                                                                                                          
 
                                                                                                                                                               
                       
 
                                                                                      






                                                                                           
                                                                                                                          


                                                                                   
                                                                                                                      


                                                                                   
                                                                                                                      
                                                                                         
                                                                                                                          





                                      
                                                                    
 
                                    
         
                                                                                                                  




                                                                                           
                                                
 
                          
                                                     
                                                                   
                                   
                                                                      
                      
                                                                          






                                                                                    
                                         



                 
                                                                                               
 



                                                        
                                                   







                                                
                                                         

                                               
                                                                                                    



                                                                                           
                                                        
                                                                                                



                                                                    
                                                         


                                                         

                                                                                                                     
                         
                                                                                             

                                                
                                                         
                                 

                                                                 

                                    
                                                                 


                            
                                                     






                                                
                                                         

                                               
                                                                                         

                                                                               
                                                        
                                                                                             



                                                                    
                                                         


                                                         
                                                                                                         
                         
                                                                                         

                                                
                                                         
                                 

                                                                 

                                    
                                                                 


                            
                                                     




                         
                                                                                                     
 



                                                        
                                                   
                                            








                                                
                                                         

                                               
                                                                                                               




                                                                                            

                                                        
                                                                                                




                                                                    
                                                         


                                          

                                                                                                                                                    


                                    

                                                                                                                                  

                                 
                                                                                             

                                                
                                                         
                                 

                                                                 

                                    
                                                                 


                            
                                                     






                                                
                                                         

                                               
                                                                                         

                                                                                               

                                                        
                                                                                             




                                                                    
                                                         


                                          
                                                                                                                               


                                    
                                                                                                                      

                                 
                                                                                           

                                                
                                                         
                                 

                                                                 

                                    
                                                                 


                            
                                                     




                         
                                                                          
 








                                                         
                          






                                              
                                                                    






                          
                                                                                        
                 
                                                                                            







                                                       
                             

                           
                                       


                                              
                                                                                             



                    
                                                


            
                                                                  
         
                                  

                           

                                     







                                                                                     
                                              
 
                                                                                      
                 

                                                                       

                                    

                                                                              

                                                 

                                                                                                          


                                    
                                                                                                    




                                              


                                                                                                                 


                                                            

                                                                                                   


                            

                                                                                                     




                                                                          
                                                                     



                                                       

                                                                                                                        


                                    

                                                                                        



                                                                      
                                                                                                  
                                    

                                                                                            
                                 
                                                                                    
                                                                       
                                                                                









                                                                                                                     
                                                                                 









                                                                                           
                                                            

                                                         
                                                                                              
                                    
                                                                                        
 
                                                                                

                                                                       

                                                                                    


                                                                                  
                                                                                    














                                                                            
                                                                        
                                                         
                                                                                                                  
                                    

                                                                                                            

                                                                       

                                                                                    



                                 
                                                                                                        




                                                

                                                                                                                                     

                 
                                      

                           
                                         


                                  
                                                                                             


         
                                                                               
 
                           
                       

                                                           
                               
         
                                                            







                                                                                                          

                                                




                                                           
                                                                                                    
                                                          
                                                                                                                                 
                                                          
                                                                                                      
                                                         
                                                                                                                                  













                                    
                
                                  

                                
                                       
 
                         



                                                           
                                                                                                    
                                                          
                                                                                                                                 
                                                          
                                                                                                      
                                                         
                                                                                                                                  


                           
                                                  
 
                                       

                                
                                     


                       



                                                                   



                                                                  
                                              
                                                                                           
                 
                                                                   
     
                                                                           
     
                                                           
                                                                                        


                                    

                                                                              

                                                 

                                                                                                          


                                    
                                                                                                    



                                       
                                                  


                                                                                                                 


                                                            

                                                                                                   


                            

                                                                                                     



                                                                          
                                            







                                                                                                                   
                                                 


                                                        
                                                                                 









                                                                                           
                                                            

                                                          
                                                                                           
                                    
                                                                                     
                         
                                                    





                                                                                                                   
                                                 


                                                        
                                                                                 









                                                                                           
                                                            

                                                          
                                                                                                  
                                    
                                                                                            


                            
                                                                                                       






                                                                       
                                                                                                                                  
                                                                           
                                                                                                
                                                                           
                                                                                                      
                                                                          
                                                                                               


                                                                                           
                                                                                                                                  
                                                                                               
                                                                                                                                        
                                                                                               
                                                                                         
                                                                          
                                                                                               
 
                                           

                                
                                         




                                                           
                                                                                                    
                                                          
                                                                                                                                 
                                                          
                                                                                                      
                                                         
                                                                                                                                  







                                                                              
                                                        
 
                           
                                             
                                
                                                      
            
                                                     
 
                            


 
                                                     
 














                                                                                                
                                          
                 

                                                                           











                                                                                                
                                          
                 

                                                                           


                      
                                                                    
                                          
                 








                                                         


                      
                                                               
                                          
                 
                                             


                      
                                                               
                                          
                 
                                             


                      
                                                                            
                                          
                 
                                             


                      
                                                                               
                                          
                 
                                             











                                                                                           
                                          
                 
                                             


                      
                                                                   
                                          
                 

                                                              


                      
                                                                   
                                          
                 

                                                              



                      
                                             

                      
                                                          

                                                           


                      
                                          
                 
                                             

                                    

                                                          


                            

                                                          




                         
                                          
                 
                                             



                      
                                          
                 


                                                  



                      
                                          
                 



                                                    


                      
                                                                  
                                          
                 

                                                                                                  


                      
                                                                    
                                          
                 

                                                               


                      
                                                                    
                                          
                 

                                                               


                      
                                                                    
                                          
                 

                                                      


                      
                                                            
                                          
                 
                                             




                                                                       
                                     

                      
                                                                       
                                     
                                                   

                      
                                     
                                
                                                    
                    
                                                        














                      
                                     












                                                                             
                                     



                      
                                          
 






                                                      
                                                                              


                      
                                          


                      
                                           


                      
                                           

                      
                                                                         
                                                
                                           


                      
                                           

                      
                                                                                   


                                    

                      
                                                                                       


                                    






                      
                                    
































                      
                                    



                      
                                    















                                                                     
                                                         
                                    












                                                                            
                                    




                   































































                                                                                     
         

                                           
                                                                  
 
                            






















                                               
                                                                                    

                                               
                                                                                         

                                               
                                                                                         

                                               
                                                                                         

                                               
                                                                                         

                                               
                                                                                         

                                               
                                                                                         

                                               
                                                                                         
 
                                            
                 




                                                                                 













                                          
                                                        
 
                            






















                                               
                                                                                   

                                               
                                                                                        

                                               
                                                                                        

                                               
                                                                                        

                                               
                                                                                        

                                               
                                                                                        

                                               
                                                                                        

                                               
                                                                                        
 
                                            
                 




                                                                                 












                                        
                                  
 
                                                           


                              
                                                                   
                 
                                                                         
                         
                                                                                 
                                 

                                                                         
                                            
                                                                                       


                                 
                                 


            
                                                                  
                 
                                                                         
                         
                                                                             
                                 
                                                                 






                                 
                                                                
                                                

         
                                                          
         
                                                                                                 
                                                



                     
                                                               
                                                

         
                                                 
         
                                                                                       
                                                


         
                                        
 


                                  

                                    
         

                                    
                                                 
                                                                                                                         
 
                                    
                 






                                                                                                  


















                                                                                        
                                                                       
                 

                                                
                                                     
                                                          
                                                                                                      
                                                                                                                           
                                                                                                    
                                                                                                                       
                            
                                                          
                                                                                                      
                                                                                                                           
                                                                                                    
                                                                                                                       


                                   
                                         


                    
                                                     
                         

                                                                                                                                                               


                            

                                                                                                                                                               



                                       
                                                                    
 
                               



                                                  
                                                                                                                             



                 
                                                         
         
                                 

         

                                                                                                                          
                 
                                                     
                         

                                                                                                                                                                          


                            

                                                                                                                                                                          



                         
                                                                                     
 
                                                            

                 
// license:BSD-3-Clause
// copyright-holders:Peter Trauner
/***************************************************************************

    Video Interface Chip (4567)

    original emulation by PeT (mess@utanet.at)

    2010-02: converted to be a device and split from vic II

    TODO:
      - plenty of cleanups
      - emulate variants of the vic chip
      - update vic III to use the new vic6567.c code for the vic II comaptibility

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

#include "emu.h"
#include "vic4567.h"

#include "screen.h"

#include <algorithm>


/*****************************************************************************
    CONSTANTS
*****************************************************************************/

#define VERBOSE_LEVEL 0
#define DBG_LOG(N,M,A) \
	do { \
		if(VERBOSE_LEVEL >= N) \
		{ \
			if( M ) \
				logerror("%11.6f: %-24s", machine().time().as_double(), (char*) M ); \
			logerror A; \
		} \
	} while (0)

#define VREFRESHINLINES         28

#define VIC2_YPOS               50
#define RASTERLINE_2_C64(a)     (a)
#define C64_2_RASTERLINE(a)     (a)
#define XPOS                (VIC2_STARTVISIBLECOLUMNS + (VIC2_VISIBLECOLUMNS - VIC2_HSIZE) / 2)
#define YPOS                (VIC2_STARTVISIBLELINES /* + (VIC2_VISIBLELINES - VIC2_VSIZE) / 2 */)
#define FIRSTLINE               10 /* 36 ((VIC2_VISIBLELINES - VIC2_VSIZE)/2) */
#define FIRSTCOLUMN         50

/* 2008-05 FP: lightpen code needs to read input port from c64.c and cbmb.c */

#define LIGHTPEN_BUTTON     (m_lightpen_button_cb(0))
#define LIGHTPEN_X_VALUE    (m_lightpen_x_cb(0))
#define LIGHTPEN_Y_VALUE    (m_lightpen_y_cb(0))

/* lightpen delivers values from internal counters; they do not start with the visual area or frame area */
#define VIC2_MAME_XPOS          0
#define VIC2_MAME_YPOS          0
#define VIC6567_X_BEGIN         38
#define VIC6567_Y_BEGIN         -6             /* first 6 lines after retrace not for lightpen! */
#define VIC6569_X_BEGIN         38
#define VIC6569_Y_BEGIN         -6
#define VIC2_X_BEGIN            ((m_type == vic3_type::PAL) ? VIC6569_X_BEGIN : VIC6567_X_BEGIN)
#define VIC2_Y_BEGIN            ((m_type == vic3_type::PAL) ? VIC6569_Y_BEGIN : VIC6567_Y_BEGIN)
#define VIC2_X_VALUE            ((LIGHTPEN_X_VALUE + VIC2_X_BEGIN + VIC2_MAME_XPOS) / 2)
#define VIC2_Y_VALUE            ((LIGHTPEN_Y_VALUE + VIC2_Y_BEGIN + VIC2_MAME_YPOS))

#define VIC2E_K0_LEVEL          (m_reg[0x2f] & 0x01)
#define VIC2E_K1_LEVEL          (m_reg[0x2f] & 0x02)
#define VIC2E_K2_LEVEL          (m_reg[0x2f] & 0x04)

/*#define VIC3_P5_LEVEL (m_reg[0x30] & 0x20) */
#define VIC3_BITPLANES          (m_reg[0x31] & 0x10)
#define VIC3_80COLUMNS          (m_reg[0x31] & 0x80)
#define VIC3_LINES              ((m_reg[0x31] & 0x19) == 0x19 ? 400 : 200)
#define VIC3_BITPLANES_WIDTH    (m_reg[0x31] & 0x80 ? 640 : 320)

/*#define VIC2E_TEST (vic2[0x30] & 2) */
#define DOUBLE_CLOCK            (m_reg[0x30] & 0x01)

/* sprites 0 .. 7 */
#define SPRITEON(nr)            (m_reg[0x15] & (1 << nr))
#define SPRITE_Y_EXPAND(nr)     (m_reg[0x17] & (1 << nr))
#define SPRITE_Y_SIZE(nr)       (SPRITE_Y_EXPAND(nr) ? 2 * 21 : 21)
#define SPRITE_X_EXPAND(nr)     (m_reg[0x1d] & (1 << nr))
#define SPRITE_X_SIZE(nr)       (SPRITE_X_EXPAND(nr) ? 2 * 24 : 24)
#define SPRITE_X_POS(nr)        ((m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0)) - 24 + XPOS)
#define SPRITE_X_POS2(nr)       (m_reg[(nr) * 2] | (m_reg[0x10] & (1 <<(nr)) ? 0x100 : 0))
#define SPRITE_Y_POS(nr)        (m_reg[1+2*(nr)] - 50 + YPOS)
#define SPRITE_Y_POS2(nr)       (m_reg[1 + 2 *(nr)])
#define SPRITE_MULTICOLOR(nr)   (m_reg[0x1c] & (1 << nr))
#define SPRITE_PRIORITY(nr)     (m_reg[0x1b] & (1 << nr))
#define SPRITE_MULTICOLOR1      (m_reg[0x25] & 0x0f)
#define SPRITE_MULTICOLOR2      (m_reg[0x26] & 0x0f)
#define SPRITE_COLOR(nr)        (m_reg[0x27+nr] & 0x0f)
#define SPRITE_ADDR(nr)         (m_videoaddr | 0x3f8 | nr)
#define SPRITE_BG_COLLISION(nr) (m_reg[0x1f] & (1 << nr))
#define SPRITE_COLLISION(nr)        (m_reg[0x1e] & (1 << nr))
#define SPRITE_SET_BG_COLLISION(nr) (m_reg[0x1f] |= (1 << nr))
#define SPRITE_SET_COLLISION(nr)    (m_reg[0x1e] |= (1 << nr))
#define SPRITE_COLL         (m_reg[0x1e])
#define SPRITE_BG_COLL          (m_reg[0x1f])

#define GFXMODE             ((m_reg[0x11] & 0x60) | (m_reg[0x16] & 0x10)) >> 4
#define SCREENON                (m_reg[0x11] & 0x10)
#define VERTICALPOS         (m_reg[0x11] & 0x07)
#define HORIZONTALPOS           (m_reg[0x16] & 0x07)
#define ECMON               (m_reg[0x11] & 0x40)
#define HIRESON             (m_reg[0x11] & 0x20)
#define MULTICOLORON            (m_reg[0x16] & 0x10)
#define LINES25             (m_reg[0x11] & 0x08)           /* else 24 Lines */
#define LINES               (LINES25 ? 25 : 24)
#define YSIZE               (LINES * 8)
#define COLUMNS40               (m_reg[0x16] & 0x08)           /* else 38 Columns */
#define COLUMNS             (COLUMNS40 ? 40 : 38)
#define XSIZE               (COLUMNS * 8)

#define VIDEOADDR               ((m_reg[0x18] & 0xf0) << (10 - 4))
#define CHARGENADDR         ((m_reg[0x18] & 0x0e) << 10)
#define BITMAPADDR          ((data & 0x08) << 10)

#define RASTERLINE          (((m_reg[0x11] & 0x80) << 1) | m_reg[0x12])

#define FRAMECOLOR          (m_reg[0x20] & 0x0f)
#define BACKGROUNDCOLOR         (m_reg[0x21] & 0x0f)
#define MULTICOLOR1         (m_reg[0x22] & 0x0f)
#define MULTICOLOR2         (m_reg[0x23] & 0x0f)
#define FOREGROUNDCOLOR         (m_reg[0x24] & 0x0f)


#define VIC2_LINES      (m_type == vic3_type::PAL ? VIC6569_LINES : VIC6567_LINES)
#define VIC2_VISIBLELINES   (m_type == vic3_type::PAL ? VIC6569_VISIBLELINES : VIC6567_VISIBLELINES)
#define VIC2_VISIBLECOLUMNS (m_type == vic3_type::PAL ? VIC6569_VISIBLECOLUMNS : VIC6567_VISIBLECOLUMNS)
#define VIC2_STARTVISIBLELINES ((VIC2_LINES - VIC2_VISIBLELINES)/2)
#define VIC2_FIRSTRASTERLINE  (m_type == vic3_type::PAL ? VIC6569_FIRSTRASTERLINE : VIC6567_FIRSTRASTERLINE)
#define VIC2_COLUMNS          (m_type == vic3_type::PAL ? VIC6569_COLUMNS : VIC6567_COLUMNS)
#define VIC2_STARTVISIBLECOLUMNS ((VIC2_COLUMNS - VIC2_VISIBLECOLUMNS)/2)

#define VIC3_BITPLANES_MASK (m_reg[0x32])
/* bit 0, 4 not used !?*/
/* I think hinibbles contains the banknumbers for interlaced modes */
/* if hinibble set then x&1==0 should be in bank1 (0x10000), x&1==1 in bank 0 */
#define VIC3_BITPLANE_ADDR_HELPER(x)  ((m_reg[0x33 + x] & 0x0f) << 12)
#define VIC3_BITPLANE_ADDR(x) (x & 1 ? VIC3_BITPLANE_ADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_ADDR_HELPER(x) )
#define VIC3_BITPLANE_IADDR_HELPER(x)  ((m_reg[0x33 + x] & 0xf0) << 8)
#define VIC3_BITPLANE_IADDR(x) (x & 1 ? VIC3_BITPLANE_IADDR_HELPER(x) + 0x10000 : VIC3_BITPLANE_IADDR_HELPER(x))


DEFINE_DEVICE_TYPE(VIC3, vic3_device, "vic3", "CSG 4567 VIC-III")

vic3_device::vic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, VIC3, tag, owner, clock)
	, device_palette_interface(mconfig, *this)
	, device_video_interface(mconfig, *this)
	, m_type(vic3_type::NTSC)
	, m_cpu(*this, finder_base::DUMMY_TAG)
	, m_dma_read_cb(*this, 0)
	, m_dma_read_color_cb(*this, 0)
	, m_interrupt_cb(*this)
	, m_port_changed_cb(*this)
	, m_lightpen_button_cb(*this, 0)
	, m_lightpen_x_cb(*this, 0)
	, m_lightpen_y_cb(*this, 0)
	, m_c64_mem_r_cb(*this, 0)
{
}

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

void vic3_device::device_start()
{
	int width = screen().width();
	int height = screen().height();

	m_bitmap = std::make_unique<bitmap_ind16>(width, height);

	m_screendata = std::make_unique<uint8_t []>(216 * 656 / 8);
	m_screenptr[0] = m_screendata.get();

	for (int i = 1; i < 216; i++)
		m_screenptr[i] = m_screenptr[i - 1] + 656 / 8;

	for (int i = 0; i < 256; i++)
	{
		m_foreground[i] = 0;
		if ((i & 3) > 1)
			m_foreground[i] |= 0x3;
		if ((i & 0xc) > 0x4)
			m_foreground[i] |= 0xc;
		if ((i & 0x30) > 0x10)
			m_foreground[i] |= 0x30;
		if ((i & 0xc0) > 0x40)
			m_foreground[i] |= 0xc0;
	}

	for (int i = 0; i < 256; i++)
	{
		m_expandx[i] = 0;
		if (i & 1)
			m_expandx[i] |= 3;
		if (i & 2)
			m_expandx[i] |= 0xc;
		if (i & 4)
			m_expandx[i] |= 0x30;
		if (i & 8)
			m_expandx[i] |= 0xc0;
		if (i & 0x10)
			m_expandx[i] |= 0x300;
		if (i & 0x20)
			m_expandx[i] |= 0xc00;
		if (i & 0x40)
			m_expandx[i] |= 0x3000;
		if (i & 0x80)
			m_expandx[i] |= 0xc000;
	}

	for (int i = 0; i < 256; i++)
	{
		m_expandx_multi[i] = 0;
		if (i & 1)
			m_expandx_multi[i] |= 5;
		if (i & 2)
			m_expandx_multi[i] |= 0xa;
		if (i & 4)
			m_expandx_multi[i] |= 0x50;
		if (i & 8)
			m_expandx_multi[i] |= 0xa0;
		if (i & 0x10)
			m_expandx_multi[i] |= 0x500;
		if (i & 0x20)
			m_expandx_multi[i] |= 0xa00;
		if (i & 0x40)
			m_expandx_multi[i] |= 0x5000;
		if (i & 0x80)
			m_expandx_multi[i] |= 0xa000;
	}

	save_item(NAME(m_reg));

	save_item(NAME(m_on));

	//save_item(NAME(m_bitmap));

	save_item(NAME(m_lines));

	save_item(NAME(m_chargenaddr));
	save_item(NAME(m_videoaddr));
	save_item(NAME(m_bitmapaddr));

	save_item(NAME(m_x_begin));
	save_item(NAME(m_x_end));
	save_item(NAME(m_y_begin));
	save_item(NAME(m_y_end));

	save_item(NAME(m_c64_bitmap));
	save_item(NAME(m_bitmapmulti));
	save_item(NAME(m_mono));
	save_item(NAME(m_multi));
	save_item(NAME(m_ecmcolor));
	save_item(NAME(m_colors));
	save_item(NAME(m_spritemulti));

	save_item(NAME(m_lastline));
	save_item(NAME(m_rasterline));
	save_item(NAME(m_interlace));

	save_item(NAME(m_columns));
	save_item(NAME(m_rows));

	save_item(NAME(m_shift));
	save_item(NAME(m_foreground));
	save_item(NAME(m_multi_collision));

	save_item(NAME(m_palette_red));
	save_item(NAME(m_palette_green));
	save_item(NAME(m_palette_blue));
	save_item(NAME(m_palette_dirty));

	for (int i = 0; i < 8; i++)
	{
		save_item(NAME(m_sprites[i].x), i);
		save_item(NAME(m_sprites[i].y), i);
		save_item(NAME(m_sprites[i].repeat), i);
		save_item(NAME(m_sprites[i].line), i);
		save_item(NAME(m_sprites[i].paintedline), i);
		save_item(NAME(m_sprites[i].bitmap[0]), i);
		save_item(NAME(m_sprites[i].bitmap[1]), i);
		save_item(NAME(m_sprites[i].bitmap[2]), i);
		save_item(NAME(m_sprites[i].bitmap[3]), i);
		save_item(NAME(m_sprites[i].bitmap[4]), i);
		save_item(NAME(m_sprites[i].bitmap[5]), i);
		save_item(NAME(m_sprites[i].bitmap[6]), i);
		save_item(NAME(m_sprites[i].bitmap[7]), i);
	}
}

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

void vic3_device::device_reset()
{
	std::fill(std::begin(m_reg), std::end(m_reg), 0);

	m_on = 1;

	m_interlace = 0;
	m_columns = 640;
	m_rows = 200;
	m_lines = VIC2_LINES;

	memset(&m_sprites, 0, sizeof(m_sprites));

	m_chargenaddr = 0;
	m_videoaddr = 0;
	m_bitmapaddr = 0;

	m_x_begin = 0;
	m_x_end = 0;
	m_y_begin = 0;
	m_y_end = 0;

	for (int i = 0; i < 2; i++)
	{
		m_c64_bitmap[i] = 0;
		m_mono[i] = 0;
		m_ecmcolor[i] = 0;
	}

	for (int i = 0; i < 4; i++)
	{
		m_bitmapmulti[i] = 0;
		m_multi[i] = 0;
		m_colors[i] = 0;
		m_spritemulti[i] = 0;
	}

	m_lastline = 0;
	m_rasterline = 0;

	std::fill(std::begin(m_shift), std::end(m_shift), 0);
	std::fill(std::begin(m_multi_collision), std::end(m_multi_collision), 0);

	for (int i = 0; i < 256; i++)
	{
		m_palette_red[i] = m_palette_green[i] = m_palette_blue[i] = 0;
		set_pen_color(i, rgb_t::black());
	}

	m_palette_dirty = 0;
}


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

inline int vic3_device::getforeground( int y, int x )
{
	return ((m_screenptr[y][x >> 3] << 8) | (m_screenptr[y][(x >> 3) + 1])) >> (8 - (x & 7));
}

inline int vic3_device::getforeground16( int y, int x )
{
	return ((m_screenptr[y][x >> 3] << 16) | (m_screenptr[y][(x >> 3) + 1] << 8) | (m_screenptr[y][(x >> 3) + 2])) >> (8 - (x & 7));
}

void vic3_device::set_interrupt( int mask )
{
	if (((m_reg[0x19] ^ mask) & m_reg[0x1a] & 0xf))
	{
		if (!(m_reg[0x19] & 0x80))
		{
			//DBG_LOG(2, "vic2", ("irq start %.2x\n", mask));
			m_reg[0x19] |= 0x80;
			m_interrupt_cb(1);
		}
	}
	m_reg[0x19] |= mask;
}

void vic3_device::clear_interrupt( int mask )
{
	m_reg[0x19] &= ~mask;
	if ((m_reg[0x19] & 0x80) && !(m_reg[0x19] & m_reg[0x1a] & 0xf))
	{
		//DBG_LOG(2, "vic2", ("irq end %.2x\n", mask));
		m_reg[0x19] &= ~0x80;
		m_interrupt_cb(0);
	}
}

TIMER_CALLBACK_MEMBER( vic3_device::timer_timeout )
{
	int which = param;
	//DBG_LOG(3, "vic3 ", ("timer %d timeout\n", which));
	switch (which)
	{
	case 1:                        /* light pen */
		/* and diode must recognize light */
		if (1)
		{
			m_reg[0x13] = VIC2_X_VALUE;
			m_reg[0x14] = VIC2_Y_VALUE;
		}
		set_interrupt(8);
		break;
	}
}

void vic3_device::draw_character( int ybegin, int yend, int ch, int yoff, int xoff, uint16_t *color, int start_x, int end_x )
{
	for (int y = ybegin; y <= yend; y++)
	{
		int code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
		m_screenptr[y + yoff][xoff >> 3] = code;
		if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = color[code >> 7];
		if ((xoff + 1 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = color[(code >> 6) & 1];
		if ((xoff + 2 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = color[(code >> 5) & 1];
		if ((xoff + 3 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = color[(code >> 4) & 1];
		if ((xoff + 4 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = color[(code >> 3) & 1];
		if ((xoff + 5 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = color[(code >> 2) & 1];
		if ((xoff + 6 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = color[(code >> 1) & 1];
		if ((xoff + 7 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = color[code & 1];
	}
}

void vic3_device::draw_character_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
{
	for (int y = ybegin; y <= yend; y++)
	{
		int code = m_dma_read_cb(m_chargenaddr + ch * 8 + y);
		m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
		if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_multi[code >> 6];
		if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_multi[code >> 6];
		if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_multi[(code >> 4) & 3];
		if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_multi[(code >> 4) & 3];
		if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_multi[(code >> 2) & 3];
		if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_multi[(code >> 2) & 3];
		if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_multi[code & 3];
		if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_multi[code & 3];
	}
}

void vic3_device::draw_bitmap( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
{
	for (int y = ybegin; y <= yend; y++)
	{
		int code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
		m_screenptr[y + yoff][xoff >> 3] = code;
		if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_c64_bitmap[code >> 7];
		if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_c64_bitmap[(code >> 6) & 1];
		if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_c64_bitmap[(code >> 5) & 1];
		if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_c64_bitmap[(code >> 4) & 1];
		if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_c64_bitmap[(code >> 3) & 1];
		if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_c64_bitmap[(code >> 2) & 1];
		if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_c64_bitmap[(code >> 1) & 1];
		if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_c64_bitmap[code & 1];
	}
}

void vic3_device::draw_bitmap_multi( int ybegin, int yend, int ch, int yoff, int xoff, int start_x, int end_x )
{
	for (int y = ybegin; y <= yend; y++)
	{
		int code = m_dma_read_cb((m_chargenaddr & 0x2000) + ch * 8 + y);
		m_screenptr[y + yoff][xoff >> 3] = m_foreground[code];
		if ((xoff + 0 > start_x) && (xoff + 0 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 0) = m_bitmapmulti[code >> 6];
		if ((xoff + 1 > start_x) && (xoff + 1 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 1) = m_bitmapmulti[code >> 6];
		if ((xoff + 2 > start_x) && (xoff + 2 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 2) = m_bitmapmulti[(code >> 4) & 3];
		if ((xoff + 3 > start_x) && (xoff + 3 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 3) = m_bitmapmulti[(code >> 4) & 3];
		if ((xoff + 4 > start_x) && (xoff + 4 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 4) = m_bitmapmulti[(code >> 2) & 3];
		if ((xoff + 5 > start_x) && (xoff + 5 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 5) = m_bitmapmulti[(code >> 2) & 3];
		if ((xoff + 6 > start_x) && (xoff + 6 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 6) = m_bitmapmulti[code & 3];
		if ((xoff + 7 > start_x) && (xoff + 7 < end_x)) m_bitmap->pix(y + yoff + FIRSTLINE, xoff + 7) = m_bitmapmulti[code & 3];
	}
}

void vic3_device::draw_sprite_code( int y, int xbegin, int code, int color, int start_x, int end_x )
{
	if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
		return;

	for (int x = 0, mask = 0x80; x < 8; x++, mask >>= 1)
	{
		if (code & mask)
		{
			if ((xbegin + x > start_x) && (xbegin + x < end_x))
				m_bitmap->pix(y + FIRSTLINE, xbegin + x) = color;
		}
	}
}

void vic3_device::draw_sprite_code_multi( int y, int xbegin, int code, int prior, int start_x, int end_x )
{
	if ((y < YPOS) || (y >= (VIC2_STARTVISIBLELINES + VIC2_VISIBLELINES)) || (xbegin <= 1) || (xbegin >= (VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS)))
		return;

	for (int x = 0, mask = 0xc0, shift = 6; x < 8; x += 2, mask >>= 2, shift -= 2)
	{
		if (code & mask)
		{
			switch ((prior & mask) >> shift)
			{
			case 1:
				if ((xbegin + x + 1 > start_x) && (xbegin + x + 1 < end_x))
					m_bitmap->pix(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
				break;
			case 2:
				if ((xbegin + x > start_x) && (xbegin + x < end_x))
					m_bitmap->pix(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
				break;
			case 3:
				if ((xbegin + x > start_x) && (xbegin + x < end_x))
					m_bitmap->pix(y + FIRSTLINE, xbegin + x) = m_spritemulti[(code >> shift) & 3];
				if ((xbegin + x + 1> start_x) && (xbegin + x + 1< end_x))
					m_bitmap->pix(y + FIRSTLINE, xbegin + x + 1) = m_spritemulti[(code >> shift) & 3];
				break;
			}
		}
	}
}

void vic3_device::sprite_collision( int nr, int y, int x, int mask )
{
	for (int i = 7; i > nr; i--)
	{
		if (!SPRITEON(i) || !m_sprites[i].paintedline[y] || (SPRITE_COLLISION(i) && SPRITE_COLLISION(nr)))
			continue;

		if ((x + 7 < SPRITE_X_POS(i)) || (x >= SPRITE_X_POS(i) + SPRITE_X_SIZE(i)))
			continue;

		int xdiff = x - SPRITE_X_POS(i);

		int value;
		if ((x & 7) == (SPRITE_X_POS(i) & 7))
			value = m_sprites[i].bitmap[y][xdiff >> 3];
		else if (xdiff < 0)
			value = m_sprites[i].bitmap[y][0] >> (-xdiff);
		else {
			uint8_t *vp = m_sprites[i].bitmap[y]+(xdiff >> 3);
			value = ((vp[1] | (*vp << 8)) >> (8 - (xdiff & 7) )) & 0xff;
		}

		if (value & mask)
		{
			SPRITE_SET_COLLISION(i);
			SPRITE_SET_COLLISION(nr);
			set_interrupt(4);
		}
	}
}

void vic3_device::draw_sprite( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
{
	int y, i, addr, xbegin, color, prior, collision;
	int value, value3 = 0;

	xbegin = SPRITE_X_POS(nr);
	addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
	color = SPRITE_COLOR(nr);
	prior = SPRITE_PRIORITY(nr);
	collision = SPRITE_BG_COLLISION(nr);

	if (SPRITE_X_EXPAND(nr))
	{
		for (y = ybegin; y <= yend; y++)
		{
			m_sprites[nr].paintedline[y] = 1;
			for (i = 0; i < 3; i++)
			{
				value = m_expandx[m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
				m_sprites[nr].bitmap[y][i * 2] = value >> 8;
				m_sprites[nr].bitmap[y][i * 2 + 1] = value & 0xff;
				sprite_collision(nr, y, xbegin + i * 16, value >> 8);
				sprite_collision(nr, y, xbegin + i * 16 + 8, value & 0xff);
				if (prior || !collision)
					value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
				if (!collision && (value & value3))
				{
					collision = 1;
					SPRITE_SET_BG_COLLISION(nr);
					set_interrupt(2);
				}
				if (prior)
					value &= ~value3;
				draw_sprite_code(yoff + y, xbegin + i * 16, value >> 8, color, start_x, end_x);
				draw_sprite_code(yoff + y, xbegin + i * 16 + 8, value & 0xff, color, start_x, end_x);
			}
			m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
			if (SPRITE_Y_EXPAND(nr))
			{
				if (m_sprites[nr].repeat)
				{
					m_sprites[nr].line++;
					m_sprites[nr].repeat = 0;
				}
				else
					m_sprites[nr].repeat = 1;
			}
			else
			{
				m_sprites[nr].line++;
			}
		}
	}
	else
	{
		for (y = ybegin; y <= yend; y++)
		{
			m_sprites[nr].paintedline[y] = 1;
			for (i = 0; i < 3; i++)
			{
				value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
				m_sprites[nr].bitmap[y][i] = value;
				sprite_collision(nr, y, xbegin + i * 8, value);
				if (prior || !collision)
					value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
				if (!collision && (value & value3))
				{
					collision = 1;
					SPRITE_SET_BG_COLLISION(nr);
					set_interrupt(2);
				}
				if (prior)
					value &= ~value3;
				draw_sprite_code(yoff + y, xbegin + i * 8, value, color, start_x, end_x);
			}
			m_sprites[nr].bitmap[y][i]=0; //easier sprite collision detection
			if (SPRITE_Y_EXPAND(nr))
			{
				if (m_sprites[nr].repeat)
				{
					m_sprites[nr].line++;
					m_sprites[nr].repeat = 0;
				}
				else
					m_sprites[nr].repeat = 1;
			}
			else
			{
				m_sprites[nr].line++;
			}
		}
	}
}

void vic3_device::draw_sprite_multi( int nr, int yoff, int ybegin, int yend, int start_x, int end_x )
{
	int y, i, prior, addr, xbegin, collision;
	int value, value2, value3 = 0, bg/*, color[2]*/;

	xbegin = SPRITE_X_POS(nr);
	addr = m_dma_read_cb(SPRITE_ADDR(nr)) << 6;
	m_spritemulti[2] = SPRITE_COLOR(nr);
	prior = SPRITE_PRIORITY(nr);
	collision = SPRITE_BG_COLLISION(nr);
	//color[0] = 0;
	//color[1] = 1;

	if (SPRITE_X_EXPAND(nr))
	{
		for (y = ybegin; y <= yend; y++)
		{
			m_sprites[nr].paintedline[y] = 1;
			for (i = 0; i < 3; i++)
			{
				value = m_expandx_multi[bg = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i)];
				value2 = m_expandx[m_multi_collision[bg]];
				m_sprites[nr].bitmap[y][i * 2] = value2 >> 8;
				m_sprites[nr].bitmap[y][i * 2 + 1] = value2 & 0xff;
				sprite_collision(nr, y, xbegin + i * 16, value2 >> 8);
				sprite_collision(nr, y, xbegin + i * 16 + 8, value2 & 0xff);
				if (prior || !collision)
				{
					value3 = getforeground16(yoff + y, xbegin + i * 16 - 7);
				}
				if (!collision && (value2 & value3))
				{
					collision = 1;
					SPRITE_SET_BG_COLLISION(nr);
					set_interrupt(2);
				}
				if (prior)
				{
					draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, (value3 >> 8) ^ 0xff, start_x, end_x);
					draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, (value3 & 0xff) ^ 0xff, start_x, end_x);
				}
				else
				{
					draw_sprite_code_multi(yoff + y, xbegin + i * 16, value >> 8, 0xff, start_x, end_x);
					draw_sprite_code_multi(yoff + y, xbegin + i * 16 + 8, value & 0xff, 0xff, start_x, end_x);
				}
			}
			m_sprites[nr].bitmap[y][i * 2]=0; //easier sprite collision detection
			if (SPRITE_Y_EXPAND(nr))
			{
				if (m_sprites[nr].repeat)
				{
					m_sprites[nr].line++;
					m_sprites[nr].repeat = 0;
				}
				else
					m_sprites[nr].repeat = 1;
			}
			else
			{
				m_sprites[nr].line++;
			}
		}
	}
	else
	{
		for (y = ybegin; y <= yend; y++)
		{
			m_sprites[nr].paintedline[y] = 1;
			for (i = 0; i < 3; i++)
			{
				value = m_dma_read_cb(addr + m_sprites[nr].line * 3 + i);
				m_sprites[nr].bitmap[y][i] = value2 = m_multi_collision[value];
				sprite_collision(nr, y, xbegin + i * 8, value2);
				if (prior || !collision)
				{
					value3 = getforeground(yoff + y, xbegin + i * 8 - 7);
				}
				if (!collision && (value2 & value3))
				{
					collision = 1;
					SPRITE_SET_BG_COLLISION(nr);
					set_interrupt(2);
				}
				if (prior)
				{
					draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, value3 ^ 0xff, start_x, end_x);
				}
				else
				{
					draw_sprite_code_multi(yoff + y, xbegin + i * 8, value, 0xff, start_x, end_x);
				}
			}
			m_sprites[nr].bitmap[y][i] = 0; //easier sprite collision detection
			if (SPRITE_Y_EXPAND(nr))
			{
				if (m_sprites[nr].repeat)
				{
					m_sprites[nr].line++;
					m_sprites[nr].repeat = 0;
				}
				else
					m_sprites[nr].repeat = 1;
			}
			else
			{
				m_sprites[nr].line++;
			}
		}
	}
}

void vic3_device::drawlines( int first, int last, int start_x, int end_x )
{
	int line, vline, end;
	int attr, ch, ecm;
	int syend;
	int offs, yoff, xoff, ybegin, yend, xbegin, xend;
	int x_end2;
	int i, j;

	if (first == last)
		return;
	m_lastline = last;

	/* top part of display not rastered */
	first -= VIC2_YPOS - YPOS;
	last -= VIC2_YPOS - YPOS;
	if ((first >= last) || (last <= 0))
	{
		for (i = 0; i < 8; i++)
			m_sprites[i].repeat = m_sprites[i].line = 0;
		return;
	}
	if (first < 0)
		first = 0;

	if (!SCREENON)
	{
		for (line = first; (line < last) && (line < m_bitmap->height()); line++)
		{
			std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), 0);
		}
		return;
	}
	if (COLUMNS40)
		xbegin = XPOS, xend = xbegin + 640;
	else
		xbegin = XPOS + 7, xend = xbegin + 624;

	if (last < m_y_begin)
		end = last;
	else
		end = m_y_begin + YPOS;

	for (line = first; line < end; line++)
	{
		std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), FRAMECOLOR);
	}

	if (LINES25)
	{
		vline = line - m_y_begin - YPOS;
	}
	else
	{
		vline = line - m_y_begin - YPOS + 8 - VERTICALPOS;
	}
	if (last < m_y_end + YPOS)
		end = last;
	else
		end = m_y_end + YPOS;
	x_end2 = m_x_end * 2;
	for (; line < end; vline = (vline + 8) & ~7, line = line + 1 + yend - ybegin)
	{
		offs = (vline >> 3) * 80;
		ybegin = vline & 7;
		yoff = line - ybegin;
		yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
		/* rendering 39 characters */
		/* left and right borders are overwritten later */
		m_shift[line] = HORIZONTALPOS;

		for (xoff = m_x_begin + XPOS; xoff < x_end2 + XPOS; xoff += 8, offs++)
		{
			ch = m_dma_read_cb(m_videoaddr + offs);
			attr = m_dma_read_color_cb(m_videoaddr + offs);
			if (HIRESON)
			{
				m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
				m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
				if (MULTICOLORON)
				{
					m_bitmapmulti[3] = attr;
					draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
				}
				else
				{
					draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
				}
			}
			else if (ECMON)
			{
				ecm = ch >> 6;
				m_ecmcolor[0] = m_colors[ecm];
				m_ecmcolor[1] = attr;
				draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
			}
			else if (MULTICOLORON && (attr & 8))
			{
				m_multi[3] = attr & 7;
				draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
			}
			else
			{
				m_mono[1] = attr;
				draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
			}
		}
		/* sprite priority, sprite overwrites lowerprior pixels */
		for (i = 7; i >= 0; i--)
		{
			if (m_sprites[i].line || m_sprites[i].repeat)
			{
				syend = yend;
				if (SPRITE_Y_EXPAND(i))
				{
					if ((21 - m_sprites[i].line) * 2 - m_sprites[i].repeat < yend - ybegin + 1)
						syend = ybegin + (21 - m_sprites[i].line) * 2 - m_sprites[i].repeat - 1;
				}
				else
				{
					if (m_sprites[i].line + yend - ybegin + 1 > 20)
						syend = ybegin + 20 - m_sprites[i].line;
				}
				if (yoff + syend > YPOS + 200)
					syend = YPOS + 200 - yoff - 1;
				if (SPRITE_MULTICOLOR(i))
					draw_sprite_multi(i, yoff, ybegin, syend, start_x, end_x);
				else
					draw_sprite(i, yoff, ybegin, syend, start_x, end_x);
				if ((syend != yend) || (m_sprites[i].line > 20))
				{
					m_sprites[i].line = m_sprites[i].repeat = 0;
					for (j = syend; j <= yend; j++)
						m_sprites[i].paintedline[j] = 0;
				}
			}
			// sprite wrap y at the top of the screen
			else if (SPRITEON(i) && (yoff == 1 + yend - ybegin) && (SPRITE_Y_POS(i) < 1 + yend - ybegin))
			{
				int wrapped = 1 + yend - ybegin - SPRITE_Y_POS(i);
				syend = yend;

				if (SPRITE_Y_EXPAND(i))
				{
					if (wrapped & 1) m_sprites[i].repeat = 1;
					wrapped >>= 1;
					syend = 21 * 2 - 1 - wrapped * 2;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}
				else
				{
					syend = 21 - 1 - wrapped;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}

				m_sprites[i].line = wrapped;

				if (SPRITE_MULTICOLOR(i))
					draw_sprite_multi(i, yoff, 0 , syend, start_x, end_x);
				else
					draw_sprite(i, yoff, 0 , syend, start_x, end_x);

				if ((syend != yend) || (m_sprites[i].line > 20))
				{
					for (j = syend; j <= yend; j++)
						m_sprites[i].paintedline[j] = 0;
					m_sprites[i].line = m_sprites[i].repeat = 0;
				}
			}
			else if (SPRITEON(i) && (yoff + ybegin <= SPRITE_Y_POS(i))
						&& (yoff + yend >= SPRITE_Y_POS(i)))
			{
				syend = yend;
				if (SPRITE_Y_EXPAND(i))
				{
					if (21 * 2 < yend - ybegin + 1)
						syend = ybegin + 21 * 2 - 1;
				}
				else
				{
					if (yend - ybegin + 1 > 21)
						syend = ybegin + 21 - 1;
				}
				if (yoff + syend >= YPOS + 200)
					syend = YPOS + 200 - yoff - 1;
				for (j = 0; j < SPRITE_Y_POS(i) - yoff; j++)
					m_sprites[i].paintedline[j] = 0;
				if (SPRITE_MULTICOLOR(i))
					draw_sprite_multi(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
				else
					draw_sprite(i, yoff, SPRITE_Y_POS(i) - yoff, syend, start_x, end_x);
				if ((syend != yend) || (m_sprites[i].line > 20))
				{
					for (j = syend; j <= yend; j++)
						m_sprites[i].paintedline[j] = 0;
					m_sprites[i].line = m_sprites[i].repeat = 0;
				}
			}
			else
			{
				memset (m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
			}
		}

		for (i = ybegin; i <= yend; i++)
		{
			m_bitmap->plot_box(0, yoff + ybegin + FIRSTLINE, xbegin, yend - ybegin + 1, FRAMECOLOR);
			m_bitmap->plot_box(xend, yoff + ybegin + FIRSTLINE, m_bitmap->width() - xend, yend - ybegin + 1, FRAMECOLOR);
		}
	}
	if (last < m_bitmap->height())
		end = last;
	else
		end = m_bitmap->height();

	for (; line < end; line++)
	{
		std::fill_n(&m_bitmap->pix(line + FIRSTLINE), m_bitmap->width(), FRAMECOLOR);
	}
}

void vic3_device::vic2_drawlines( int first, int last, int start_x, int end_x )
{
	if (VIC3_BITPLANES)
		return;

	/* temporary allowing vic3 displaying 80 columns */
	if (m_reg[0x31] & 0x80)
	{
		drawlines(first, first + 1, start_x, end_x);
		return;
	}

	/* otherwise, draw VIC II output (currently using the old code, not the new one from vic6567.c) */

	/* top part of display not rastered */
	first -= VIC2_YPOS - YPOS;

	int xbegin = VIC2_STARTVISIBLECOLUMNS;
	int xend = xbegin + VIC2_VISIBLECOLUMNS;
	if (!SCREENON)
	{
		xbegin = VIC2_STARTVISIBLECOLUMNS;
		xend = xbegin + VIC2_VISIBLECOLUMNS;
		if ((start_x <= xbegin) && (end_x >= xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x >= xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
		if ((start_x <= xbegin) && (end_x < xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x < xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
		return;
	}

	if (COLUMNS40)
	{
		xbegin = XPOS;
		xend = xbegin + 320;
	}
	else
	{
		xbegin = XPOS + 7;
		xend = xbegin + 304;
	}

	int end;
	if (first + 1 < m_y_begin)
		end = first + 1;
	else
		end = m_y_begin + YPOS;

	int line = first;
	// top border
	if (line < end)
	{
		if ((start_x <= xbegin) && (end_x >= xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x >= xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
		if ((start_x <= xbegin) && (end_x < xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x < xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
		line = end;
	}

	int vline = line - YPOS + 3 - VERTICALPOS;

	if (first + 1 < m_y_end + YPOS)
		end = first + 1;
	else
		end = m_y_end + YPOS;

	if (line < end)
	{
		int offs = (vline >> 3) * 40;
		int ybegin = vline & 7;
		int yoff = line - ybegin;
		int yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);

		/* rendering 39 characters */
		/* left and right borders are overwritten later */

		m_shift[line] = HORIZONTALPOS;
		for (int xoff = m_x_begin + XPOS; xoff < m_x_end + XPOS; xoff += 8, offs++)
		{
			int ch = m_dma_read_cb(m_videoaddr + offs);
#if 0
			int attr = m_dma_read_color_cb(m_videoaddr + offs);
#else
			/* temporary until vic3 finished */
			int attr = m_dma_read_color_cb((m_videoaddr + offs)&0x3ff)&0x0f;
#endif
			if (HIRESON)
			{
				m_bitmapmulti[1] = m_c64_bitmap[1] = ch >> 4;
				m_bitmapmulti[2] = m_c64_bitmap[0] = ch & 0xf;
				if (MULTICOLORON)
				{
					m_bitmapmulti[3] = attr;
					draw_bitmap_multi(ybegin, yend, offs, yoff, xoff, start_x, end_x);
				}
				else
				{
					draw_bitmap(ybegin, yend, offs, yoff, xoff, start_x, end_x);
				}
			}
			else if (ECMON)
			{
				int ecm = ch >> 6;
				m_ecmcolor[0] = m_colors[ecm];
				m_ecmcolor[1] = attr;
				draw_character(ybegin, yend, ch & ~0xC0, yoff, xoff, m_ecmcolor, start_x, end_x);
			}
			else if (MULTICOLORON && (attr & 8))
			{
				m_multi[3] = attr & 7;
				draw_character_multi(ybegin, yend, ch, yoff, xoff, start_x, end_x);
			}
			else
			{
				m_mono[1] = attr;
				draw_character(ybegin, yend, ch, yoff, xoff, m_mono, start_x, end_x);
			}
		}

		/* sprite priority, sprite overwrites lowerprior pixels */
		for (int i = 7; i >= 0; i--)
		{
			if (SPRITEON (i) &&
					(yoff + ybegin >= SPRITE_Y_POS (i)) &&
					(yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
					(SPRITE_Y_POS (i) < 0))
			{
				int wrapped = - SPRITE_Y_POS (i) + 6;

				int syend = yend;

				if (SPRITE_Y_EXPAND (i))
				{
					if (wrapped & 1) m_sprites[i].repeat = 1;
					wrapped >>= 1;
					syend = 21 * 2 - 1 - wrapped * 2;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}
				else
				{
					syend = 21 - 1 - wrapped;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}

				m_sprites[i].line = wrapped;

				if (SPRITE_MULTICOLOR (i))
					draw_sprite_multi(i, 0, 0 , syend, start_x, end_x);
				else
					draw_sprite(i, 0, 0 , syend, start_x, end_x);
			}
			else if     (SPRITEON (i) &&
					(yoff + ybegin >= SPRITE_Y_POS (i)) &&
					(yoff + ybegin - SPRITE_Y_POS (i) < (SPRITE_Y_EXPAND (i)? 21 * 2 : 21 )) &&
					(SPRITE_Y_POS (i) >= 0))
			{
				int wrapped = yoff + ybegin - SPRITE_Y_POS (i);

				int syend = yend;

				if (SPRITE_Y_EXPAND (i))
				{
					if (wrapped & 1) m_sprites[i].repeat = 1;
					wrapped >>= 1;
					syend = 21 * 2 - 1 - wrapped * 2;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}
				else
				{
					syend = 21 - 1 - wrapped;
					if (syend > (yend - ybegin)) syend = yend - ybegin;
				}

				m_sprites[i].line = wrapped;

				if (SPRITE_MULTICOLOR (i))
					draw_sprite_multi(i, yoff + ybegin, 0, 0, start_x, end_x);
				else
					draw_sprite(i, yoff + ybegin, 0, 0, start_x, end_x);
			}
			else
			{
				memset(m_sprites[i].paintedline, 0, sizeof (m_sprites[i].paintedline));
			}
		}
		line += 1 + yend - ybegin;
	}

	// left border
	if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
		m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xbegin - VIC2_STARTVISIBLECOLUMNS, 1, FRAMECOLOR);
	else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x >= xbegin))
		m_bitmap->plot_box(start_x, first + FIRSTLINE, xbegin - start_x, 1, FRAMECOLOR);
	else if ((start_x <= VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
		m_bitmap->plot_box(VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x, 1, FRAMECOLOR);
	else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
		m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);

	// right border
	if ((start_x <= xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
		m_bitmap->plot_box(xend, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - xend, 1, FRAMECOLOR);
	else if ((start_x > xend) && (end_x >= VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
		m_bitmap->plot_box(start_x, first + FIRSTLINE, VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS - start_x, 1, FRAMECOLOR);
	else if ((start_x <= xend) && (end_x < VIC2_STARTVISIBLECOLUMNS + VIC2_VISIBLECOLUMNS))
		m_bitmap->plot_box(xend, first + FIRSTLINE, end_x - xend, 1, FRAMECOLOR);
	else if ((start_x > VIC2_STARTVISIBLECOLUMNS) && (end_x < xbegin))
		m_bitmap->plot_box(start_x, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);

	if (first + 1 < m_bitmap->height())
		end = first + 1;
	else
		end = m_bitmap->height();

	// bottom border
	if (line < end)
	{
		if ((start_x <= xbegin) && (end_x >= xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, xend - xbegin, 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x >= xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, xend - start_x, 1, FRAMECOLOR);
		if ((start_x <= xbegin) && (end_x < xend))
			m_bitmap->plot_box(xbegin, first + FIRSTLINE, end_x - xbegin , 1, FRAMECOLOR);
		if ((start_x > xbegin) && (end_x < xend))
			m_bitmap->plot_box(start_x - VIC2_STARTVISIBLECOLUMNS, first + FIRSTLINE, end_x - start_x, 1, FRAMECOLOR);
		line = end;
	}
}

/*****************************************************************************
    I/O HANDLERS
*****************************************************************************/

void vic3_device::palette_w(offs_t offset, uint8_t data)
{
	if (offset < 0x100)
		m_palette_red[offset] = data;
	else if (offset < 0x200)
		m_palette_green[offset & 0xff] = data;
	else
		m_palette_blue[offset & 0xff] = data;

	m_palette_dirty = 1;
}


void vic3_device::port_w(offs_t offset, uint8_t data)
{
	DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
	offset &= 0x7f;

	/* offsets 0x00 -> 0x2e coincide with VICII */
	switch (offset)
	{
	case 0x01:
	case 0x03:
	case 0x05:
	case 0x07:
	case 0x09:
	case 0x0b:
	case 0x0d:
	case 0x0f:
									/* sprite y positions */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_sprites[offset / 2].y = SPRITE_Y_POS(offset / 2);
		}
		break;

	case 0x00:
	case 0x02:
	case 0x04:
	case 0x06:
	case 0x08:
	case 0x0a:
	case 0x0c:
	case 0x0e:
									/* sprite x positions */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_sprites[offset / 2].x = SPRITE_X_POS(offset / 2);
		}
		break;

	case 0x10:                          /* sprite x positions */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_sprites[0].x = SPRITE_X_POS(0);
			m_sprites[1].x = SPRITE_X_POS(1);
			m_sprites[2].x = SPRITE_X_POS(2);
			m_sprites[3].x = SPRITE_X_POS(3);
			m_sprites[4].x = SPRITE_X_POS(4);
			m_sprites[5].x = SPRITE_X_POS(5);
			m_sprites[6].x = SPRITE_X_POS(6);
			m_sprites[7].x = SPRITE_X_POS(7);
		}
		break;

	case 0x17:                          /* sprite y size */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x1d:                          /* sprite x size */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x1b:                          /* sprite background priority */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x1c:                          /* sprite multicolor mode select */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x27:
	case 0x28:
	case 0x29:
	case 0x2a:
	case 0x2b:
	case 0x2c:
	case 0x2d:
	case 0x2e:
									/* sprite colors */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x25:                          /* sprite multicolor */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_spritemulti[1] = SPRITE_MULTICOLOR1;
		}
		break;

	case 0x26:                          /* sprite multicolor */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_spritemulti[3] = SPRITE_MULTICOLOR2;
		}
		break;

	case 0x19:
		clear_interrupt(data & 0x0f);
		break;

	case 0x1a:                          /* irq mask */
		m_reg[offset] = data;
		set_interrupt(0);   // beamrider needs this
		break;

	case 0x11:
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			if (LINES25)
			{
				m_y_begin = 0;
				m_y_end = m_y_begin + 200;
			}
			else
			{
				m_y_begin = 4;
				m_y_end = m_y_begin + 192;
			}
		}
		break;

	case 0x12:
		if (data != m_reg[offset])
		{
			m_reg[offset] = data;
		}
		break;

	case 0x16:
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_x_begin = HORIZONTALPOS;
			m_x_end = m_x_begin + 320;
		}
		break;

	case 0x18:
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_videoaddr = VIDEOADDR;
			m_chargenaddr = CHARGENADDR;
			m_bitmapaddr = BITMAPADDR;
		}
		break;

	case 0x21:                          /* background color */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
		}
		break;

	case 0x22:                          /* background color 1 */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_multi[1] = m_colors[1] = MULTICOLOR1;
		}
		break;

	case 0x23:                          /* background color 2 */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_multi[2] = m_colors[2] = MULTICOLOR2;
		}
		break;

	case 0x24:                          /* background color 3 */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
			m_colors[3] = FOREGROUNDCOLOR;
		}
		break;

	case 0x20:                          /* framecolor */
		if (m_reg[offset] != data)
		{
			m_reg[offset] = data;
		}
		break;

	case 0x2f:
		DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
		m_reg[offset] = data;
		break;
	case 0x30:
		DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
		m_reg[offset] = data;
		m_port_changed_cb(offs_t(0), data);
		break;
	case 0x31:
		m_reg[offset] = data;
		if (data & 0x40)
			m_cpu->set_clock_scale(1.0);
		else
			m_cpu->set_clock_scale(1.0/3.5);
		break;
	case 0x32:
	case 0x33:
	case 0x34:
	case 0x35:
	case 0x36:
	case 0x37:
	case 0x38:
	case 0x39:
	case 0x3a:
	case 0x3b:
	case 0x3c:
	case 0x3d:
	case 0x3e:
	case 0x3f:
		m_reg[offset] = data;
		DBG_LOG(2, "vic write", ("%.2x:%.2x\n", offset, data));
		break;
	case 0x40:
	case 0x41:
	case 0x42:
	case 0x43:
	case 0x44:
	case 0x45:
	case 0x46:
	case 0x47:
		DBG_LOG(2, "vic plane write", ("%.2x:%.2x\n", offset, data));
		break;
	default:
		m_reg[offset] = data;
		break;
	}
}

uint8_t vic3_device::port_r(offs_t offset)
{
	int val = 0;
	offset &= 0x7f;

	/* offsets 0x00 -> 0x2e coincide with VICII */
	switch (offset)
	{
	case 0x11:
		val = (m_reg[offset] & ~0x80) | ((m_rasterline & 0x100) >> 1);
		break;

	case 0x12:
		val = m_rasterline & 0xff;
		break;

	case 0x16:
		val = m_reg[offset] | 0xc0;
		break;

	case 0x18:
		val = m_reg[offset] | 0x01;
		break;

	case 0x19:                          /* interrupt flag register */
		/* vic2_clear_interrupt(0xf); */
		val = m_reg[offset] | 0x70;
		break;

	case 0x1a:
		val = m_reg[offset] | 0xf0;
		break;

	case 0x1e:                          /* sprite to sprite collision detect */
		val = m_reg[offset];
		m_reg[offset] = 0;
		clear_interrupt(4);
		break;

	case 0x1f:                          /* sprite to background collision detect */
		val = m_reg[offset];
		m_reg[offset] = 0;
		clear_interrupt(2);
		break;

	case 0x20:
	case 0x21:
	case 0x22:
	case 0x23:
	case 0x24:
		val = m_reg[offset];
		break;

	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:
	case 0x07:
	case 0x08:
	case 0x09:
	case 0x0a:
	case 0x0b:
	case 0x0c:
	case 0x0d:
	case 0x0e:
	case 0x0f:
	case 0x10:
	case 0x17:
	case 0x1b:
	case 0x1c:
	case 0x1d:
	case 0x25:
	case 0x26:
	case 0x27:
	case 0x28:
	case 0x29:
	case 0x2a:
	case 0x2b:
	case 0x2c:
	case 0x2d:
	case 0x2e:
		val = m_reg[offset];
		break;

	case 0x2f:
	case 0x30:
		val = m_reg[offset];
		DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
		break;
	case 0x31:
	case 0x32:
	case 0x33:
	case 0x34:
	case 0x35:
	case 0x36:
	case 0x37:
	case 0x38:
	case 0x39:
	case 0x3a:
	case 0x3b:
	case 0x3c:
	case 0x3d:
	case 0x3e:
	case 0x3f:                         /* not used */
		val = m_reg[offset];
		DBG_LOG(2, "vic read", ("%.2x:%.2x\n", offset, val));
		break;
	case 0x40:
	case 0x41:
	case 0x42:
	case 0x43:
	case 0x44:
	case 0x45:
	case 0x46:
	case 0x47:
		DBG_LOG(2, "vic3 plane read", ("%.2x:%.2x\n", offset, val));
		break;
	default:
		val = m_reg[offset];
	}
	return val;
}


#define VIC3_MASK(M)                                                \
	if (M)                                                          \
	{                                                               \
		if (M & 0x01)                                               \
			colors[0] = m_c64_mem_r_cb(VIC3_ADDR(0) + offset);      \
		if (M & 0x02)                                               \
			colors[1] = m_c64_mem_r_cb(VIC3_ADDR(1) + offset) << 1; \
		if (M & 0x04)                                               \
			colors[2] = m_c64_mem_r_cb(VIC3_ADDR(2) + offset) << 2; \
		if (M & 0x08)                                               \
			colors[3] = m_c64_mem_r_cb(VIC3_ADDR(3) + offset) << 3; \
		if (M & 0x10)                                               \
			colors[4] = m_c64_mem_r_cb(VIC3_ADDR(4) + offset) << 4; \
		if (M & 0x20)                                               \
			colors[5] = m_c64_mem_r_cb(VIC3_ADDR(5) + offset) << 5; \
		if (M & 0x40)                                               \
			colors[6] = m_c64_mem_r_cb(VIC3_ADDR(6) + offset) << 6; \
		if (M & 0x80)                                               \
			colors[7] = m_c64_mem_r_cb(VIC3_ADDR(7) + offset) << 7; \
		for (int i = 7; i >= 0; i--)                                \
		{                                                           \
			int p = 0;                                              \
			if (M & 0x01)                                           \
			{                                                       \
				p = colors[0] & 0x01;                               \
				colors[0] >>= 1;                                    \
			}                                                       \
			if (M & 0x02)                                           \
			{                                                       \
				p |= colors[1] & 0x02;                              \
				colors[1] >>= 1;                                    \
			}                                                       \
			if (M & 0x04)                                           \
			{                                                       \
				p |= colors[2] & 0x04;                              \
				colors[2] >>= 1;                                    \
			}                                                       \
			if (M & 0x08)                                           \
			{                                                       \
				p |= colors[3] & 0x08;                              \
				colors[3] >>= 1;                                    \
			}                                                       \
			if (M & 0x10)                                           \
			{                                                       \
				p |= colors[4] & 0x10;                              \
				colors[4] >>= 1;                                    \
			}                                                       \
			if (M & 0x20)                                           \
			{                                                       \
				p |= colors[5] & 0x20;                              \
				colors[5] >>= 1;                                    \
			}                                                       \
			if (M & 0x40)                                           \
			{                                                       \
				p |= colors[6] & 0x40;                              \
				colors[6] >>= 1;                                    \
			}                                                       \
			if (M & 0x80)                                           \
			{                                                       \
				p |= colors[7] & 0x80;                              \
				colors[7] >>= 1;                                    \
			}                                                       \
			m_bitmap->pix(YPOS + y, XPOS + x + i) = p;              \
		}                                                           \
	}

#define VIC3_ADDR(a) VIC3_BITPLANE_IADDR(a)
void vic3_device::interlace_draw_block( int x, int y, int offset )
{
	int colors[8] = {0};

	switch (VIC3_BITPLANES_MASK)
	{
	case 0x05:
		VIC3_MASK(0x05)
		break;
	case 0x07:
		VIC3_MASK(0x07)
		break;
	case 0x0f:
		VIC3_MASK(0x0f)
		break;
	case 0x1f:
		VIC3_MASK(0x1f)
		break;
	case 0x7f:
		VIC3_MASK(0x7f)
		break;
	case 0xff:
		VIC3_MASK(0xff)
		break;
	default:
		if (VIC3_BITPLANES_MASK & 0x01)
			colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(0) + offset);

		if (VIC3_BITPLANES_MASK & 0x02)
			colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(1) + offset) << 1;

		if (VIC3_BITPLANES_MASK & 0x04)
			colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(2) + offset) << 2;

		if (VIC3_BITPLANES_MASK & 0x08)
			colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(3) + offset) << 3;

		if (VIC3_BITPLANES_MASK & 0x10)
			colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(4) + offset) << 4;

		if (VIC3_BITPLANES_MASK & 0x20)
			colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(5) + offset) << 5;

		if (VIC3_BITPLANES_MASK & 0x40)
			colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(6) + offset) << 6;

		if (VIC3_BITPLANES_MASK & 0x80)
			colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_IADDR(7) + offset) << 7;

		for (int i = 7; i >= 0; i--)
		{
			m_bitmap->pix(YPOS + y, XPOS + x + i) =
					(colors[0] & 0x01) | (colors[1] & 0x02) |
					(colors[2] & 0x04) | (colors[3] & 0x08) |
					(colors[4] & 0x10) | (colors[5] & 0x20) |
					(colors[6] & 0x40) | (colors[7] & 0x80);
			colors[0] >>= 1;
			colors[1] >>= 1;
			colors[2] >>= 1;
			colors[3] >>= 1;
			colors[4] >>= 1;
			colors[5] >>= 1;
			colors[6] >>= 1;
			colors[7] >>= 1;
		}
	}
}

#undef VIC3_ADDR
#define VIC3_ADDR(a) VIC3_BITPLANE_ADDR(a)
void vic3_device::draw_block( int x, int y, int offset )
{
	int colors[8] = {0};

	switch (VIC3_BITPLANES_MASK)
	{
	case 5:
		VIC3_MASK(0x05)
		break;
	case 7:
		VIC3_MASK(0x07)
		break;
	case 0xf:
		VIC3_MASK(0x0f)
		break;
	case 0x1f:
		VIC3_MASK(0x1f)
		break;
	case 0x7f:
		VIC3_MASK(0x7f)
		break;
	case 0xff:
		VIC3_MASK(0xff)
		break;
	default:
		if (VIC3_BITPLANES_MASK & 0x01)
			colors[0] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(0) + offset);

		if (VIC3_BITPLANES_MASK & 0x02)
			colors[1] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(1) + offset) << 1;

		if (VIC3_BITPLANES_MASK & 0x04)
			colors[2] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(2) + offset) << 2;

		if (VIC3_BITPLANES_MASK & 0x08)
			colors[3] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(3) + offset) << 3;

		if (VIC3_BITPLANES_MASK & 0x10)
			colors[4] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(4) + offset) << 4;

		if (VIC3_BITPLANES_MASK & 0x20)
			colors[5] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(5) + offset) << 5;

		if (VIC3_BITPLANES_MASK & 0x40)
			colors[6] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(6) + offset) << 6;

		if (VIC3_BITPLANES_MASK & 0x80)
			colors[7] = m_c64_mem_r_cb(VIC3_BITPLANE_ADDR(7) + offset) << 7;

		for (int i = 7; i >= 0; i--)
		{
			m_bitmap->pix(YPOS + y, XPOS + x + i) =
					(colors[0] & 0x01) | (colors[1] & 0x02) |
					(colors[2] & 0x04) | (colors[3] & 0x08) |
					(colors[4] & 0x10) | (colors[5] & 0x20) |
					(colors[6] & 0x40) | (colors[7] & 0x80);
			colors[0] >>= 1;
			colors[1] >>= 1;
			colors[2] >>= 1;
			colors[3] >>= 1;
			colors[4] >>= 1;
			colors[5] >>= 1;
			colors[6] >>= 1;
			colors[7] >>= 1;
		}
	}
}


void vic3_device::draw_bitplanes()
{
	const rectangle &visarea = screen().visible_area();

	if (VIC3_LINES == 400)
	{ /* interlaced! */
		for (int y1s = 0, offset = 0; y1s < 400; y1s += 16)
		{
			for (int x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
			{
				for (int y = y1s; y < y1s + 16; y += 2, offset++)
				{
					if (m_interlace)
						draw_block(x, y, offset);
					else
						interlace_draw_block(x, y + 1, offset);
				}
			}
		}
		m_interlace ^= 1;
	}
	else
	{
		for (int y1s = 0, offset = 0; y1s < 200; y1s += 8)
		{
			for (int x = 0; x < VIC3_BITPLANES_WIDTH; x += 8)
			{
				for (int y = y1s; y < y1s + 8; y++, offset++)
				{
					draw_block(x, y, offset);
				}
			}
		}
	}

	if (XPOS > 0)
	{
		rectangle vis(0, XPOS - 1, 0, visarea.bottom());
		m_bitmap->fill(FRAMECOLOR, vis);
	}

	if (XPOS + VIC3_BITPLANES_WIDTH < visarea.right())
	{
		rectangle vis(XPOS + VIC3_BITPLANES_WIDTH, visarea.right(), 0, visarea.bottom());
		m_bitmap->fill(FRAMECOLOR, vis);
	}

	if (YPOS > 0)
	{
		rectangle vis(0, visarea.right(), 0, YPOS - 1);
		m_bitmap->fill(FRAMECOLOR, vis);
	}

	if (YPOS + VIC3_LINES < visarea.bottom())
	{
		rectangle vis(0, visarea.right(), YPOS + VIC3_LINES, visarea.bottom());
		m_bitmap->fill(FRAMECOLOR, vis);
	}
}

void vic3_device::raster_interrupt_gen()
{
	int new_columns, new_rows;
	int i;

	m_rasterline++;
	if (m_rasterline >= m_lines)
	{
		m_rasterline = 0;
		if (m_palette_dirty)
			for (i = 0; i < 256; i++)
				set_pen_color(i, m_palette_red[i] << 4, m_palette_green[i] << 4, m_palette_blue[i] << 4);

		if (m_palette_dirty)
		{
			m_spritemulti[1] = SPRITE_MULTICOLOR1;
			m_spritemulti[3] = SPRITE_MULTICOLOR2;
			m_mono[0] = m_bitmapmulti[0] = m_multi[0] = m_colors[0] = BACKGROUNDCOLOR;
			m_multi[1] = m_colors[1] = MULTICOLOR1;
			m_multi[2] = m_colors[2] = MULTICOLOR2;
			m_colors[3] = FOREGROUNDCOLOR;
			m_palette_dirty = 0;
		}

		new_rows = 200;

		if (VIC3_BITPLANES)
		{
			new_columns = VIC3_BITPLANES_WIDTH;
			if (new_columns < 320)
				new_columns = 320; /*sprites resolution about 320x200 */
			new_rows = VIC3_LINES;
		}
		else if (VIC3_80COLUMNS)
		{
			new_columns = 640;
		}
		else
		{
			new_columns = 320;
		}
		if ((new_columns != m_columns) || (new_rows != m_rows))
		{
			m_rows = new_rows;
			m_columns = new_columns;
			if (m_type == vic3_type::PAL)
				screen().set_visible_area(
									VIC2_STARTVISIBLECOLUMNS + 32,
									VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1,
									VIC2_STARTVISIBLELINES + 34,
									VIC2_STARTVISIBLELINES + 34 + m_rows + 16 - 1);
			else
				screen().set_visible_area(
									VIC2_STARTVISIBLECOLUMNS + 34,
									VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1,
									VIC2_STARTVISIBLELINES + 10,
									VIC2_STARTVISIBLELINES + 10 + m_rows + 16 - 1);
		}
		if (VIC3_BITPLANES)
		{
			draw_bitplanes();
		}
		else
		{
			if (m_type == vic3_type::PAL)
			{
				if (m_on)
					vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
			}
			else
			{
				if (m_on)
					vic2_drawlines(m_lastline, m_lines, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
			}
		}

		for (i = 0; i < 8; i++)
			m_sprites[i].repeat = m_sprites[i].line = 0;

		m_lastline = 0;

		if (LIGHTPEN_BUTTON)
		{
			/* lightpen timer start */
			machine().scheduler().synchronize(timer_expired_delegate(FUNC(vic3_device::timer_timeout), this), 1);
		}

	}

	if (m_rasterline == C64_2_RASTERLINE(RASTERLINE))
	{
		set_interrupt(1);
	}

	if (m_on)
		if ((m_rasterline >= VIC2_FIRSTRASTERLINE) && (m_rasterline < (VIC2_FIRSTRASTERLINE + VIC2_VISIBLELINES)))
		{
			if (m_type == vic3_type::PAL)
			{
				if (m_on)
					vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 32, VIC2_STARTVISIBLECOLUMNS + 32 + m_columns + 16 - 1);
			}
			else
			{
				if (m_on)
					vic2_drawlines(m_rasterline - 1, m_rasterline, VIC2_STARTVISIBLECOLUMNS + 34, VIC2_STARTVISIBLECOLUMNS + 34 + m_columns + 16 - 1);
			}
		}
}

uint32_t vic3_device::video_update( bitmap_ind16 &bitmap, const rectangle &cliprect )
{
	copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect);
	return 0;
}