summaryrefslogblamecommitdiffstatshomepage
path: root/src/mess/video/fmtowns.c
blob: d14d92a66054298a437f7d28710e2ec04d465d31 (plain) (tree)































































































                                                                          
                                           
 

                                  
                                                                                      

                  





                                                                               

                  





                                                                               






                                                            
                                                                                               



























































































                                                                                           
                                             
 
                                           
                                             
         



                                                                                                             
         
                                                  
         



                                                                                                                
                                                                 


            



                                                                                                             
                                                                  




                                                
                                               














                                                                                                     



                                                          





































                                                                                                                       
                                                    



                                                                                                                     
                                                    














































































































                                                                                                                                                          
                                                  




                                                                                                        
                                                  






































                                                                                                             
                                          



                                                   
                                      

































































































                                                                                                                      
                                                
 
                    














                                                                             
                                               
























































































                                                                                      
                                                                                                                                        
 




                                       

                                                                                                                                   


































                                                                  
                                                          


                                                  


                                                                                                                        
                                                      

                                                                                                     


                                                                               

                                                                                                 





                                           



                                                                                                               


                                                                               

                                                                                                 







                                           
                                                                                                                         
 




                                       

                                                                                                                                   


































                                                                  
                                                          


                                                  

                                                                                                                        
                                                      

                                                                                                     


                                                                                 

                                                                                                 







                                           
                                                     
 
                                                                                                         

                               

                                                                                                 

                               
                                                 


                                      

                                                             
            
                                                             


                                      



                                                                                
















                                                                                                 
                                                                                                            








                                                                                      
                                                                                                     


                 

                                                             
            
                                              
 

                                                                                               

 
                                                                                                                                 
 







                       
                                                          
            
                                                          
 
                                               

                              
                                                                                                



                      
                                                        
                               

                                                                                    

                    
                                                                                                                              

                                      

                                                                                 


            

                                                                                    

                    
                                                                                                                              

                                      

                                                                                








                                                    
                                                             



                                                            
                                                                                                                      














                                                                    
                                                             


                                                            
                                                                                                                      


















                                                                    
                                                             


                                                            
                                                                                                                      






















                                                                    
                                                             


                                                            
                                                                                                                      


























                                                                    
                                                             


                                                            
                                                                                                                      



























                                                                    
                                                                                                                            
 






                      
                                               

                              
                                                                                                


                      
                                                          
            
                                                          


                      
                                                        
                               

                                                                                  

                    
                                                                                                                              

                                      

                                                                                 


            

                                                                                  

                    
                                                                                                                              

                                      

                                                                                







                                                    
                                                             


                                                            
                                                                      


                                                           


                                                                                








                                                     
                                                             


                                                            
                                                                        


                                                           


                                                                                
                                                             


                                                                                








                                                     
                                                             


                                                            
                                                                        


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                








                                                     
                                                             


                                                            
                                                                        


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                








                                                     
                                                             


                                                            
                                                                        


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                





                              
                                                                                                                           
 






                      
                                               

                              
                                                                                                


                      
                                                          
            
                                                          


                      
                                                        
                               

                                                                             

                    
                                                                                                                          

                                      

                                                                                 


            

                                                                             

                    
                                                                                                                          

                                      

                                                                                







                                                     
                                                             


                                                            
                                                                           


                                                             


                                                                                
                         
                                                                             


                                                           


                                                                                








                                                     
                                                             


                                                            
                                                                           


                                                             


                                                                                
                                                             


                                                                                
                         
                                                                             


                                                           


                                                                                
                                                             


                                                                                








                                                     
                                                             


                                                            
                                                                           


                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                         
                                                                             


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                








                                                     
                                                             


                                                            
                                                                           


                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                         
                                                                             


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                








                                                      
                                                             


                                                            
                                                                           


                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                         
                                                                             


                                                           


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                
                                                             


                                                                                





                              
                                                                                             
 







                                                     
                                                       
                                    
                                                         



                                                              
                                                                                                       
                                                   
                                                                                                 
                                         
                                                                                                               






                                                              
                                                                                                        
                                                   
                                                                                                 
                                         
                                                                                                                






                                                              
                                                                                                             
                                                   
                                                                                                 
                                         
                                                                                                                     









                                                           
                                                       
                                    
                                                         



                                                              
                                                                                                       
                                                   
                                                                                                 
                                         
                                                                                                               






                                                              
                                                                                                        
                                                   
                                                                                                 
                                         
                                                                                                                






                                                              
                                                                                                             
                                                   
                                                                                                 
                                         
                                                                                                                     







                                                           
                                                                                         
 

                         
                                                         



                            
                                                    













                                                         


                                                                                                 



                                                         



                                                                                                    



                                                         



                                                                                                 




























                                                                                 
                                                                          






                                      
                                   

















                                                                                    





                                 
                                                                                                                                                     




                             
                                                     

                                                 


                                                     
            
                                                      

 
                                                    

                                                                                          
                                       
                                                                    
                                                             
                                      

 
                                                  
 

                                          
                                                              
                                      
                                                                                                                                                                            
                                      
                                  
                                              
                                                              





                                         
                                                                                                                                    







                                                                                                         
                                                              

                                                                  
                                                                                                
                 
                                                              

                                                                  
                                                                                                



                 
                                                              

                                                                  
                                                                                                
                 
                                                              

                                                                  
                                                                                                




                 
                                                     
                             
                                                     



















                                                                                                                                                                            
/*
 * FM Towns video hardware
 *
 * Resolution: from 320x200 to 768x512
 *
 * Up to two graphics layers
 *
 * Sprites
 *
 * CRTC registers (16-bit):
 *
 *  0:  HSync width 1
 *  1:  HSync width 2
 *  4:  HSync total
 *  5:  VSync width 1
 *  6:  VSync width 2
 *  7:  Equalising pulse accountable time (what?)
 *  8:  VSync total
 *
 *  9:
 *  10: Graphic layer 0 horizontal start/end
 *  11:
 *  12: Graphic layer 1 horizontal start/end
 *
 *  13:
 *  14: Graphic layer 0 vertical start/end
 *  15:
 *  16: Graphic layer 1 vertical start/end
 *
 *  17: Graphic layer 0 initial address?
 *  18: Graphic layer 0 horizontal adjust
 *  19: Graphic layer 0 field indirect address offset
 *  20: Graphic layer 0 line indirect address offset
 *
 *  21-24: As above, but for Graphic layer 1
 *
 *  27: Layer zoom.     bit 0 = x2 horizontal zoom layer 0
 *  to be confirmed     bit 5 = x2 vertical zoom layer 0
 *                      bit 9 = x2 horizontal zoom layer 1
 *                      bit 13 = x2 vertical zoom layer 1
 *
 *  28: Control register 0
 *      VSync enable (bit 15) (blank display?)
 *      Scroll type (layer 0 = bit 4, layer 1 = bit 5)
 *          0 = spherical scroll, 1 = cylindrical scroll
 *
 *  29: Control register 1
 *      Dot clock (bits 1 and 0)
 *      0x00 = 28.6363MHz
 *      0x01 = 24.5454MHz
 *      0x02 = 25.175MHz
 *      0x03 = 21.0525MHz (default?)
 *
 *  30: Dummy register
 *
 *  31: Control register 2
 *
 *  Video registers:
 *
 *  0:  Graphic layer(s) type: (others likely exist)
 *      bit 4 = 2 layers
 *      bits 2-3 = layer 1 mode
 *      bits 0-1 = layer 0 mode
 *          mode: 1 = 16 colours, 2 = 256 colours, 3 = highcolour (16-bit)
 *                0 = disabled?
 *
 *  1:  Layer reverse (priority?) (bit 0)
 *      YM (bit 2) - unknown
 *      peltype (bits 4 and 5)
 *
 *
 *  Sprite registers:
 *
 *  0,1:    Maximum sprite (last one to render?) (10-bit)
 *
 *  1 (bit 7):  Enable sprite display
 *
 *  2,3:    X offset (9-bit)
 *
 *  4,5:    Y offset (9-bit)
 *
 *  6 (bit 4):  VRAM location (0=0x40000,1=0x60000)
 *
 */

#include "emu.h"
#include "machine/pic8259.h"
#include "machine/ram.h"
#include "includes/fmtowns.h"

//#define CRTC_REG_DISP 1
//#define SPR_DEBUG 1

//static UINT32 pshift;  // for debugging

void towns_state::towns_crtc_refresh_mode()
{
	unsigned int width,height;

	rectangle scr(0, m_video.towns_crtc_reg[4], 0, m_video.towns_crtc_reg[8] / 2);

	// layer 0
	width = m_video.towns_crtc_reg[10] - m_video.towns_crtc_reg[9];
	height = (m_video.towns_crtc_reg[14] - m_video.towns_crtc_reg[13]) / 2;
	m_video.towns_crtc_layerscr[0].min_x = scr.xcenter() - (width / 2);
	m_video.towns_crtc_layerscr[0].min_y = scr.ycenter() - (height / 2);
	m_video.towns_crtc_layerscr[0].max_x = scr.xcenter() + (width / 2);
	m_video.towns_crtc_layerscr[0].max_y = scr.ycenter() + (height / 2);

	// layer 1
	width = m_video.towns_crtc_reg[12] - m_video.towns_crtc_reg[11];
	height = (m_video.towns_crtc_reg[16] - m_video.towns_crtc_reg[15]) / 2;
	m_video.towns_crtc_layerscr[1].min_x = scr.xcenter() - (width / 2);
	m_video.towns_crtc_layerscr[1].min_y = scr.ycenter() - (height / 2);
	m_video.towns_crtc_layerscr[1].max_x = scr.xcenter() + (width / 2);
	m_video.towns_crtc_layerscr[1].max_y = scr.ycenter() + (height / 2);

	// sanity checks
	if(scr.max_x == 0 || scr.max_y == 0)
		return;
	if(scr.max_x <= scr.min_x || scr.max_y <= scr.min_y)
		return;

	machine().primary_screen->configure(scr.max_x+1,scr.max_y+1,scr,HZ_TO_ATTOSECONDS(60));
}

READ8_MEMBER( towns_state::towns_gfx_high_r )
{
	return m_towns_gfxvram[offset];
}

WRITE8_MEMBER( towns_state::towns_gfx_high_w )
{
	m_towns_gfxvram[offset] = data;
}

READ8_MEMBER( towns_state::towns_gfx_r )
{
	UINT8 ret = 0;

	if(m_towns_mainmem_enable != 0)
		return m_messram->pointer()[offset+0xc0000];

	offset = offset << 2;

	if(m_video.towns_vram_page_sel != 0)
		offset += 0x20000;

	ret = (((m_towns_gfxvram[offset] >> m_video.towns_vram_rplane) << 7) & 0x80)
		| (((m_towns_gfxvram[offset] >> m_video.towns_vram_rplane) << 2) & 0x40)
		| (((m_towns_gfxvram[offset+1] >> m_video.towns_vram_rplane) << 5) & 0x20)
		| (((m_towns_gfxvram[offset+1] >> m_video.towns_vram_rplane)) & 0x10)
		| (((m_towns_gfxvram[offset+2] >> m_video.towns_vram_rplane) << 3) & 0x08)
		| (((m_towns_gfxvram[offset+2] >> m_video.towns_vram_rplane) >> 2) & 0x04)
		| (((m_towns_gfxvram[offset+3] >> m_video.towns_vram_rplane) << 1) & 0x02)
		| (((m_towns_gfxvram[offset+3] >> m_video.towns_vram_rplane) >> 4) & 0x01);

	return ret;
}

WRITE8_MEMBER( towns_state::towns_gfx_w )
{
	if(m_towns_mainmem_enable != 0)
	{
		m_messram->pointer()[offset+0xc0000] = data;
		return;
	}
	offset = offset << 2;
	if(m_video.towns_vram_page_sel != 0)
		offset += 0x20000;
	if(m_video.towns_vram_wplane & 0x08)
	{
		m_towns_gfxvram[offset] &= ~0x88;
		m_towns_gfxvram[offset] |= ((data & 0x80) >> 4) | ((data & 0x40) << 1);
		m_towns_gfxvram[offset + 1] &= ~0x88;
		m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 2) | ((data & 0x10) << 3);
		m_towns_gfxvram[offset + 2] &= ~0x88;
		m_towns_gfxvram[offset + 2] |= ((data & 0x08)) | ((data & 0x04) << 5);
		m_towns_gfxvram[offset + 3] &= ~0x88;
		m_towns_gfxvram[offset + 3] |= ((data & 0x02) << 2) | ((data & 0x01) << 7);
	}
	if(m_video.towns_vram_wplane & 0x04)
	{
		m_towns_gfxvram[offset] &= ~0x44;
		m_towns_gfxvram[offset] |= ((data & 0x80) >> 5) | ((data & 0x40));
		m_towns_gfxvram[offset + 1] &= ~0x44;
		m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 3) | ((data & 0x10) << 2);
		m_towns_gfxvram[offset + 2] &= ~0x44;
		m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 1) | ((data & 0x04) << 4);
		m_towns_gfxvram[offset + 3] &= ~0x44;
		m_towns_gfxvram[offset + 3] |= ((data & 0x02) << 1) | ((data & 0x01) << 6);
	}
	if(m_video.towns_vram_wplane & 0x02)
	{
		m_towns_gfxvram[offset] &= ~0x22;
		m_towns_gfxvram[offset] |= ((data & 0x80) >> 6) | ((data & 0x40) >> 1);
		m_towns_gfxvram[offset + 1] &= ~0x22;
		m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 4) | ((data & 0x10) << 1);
		m_towns_gfxvram[offset + 2] &= ~0x22;
		m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 2) | ((data & 0x04) << 3);
		m_towns_gfxvram[offset + 3] &= ~0x22;
		m_towns_gfxvram[offset + 3] |= ((data & 0x02)) | ((data & 0x01) << 5);
	}
	if(m_video.towns_vram_wplane & 0x01)
	{
		m_towns_gfxvram[offset] &= ~0x11;
		m_towns_gfxvram[offset] |= ((data & 0x80) >> 7) | ((data & 0x40) >> 2);
		m_towns_gfxvram[offset + 1] &= ~0x11;
		m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 5) | ((data & 0x10));
		m_towns_gfxvram[offset + 2] &= ~0x11;
		m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 3) | ((data & 0x04) << 2);
		m_towns_gfxvram[offset + 3] &= ~0x11;
		m_towns_gfxvram[offset + 3] |= ((data & 0x02) >> 1) | ((data & 0x01) << 4);
	}
}

void towns_state::towns_update_kanji_offset()
{
	// this is a little over the top...
	if(m_video.towns_kanji_code_h < 0x30)
	{
		m_video.towns_kanji_offset = ((m_video.towns_kanji_code_l & 0x1f) << 4)
							| (((m_video.towns_kanji_code_l - 0x20) & 0x20) << 8)
							| (((m_video.towns_kanji_code_l - 0x20) & 0x40) << 6)
							| ((m_video.towns_kanji_code_h & 0x07) << 9);
	}
	else if(m_video.towns_kanji_code_h < 0x70)
	{
		m_video.towns_kanji_offset = ((m_video.towns_kanji_code_l & 0x1f) << 4)
							+ (((m_video.towns_kanji_code_l - 0x20) & 0x60) << 8)
							+ ((m_video.towns_kanji_code_h & 0x0f) << 9)
							+ (((m_video.towns_kanji_code_h - 0x30) & 0x70) * 0xc00)
							+ 0x8000;
	}
	else
	{
		m_video.towns_kanji_offset = ((m_video.towns_kanji_code_l & 0x1f) << 4)
							| (((m_video.towns_kanji_code_l - 0x20) & 0x20) << 8)
							| (((m_video.towns_kanji_code_l - 0x20) & 0x40) << 6)
							| ((m_video.towns_kanji_code_h & 0x07) << 9)
							| 0x38000;
	}
}

READ8_MEMBER( towns_state::towns_video_cff80_r )
{
	UINT8* ROM = memregion("user")->base();

	switch(offset)
	{
		case 0x00:  // mix register
			return m_video.towns_crtc_mix;
		case 0x01:  // read/write plane select (bit 0-3 write, bit 6-7 read)
			return ((m_video.towns_vram_rplane << 6) & 0xc0) | m_video.towns_vram_wplane;
		case 0x02:  // display planes (bits 0-2,5), display page select (bit 4)
			return m_video.towns_display_plane | m_video.towns_display_page_sel;
		case 0x03:  // VRAM page select (bit 5)
			if(m_video.towns_vram_page_sel != 0)
				return 0x10;
			else
				return 0x00;
		case 0x06:
			if(m_video.towns_vblank_flag != 0)
				return 0x10;
			else
				return 0x00;
		case 0x16:  // Kanji character data
			return ROM[(m_video.towns_kanji_offset << 1) + 0x180000];
		case 0x17:  // Kanji character data
			return ROM[(m_video.towns_kanji_offset++ << 1) + 0x180001];
		case 0x19:  // ANK CG ROM
			if(m_towns_ankcg_enable != 0)
				return 0x01;
			else
				return 0x00;
		default:
			logerror("VGA: read from invalid or unimplemented memory-mapped port %05x\n",0xcff80+offset*4);
	}

	return 0;
}

WRITE8_MEMBER( towns_state::towns_video_cff80_w )
{
	switch(offset)
	{
		case 0x00:  // mix register
			m_video.towns_crtc_mix = data;
			break;
		case 0x01:  // read/write plane select (bit 0-3 write, bit 6-7 read)
			m_video.towns_vram_wplane = data & 0x0f;
			m_video.towns_vram_rplane = (data & 0xc0) >> 6;
			towns_update_video_banks(space);
			//logerror("VGA: VRAM wplane select = 0x%02x\n",towns_vram_wplane);
			break;
		case 0x02:  // display plane (bits 0-2), display page select (bit 4)
			m_video.towns_display_plane = data & 0x27;
			m_video.towns_display_page_sel = data & 0x10;
			break;
		case 0x03:  // VRAM page select (bit 4)
			m_video.towns_vram_page_sel = data & 0x10;
			break;
		case 0x14:  // Kanji offset (high)
			m_video.towns_kanji_code_h = data & 0x7f;
			towns_update_kanji_offset();
			//logerror("VID: Kanji code set (high) = %02x %02x\n",towns_kanji_code_h,towns_kanji_code_l);
			break;
		case 0x15:  // Kanji offset (low)
			m_video.towns_kanji_code_l = data & 0x7f;
			towns_update_kanji_offset();
			//logerror("VID: Kanji code set (low) = %02x %02x\n",towns_kanji_code_h,towns_kanji_code_l);
			break;
		case 0x19:  // ANK CG ROM
			m_towns_ankcg_enable = data & 0x01;
			towns_update_video_banks(space);
			break;
		default:
			logerror("VGA: write %08x to invalid or unimplemented memory-mapped port %05x\n",data,0xcff80+offset);
	}
}

READ8_MEMBER( towns_state::towns_video_cff80_mem_r )
{
	if(m_towns_mainmem_enable != 0)
		return m_messram->pointer()[offset+0xcff80];

	return towns_video_cff80_r(space,offset);
}

WRITE8_MEMBER( towns_state::towns_video_cff80_mem_w )
{
	if(m_towns_mainmem_enable != 0)
	{
		m_messram->pointer()[offset+0xcff80] = data;
		return;
	}
	towns_video_cff80_w(space,offset,data);
}

/*
 *  port 0x440-0x443 - CRTC
 *      0x440 = register select
 *      0x442/3 = register data (16-bit)
 *      0x448 = shifter register select
 *      0x44a = shifter register data (8-bit)
 *
 */
READ8_MEMBER(towns_state::towns_video_440_r)
{
	UINT8 ret = 0;
	UINT16 xpos,ypos;

	switch(offset)
	{
		case 0x00:
			return m_video.towns_crtc_sel;
		case 0x02:
//          logerror("CRTC: reading register %i (0x442) [%04x]\n",towns_crtc_sel,towns_crtc_reg[towns_crtc_sel]);
			if(m_video.towns_crtc_sel == 30)
					return 0x00;
			return m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0x00ff;
		case 0x03:
//          logerror("CRTC: reading register %i (0x443) [%04x]\n",towns_crtc_sel,towns_crtc_reg[towns_crtc_sel]);
			if(m_video.towns_crtc_sel == 30)
			{
				// check video position
				xpos = space.machine().primary_screen->hpos();
				ypos = space.machine().primary_screen->vpos();

				if(xpos < (m_video.towns_crtc_reg[0] & 0xfe))
					ret |= 0x02;
				if(ypos < (m_video.towns_crtc_reg[6] & 0x1f))
					ret |= 0x04;
				if(xpos < m_video.towns_crtc_layerscr[0].max_x && xpos > m_video.towns_crtc_layerscr[0].min_x)
					ret |= 0x10;
				if(xpos < m_video.towns_crtc_layerscr[1].max_x && xpos > m_video.towns_crtc_layerscr[1].min_x)
					ret |= 0x20;
				if(ypos < m_video.towns_crtc_layerscr[0].max_y && ypos > m_video.towns_crtc_layerscr[0].min_y)
					ret |= 0x40;
				if(ypos < m_video.towns_crtc_layerscr[1].max_y && ypos > m_video.towns_crtc_layerscr[1].min_y)
					ret |= 0x80;

				return ret;
			}
			return (m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0xff00) >> 8;
		case 0x08:
			return m_video.towns_video_sel;
		case 0x0a:
			logerror("Video: reading register %i (0x44a) [%02x]\n",m_video.towns_video_sel,m_video.towns_video_reg[m_video.towns_video_sel]);
			return m_video.towns_video_reg[m_video.towns_video_sel];
		case 0x0c:
			if(m_video.towns_dpmd_flag != 0)
			{
				m_video.towns_dpmd_flag = 0;
				ret |= 0x80;
			}
			ret |= (m_video.towns_sprite_flag ? 0x02 : 0x00);  // Sprite drawing flag
			ret |= m_video.towns_sprite_page & 0x01;
			return ret;
		case 0x10:
			return m_video.towns_sprite_sel;
		case 0x12:
			logerror("SPR: reading register %i (0x452) [%02x]\n",m_video.towns_sprite_sel,m_video.towns_sprite_reg[m_video.towns_sprite_sel]);
			return m_video.towns_sprite_reg[m_video.towns_sprite_sel];
		//default:
			//logerror("VID: read port %04x\n",offset+0x440);
	}
	return 0x00;
}

WRITE8_MEMBER(towns_state::towns_video_440_w)
{
	switch(offset)
	{
		case 0x00:
			m_video.towns_crtc_sel = data;
			break;
		case 0x02:
//          logerror("CRTC: writing register %i (0x442) [%02x]\n",towns_crtc_sel,data);
			m_video.towns_crtc_reg[m_video.towns_crtc_sel] =
				(m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0xff00) | data;
			towns_crtc_refresh_mode();
			break;
		case 0x03:
//          logerror("CRTC: writing register %i (0x443) [%02x]\n",towns_crtc_sel,data);
			m_video.towns_crtc_reg[m_video.towns_crtc_sel] =
				(m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0x00ff) | (data << 8);
			towns_crtc_refresh_mode();
			break;
		case 0x08:
			m_video.towns_video_sel = data & 0x01;
			break;
		case 0x0a:
			logerror("Video: writing register %i (0x44a) [%02x]\n",m_video.towns_video_sel,data);
			m_video.towns_video_reg[m_video.towns_video_sel] = data;
			break;
		case 0x10:
			m_video.towns_sprite_sel = data & 0x07;
			break;
		case 0x12:
			logerror("SPR: writing register %i (0x452) [%02x]\n",m_video.towns_sprite_sel,data);
			m_video.towns_sprite_reg[m_video.towns_sprite_sel] = data;
			break;
		default:
			logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0x440);
	}
}

READ8_MEMBER(towns_state::towns_video_5c8_r)
{
	//logerror("VID: read port %04x\n",offset+0x5c8);
	switch(offset)
	{
		case 0x00:  // 0x5c8 - disable TVRAM?
		if(m_video.towns_tvram_enable != 0)
		{
			m_video.towns_tvram_enable = 0;
			return 0x80;
		}
		else
			return 0x00;
	}
	return 0x00;
}

WRITE8_MEMBER(towns_state::towns_video_5c8_w)
{
	pic8259_device* dev = m_pic_slave;

	switch(offset)
	{
		case 0x02:  // 0x5ca - VSync clear?
			dev->ir3_w(0);
			if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set low\n");
			//towns_vblank_flag = 0;
			break;
	}
	logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0x5c8);
}

/* Video/CRTC
 *
 * 0xfd90 - palette colour select
 * 0xfd92/4/6 - BRG value
 * 0xfd98-9f  - degipal(?)
 */
READ8_MEMBER(towns_state::towns_video_fd90_r)
{
	UINT8 ret = 0;
	UINT16 xpos;

//    logerror("VID: read port %04x\n",offset+0xfd90);
	switch(offset)
	{
		case 0x00:
			return m_video.towns_palette_select;
		case 0x02:
			return m_video.towns_palette_b[m_video.towns_palette_select];
		case 0x04:
			return m_video.towns_palette_r[m_video.towns_palette_select];
		case 0x06:
			return m_video.towns_palette_g[m_video.towns_palette_select];
		case 0x08:
		case 0x09:
		case 0x0a:
		case 0x0b:
		case 0x0c:
		case 0x0d:
		case 0x0e:
		case 0x0f:
			return m_video.towns_degipal[offset-0x08];
		case 0x10:  // "sub status register"
			// check video position
			xpos = space.machine().primary_screen->hpos();

			if(xpos < m_video.towns_crtc_layerscr[0].max_x && xpos > m_video.towns_crtc_layerscr[0].min_x)
				ret |= 0x02;
			if(m_video.towns_vblank_flag)
				ret |= 0x01;
			return ret;
	}
	return 0x00;
}

WRITE8_MEMBER(towns_state::towns_video_fd90_w)
{
	switch(offset)
	{
		case 0x00:
			m_video.towns_palette_select = data;
			break;
		case 0x02:
			m_video.towns_palette_b[m_video.towns_palette_select] = data;
			break;
		case 0x04:
			m_video.towns_palette_r[m_video.towns_palette_select] = data;
			break;
		case 0x06:
			m_video.towns_palette_g[m_video.towns_palette_select] = data;
			break;
		case 0x08:
		case 0x09:
		case 0x0a:
		case 0x0b:
		case 0x0c:
		case 0x0d:
		case 0x0e:
		case 0x0f:
			m_video.towns_degipal[offset-0x08] = data;
			m_video.towns_dpmd_flag = 1;
			break;
		case 0x10:
			m_video.towns_layer_ctrl = data;
			break;
	}
	logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0xfd90);
}

READ8_MEMBER(towns_state::towns_video_ff81_r)
{
	return ((m_video.towns_vram_rplane << 6) & 0xc0) | m_video.towns_vram_wplane;
}

WRITE8_MEMBER(towns_state::towns_video_ff81_w)
{
	m_video.towns_vram_wplane = data & 0x0f;
	m_video.towns_vram_rplane = (data & 0xc0) >> 6;
	towns_update_video_banks(space);
	logerror("VGA: VRAM wplane select (I/O) = 0x%02x\n",m_video.towns_vram_wplane);
}

READ8_MEMBER(towns_state::towns_video_unknown_r)
{
	return 0x00;
}

/*
 *  Sprite RAM, low memory
 *  Writing to 0xc8xxx or 0xcaxxx activates TVRAM
 *  Writing to I/O port 0x5c8 disables TVRAM
 *     (bit 7 returns high if TVRAM was previously active)
 *
 *  In TVRAM mode:
 *    0xc8000-0xc8fff: ASCII text (2 bytes each: ISO646 code, then attribute)
 *    0xca000-0xcafff: JIS code
 */
READ8_MEMBER(towns_state::towns_spriteram_low_r)
{
	UINT8* RAM = m_messram->pointer();
	UINT8* ROM = memregion("user")->base();

	if(offset < 0x1000)
	{  // 0xc8000-0xc8fff
		if(m_towns_mainmem_enable == 0)
		{
//          if(towns_tvram_enable == 0)
//              return towns_sprram[offset];
//          else
				return m_towns_txtvram[offset];
		}
		else
			return RAM[offset + 0xc8000];
	}
	if(offset >= 0x1000 && offset < 0x2000)
	{  // 0xc9000-0xc9fff
		return RAM[offset + 0xc9000];
	}
	if(offset >= 0x2000 && offset < 0x3000)
	{  // 0xca000-0xcafff
		if(m_towns_mainmem_enable == 0)
		{
			if(m_towns_ankcg_enable != 0 && offset < 0x2800)
				return ROM[0x180000 + 0x3d000 + (offset-0x2000)];
//          if(towns_tvram_enable == 0)
//              return m_towns_sprram[offset];
//          else
				return m_towns_txtvram[offset];
		}
		else
			return RAM[offset + 0xca000];
	}
	return 0x00;
}

WRITE8_MEMBER(towns_state::towns_spriteram_low_w)
{
	UINT8* RAM = m_messram->pointer();

	if(offset < 0x1000)
	{  // 0xc8000-0xc8fff
		m_video.towns_tvram_enable = 1;
		if(m_towns_mainmem_enable == 0)
			m_towns_txtvram[offset] = data;
		else
			RAM[offset + 0xc8000] = data;
	}
	if(offset >= 0x1000 && offset < 0x2000)
	{
		RAM[offset + 0xc9000] = data;
	}
	if(offset >= 0x2000 && offset < 0x3000)
	{  // 0xca000-0xcafff
		m_video.towns_tvram_enable = 1;
		if(m_towns_mainmem_enable == 0)
			m_towns_txtvram[offset] = data;
		else
			RAM[offset + 0xca000] = data;
	}
}

READ8_MEMBER( towns_state::towns_spriteram_r )
{
	return m_towns_txtvram[offset];
}

WRITE8_MEMBER( towns_state::towns_spriteram_w )
{
	m_towns_txtvram[offset] = data;
}

/*
 *  Sprites
 *
 *  Max. 1024, 16x16, 16 colours per sprite
 *  128kB Sprite RAM (8kB attributes, 120kB pattern/colour data)
 *  Sprites are rendered directly to VRAM layer 1 (VRAM offset 0x40000 or 0x60000)
 *
 *  Sprite RAM format:
 *      4 words per sprite
 *      +0: X position (10-bit)
 *      +2: Y position (10-bit)
 *      +4: Sprite Attribute
 *          bit 15: enforce offsets (regs 2-5)
 *          bit 12,13: flip sprite
 *          bits 10-0: Sprite RAM offset containing sprite pattern
 *          TODO: other attributes (zoom?)
 *      +6: Sprite Colour
 *          bit 15: use colour data in located in sprite RAM offset in bits 11-0 (x32)
 */
void towns_state::render_sprite_4(UINT32 poffset, UINT32 coffset, UINT16 x, UINT16 y, UINT16 xflip, UINT16 yflip, const rectangle* rect)
{
	UINT16 xpos,ypos;
	UINT16 col,pixel;
	UINT32 voffset;
	UINT16 xstart,xend,ystart,yend;
	int xdir,ydir;
	int width = (m_video.towns_crtc_reg[12] - m_video.towns_crtc_reg[11]) / (((m_video.towns_crtc_reg[27] & 0x0f00) >> 8)+1);
	int height = (m_video.towns_crtc_reg[16] - m_video.towns_crtc_reg[15]) / (((m_video.towns_crtc_reg[27] & 0xf000) >> 12)+2);

	if(xflip)
	{
		xstart = x+14;
		xend = x-2;
		xdir = -2;
	}
	else
	{
		xstart = x+1;
		xend = x+17;
		xdir = 2;
	}
	if(yflip)
	{
		ystart = y+15;
		yend = y-1;
		ydir = -1;
	}
	else
	{
		ystart = y;
		yend = y+16;
		ydir = 1;
	}
	xstart &= 0x1ff;
	xend &= 0x1ff;
	ystart &= 0x1ff;
	yend &= 0x1ff;
	poffset &= 0x1ffff;

	for(ypos=ystart;ypos!=yend;ypos+=ydir,ypos&=0x1ff)
	{
		for(xpos=xstart;xpos!=xend;xpos+=xdir,xpos&=0x1ff)
		{
			if(m_video.towns_sprite_page != 0)
				voffset = 0x20000;
			else
				voffset = 0x00000;
			pixel = (m_towns_txtvram[poffset] & 0xf0) >> 4;
			col = m_towns_txtvram[coffset+(pixel*2)] | (m_towns_txtvram[coffset+(pixel*2)+1] << 8);
			voffset += (m_video.towns_crtc_reg[24] * 4) * (ypos & 0x1ff);  // scanline size in bytes * y pos
			voffset += (xpos & 0x1ff) * 2;
			if((m_video.towns_sprite_page != 0 && voffset > 0x1ffff && voffset < 0x40000)
					|| (m_video.towns_sprite_page == 0 && voffset < 0x20000))
			{
				if(xpos < width && ypos < height && pixel != 0)
				{
					m_towns_gfxvram[0x40000+voffset+1] = (col & 0xff00) >> 8;
					m_towns_gfxvram[0x40000+voffset] = col & 0x00ff;
				}
			}
			if(xflip)
				voffset+=2;
			else
				voffset-=2;
			pixel = m_towns_txtvram[poffset] & 0x0f;
			col = m_towns_txtvram[coffset+(pixel*2)] | (m_towns_txtvram[coffset+(pixel*2)+1] << 8);
			if((m_video.towns_sprite_page != 0 && voffset > 0x1ffff && voffset < 0x40000)
					|| (m_video.towns_sprite_page == 0 && voffset < 0x20000))
			{
				if(xpos < width && ypos < height && pixel != 0)
				{
					m_towns_gfxvram[0x40000+voffset+1] = (col & 0xff00) >> 8;
					m_towns_gfxvram[0x40000+voffset] = col & 0x00ff;
				}
			}
			poffset++;
			poffset &= 0x1ffff;
		}
	}
}

void towns_state::render_sprite_16(UINT32 poffset, UINT16 x, UINT16 y, UINT16 xflip, UINT16 yflip, const rectangle* rect)
{
	UINT16 xpos,ypos;
	UINT16 col;
	UINT32 voffset;
	UINT16 xstart,ystart,xend,yend;
	int xdir,ydir;
	int width = (m_video.towns_crtc_reg[12] - m_video.towns_crtc_reg[11]) / (((m_video.towns_crtc_reg[27] & 0x0f00) >> 8)+1);
	int height = (m_video.towns_crtc_reg[16] - m_video.towns_crtc_reg[15]) / (((m_video.towns_crtc_reg[27] & 0xf000) >> 12)+2);

	if(xflip)
	{
		xstart = x+16;
		xend = x;
		xdir = -1;
	}
	else
	{
		xstart = x+1;
		xend = x+17;
		xdir = 1;
	}
	if(yflip)
	{
		ystart = y+15;
		yend = y-1;
		ydir = -1;
	}
	else
	{
		ystart = y;
		yend = y+16;
		ydir = 1;
	}
	xstart &= 0x1ff;
	xend &= 0x1ff;
	ystart &= 0x1ff;
	yend &= 0x1ff;
	poffset &= 0x1ffff;

	for(ypos=ystart;ypos!=yend;ypos+=ydir,ypos&=0x1ff)
	{
		for(xpos=xstart;xpos!=xend;xpos+=xdir,xpos&=0x1ff)
		{
			if(m_video.towns_sprite_page != 0)
				voffset = 0x20000;
			else
				voffset = 0x00000;
			col = m_towns_txtvram[poffset] | (m_towns_txtvram[poffset+1] << 8);
			voffset += (m_video.towns_crtc_reg[24] * 4) * (ypos & 0x1ff);  // scanline size in bytes * y pos
			voffset += (xpos & 0x1ff) * 2;
			if((m_video.towns_sprite_page != 0 && voffset > 0x1ffff && voffset < 0x40000)
					|| (m_video.towns_sprite_page == 0 && voffset < 0x20000))
			{
				if(xpos < width && ypos < height && col < 0x8000)
				{
					m_towns_gfxvram[0x40000+voffset+1] = (col & 0xff00) >> 8;
					m_towns_gfxvram[0x40000+voffset] = col & 0x00ff;
				}
			}
			poffset+=2;
			poffset &= 0x1ffff;
		}
	}
}

void towns_state::draw_sprites(const rectangle* rect)
{
	UINT16 sprite_limit = (m_video.towns_sprite_reg[0] | (m_video.towns_sprite_reg[1] << 8)) & 0x3ff;
	int n;
	UINT16 x,y,attr,colour;
	UINT16 xoff = (m_video.towns_sprite_reg[2] | (m_video.towns_sprite_reg[3] << 8)) & 0x1ff;
	UINT16 yoff = (m_video.towns_sprite_reg[4] | (m_video.towns_sprite_reg[5] << 8)) & 0x1ff;
	UINT32 poffset,coffset;

	if(!(m_video.towns_sprite_reg[1] & 0x80))
		return;

	// clears VRAM for each frame?
	if(m_video.towns_sprite_page == 0)
		memset(m_towns_gfxvram+0x40000,0x80,0x20000);
	else
		memset(m_towns_gfxvram+0x60000,0x80,0x20000);

	for(n=sprite_limit;n<1024;n++)
	{
		x = m_towns_txtvram[8*n] | (m_towns_txtvram[8*n+1] << 8);
		y = m_towns_txtvram[8*n+2] | (m_towns_txtvram[8*n+3] << 8);
		attr = m_towns_txtvram[8*n+4] | (m_towns_txtvram[8*n+5] << 8);
		colour = m_towns_txtvram[8*n+6] | (m_towns_txtvram[8*n+7] << 8);
		if(attr & 0x8000)
		{
			x += xoff;
			y += yoff;
		}
		x &= 0x1ff;
		y &= 0x1ff;

		if(colour & 0x8000)
		{
			poffset = (attr & 0x3ff) << 7;
			coffset = (colour & 0xfff) << 5;
#ifdef SPR_DEBUG
			printf("Sprite4 #%i, X %i Y %i Attr %04x Col %04x Poff %08x Coff %08x\n",
				n,x,y,attr,colour,poffset,coffset);
#endif
			if(!(colour & 0x2000))
				render_sprite_4((poffset)&0x1ffff,coffset,x,y,attr&0x2000,attr&0x1000,rect);
		}
		else
		{
			poffset = (attr & 0x3ff) << 7;
#ifdef SPR_DEBUG
			printf("Sprite16 #%i, X %i Y %i Attr %04x Col %04x Poff %08x",
				n,x,y,attr,colour,poffset);
#endif
			if(!(colour & 0x2000))
				render_sprite_16((poffset)&0x1ffff,x,y,attr&0x2000,attr&0x1000,rect);
		}
	}

	if(m_video.towns_sprite_page == 0)  // flip VRAM page
		m_video.towns_sprite_page = 1;
	else
		m_video.towns_sprite_page = 0;

	m_video.towns_sprite_flag = 1;  // we are now drawing
	m_video.sprite_timer->adjust(m_maincpu->cycles_to_attotime(128 * (1025-sprite_limit)));
}

void towns_state::towns_crtc_draw_scan_layer_hicolour(bitmap_rgb32 &bitmap,const rectangle* rect,int layer,int line,int scanline)
{
	UINT32 off = 0;
	int x;
	UINT16 colour;
	int hzoom = 1;
	int linesize;
	UINT32 scroll;

	if(layer == 0)
		linesize = m_video.towns_crtc_reg[20] * 4;
	else
		linesize = m_video.towns_crtc_reg[24] * 4;

	if(m_video.towns_display_page_sel != 0)
		off = 0x20000;

//  if((layer == 1) && (m_video.towns_sprite_reg[1] & 0x80) && (m_video.towns_sprite_page == 1))
//      off = 0x20000;

	if(layer != 0)
	{
		if(!(m_video.towns_video_reg[0] & 0x10))
			return;
		if(!(m_video.towns_crtc_reg[28] & 0x10))
			off += (m_video.towns_crtc_reg[21]) << 2;  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[21] & 0xfc00) << 2) | (((m_video.towns_crtc_reg[21] & 0x3ff) << 2));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[22]);
		hzoom = ((m_video.towns_crtc_reg[27] & 0x0f00) >> 8) + 1;
	}
	else
	{
		if(!(m_video.towns_crtc_reg[28] & 0x20))
			off += (m_video.towns_crtc_reg[17]) << 2;  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[17] & 0xfc00) << 2) | (((m_video.towns_crtc_reg[17] & 0x3ff) << 2));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]);
		hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
	}

	off += line * linesize;
	off &= ~0x01;

	if(hzoom == 1)
	{
		for(x=rect->min_x;x<rect->max_x;x++)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer

			colour = (m_towns_gfxvram[off+(layer*0x40000)+1] << 8) | m_towns_gfxvram[off+(layer*0x40000)];
			if(colour < 0x8000)
			{
				bitmap.pix32(scanline, x) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
			}
			off+=2;
		}
	}

	if(hzoom == 2)
	{  // x2 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=2)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = (m_towns_gfxvram[off+(layer*0x40000)+1] << 8) | m_towns_gfxvram[off+(layer*0x40000)];
			if(colour < 0x8000)
			{
				bitmap.pix32(scanline, x) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+1) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
			}
			off+=2;
		}
	}

	if(hzoom == 3)
	{  // x3 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=3)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = (m_towns_gfxvram[off+(layer*0x40000)+1] << 8) | m_towns_gfxvram[off+(layer*0x40000)];
			if(colour < 0x8000)
			{
				bitmap.pix32(scanline, x) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+1) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+2) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
			}
			off+=2;
		}
	}

	if(hzoom == 4)
	{  // x4 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=4)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = (m_towns_gfxvram[off+(layer*0x40000)+1] << 8) | m_towns_gfxvram[off+(layer*0x40000)];
			if(colour < 0x8000)
			{
				bitmap.pix32(scanline, x) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+1) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+2) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+3) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
			}
			off+=2;
		}
	}

	if(hzoom == 5)
	{  // x5 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=5)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = (m_towns_gfxvram[off+(layer*0x40000)+1] << 8) | m_towns_gfxvram[off+(layer*0x40000)];
			if(colour < 0x8000)
			{
				bitmap.pix32(scanline, x) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+1) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+2) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+3) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
				bitmap.pix32(scanline, x+4) =
					((colour & 0x001f) << 3)
					| ((colour & 0x7c00) << 1)
					| ((colour & 0x03e0) << 14);
			}
			off+=2;
		}
	}
}

void towns_state::towns_crtc_draw_scan_layer_256(bitmap_rgb32 &bitmap,const rectangle* rect,int layer,int line,int scanline)
{
	int off = 0;
	int x;
	UINT8 colour;
	int hzoom = 1;
	int linesize;
	UINT32 scroll;

	if(m_video.towns_display_page_sel != 0)
		off = 0x20000;

//  if((layer == 1) && (m_video.towns_sprite_reg[1] & 0x80) && (m_video.towns_sprite_page == 1))
//      off = 0x20000;

	if(layer == 0)
		linesize = m_video.towns_crtc_reg[20] * 8;
	else
		linesize = m_video.towns_crtc_reg[24] * 8;

	if(layer != 0)
	{
		if(!(m_video.towns_video_reg[0] & 0x10))
			return;
		if(!(m_video.towns_crtc_reg[28] & 0x10))
			off += m_video.towns_crtc_reg[21] << 3;  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[21] & 0xfc00) << 3) | (((m_video.towns_crtc_reg[21] & 0x3ff) << 3));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[22]);
		hzoom = ((m_video.towns_crtc_reg[27] & 0x0f00) >> 8) + 1;
	}
	else
	{
		if(!(m_video.towns_crtc_reg[28] & 0x20))
			off += m_video.towns_crtc_reg[17] << 3;  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[17] & 0xfc00) << 3) | (((m_video.towns_crtc_reg[17] & 0x3ff) << 3));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]);
		hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
	}

	off += line * linesize;

	if(hzoom == 1)
	{
		for(x=rect->min_x;x<rect->max_x;x++)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)];
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 2)
	{  // x2 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=2)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)+1];
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 3)
	{  // x3 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=3)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)+1];
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 4)
	{  // x4 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=4)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)+1];
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 5)
	{  // x5 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=5)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)+1];
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+4) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}
}

void towns_state::towns_crtc_draw_scan_layer_16(bitmap_rgb32 &bitmap,const rectangle* rect,int layer,int line,int scanline)
{
	int off = 0;
	int x;
	UINT8 colour;
	int hzoom = 1;
	int linesize;
	UINT32 scroll;

	if(m_video.towns_display_page_sel != 0)
		off = 0x20000;

//  if((layer == 1) && (m_video.towns_sprite_reg[1] & 0x80) && (m_video.towns_sprite_page == 1))
//      off = 0x20000;

	if(layer == 0)
		linesize = m_video.towns_crtc_reg[20] * 4;
	else
		linesize = m_video.towns_crtc_reg[24] * 4;

	if(layer != 0)
	{
		if(!(m_video.towns_video_reg[0] & 0x10))
			return;
		if(!(m_video.towns_crtc_reg[28] & 0x10))
			off += m_video.towns_crtc_reg[21];  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[21] & 0xfc00)<<2) | (((m_video.towns_crtc_reg[21] & 0x3ff)<<2));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[22]);
		hzoom = ((m_video.towns_crtc_reg[27] & 0x0f00) >> 8) + 1;
	}
	else
	{
		if(!(m_video.towns_crtc_reg[28] & 0x20))
			off += m_video.towns_crtc_reg[17];  // initial offset
		else
		{
			scroll = ((m_video.towns_crtc_reg[17] & 0xfc00)<<2) | (((m_video.towns_crtc_reg[17] & 0x3ff)<<2));
			off += scroll;
		}
		off += (m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]);
		hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
	}

	off += line * linesize;

	if(hzoom == 1)
	{
		for(x=rect->min_x;x<rect->max_x;x+=2)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 2)
	{  // x2 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=4)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 3)
	{  // x3 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=6)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+4) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+5) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 4)
	{  // x4 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=8)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x+4) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+5) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+6) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+7) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}

	if(hzoom == 5)
	{  // x5 horizontal zoom
		for(x=rect->min_x;x<rect->max_x;x+=10)
		{
			if(m_video.towns_video_reg[0] & 0x10)
				off &= 0x3ffff;  // 2 layers
			else
				off &= 0x7ffff;  // 1 layer
			colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x+5) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+6) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+7) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+8) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+9) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
			if(colour != 0)
			{
				bitmap.pix32(scanline, x) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+1) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+2) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+3) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
				bitmap.pix32(scanline, x+4) =
					(m_video.towns_palette_r[colour] << 16)
					| (m_video.towns_palette_g[colour] << 8)
					| (m_video.towns_palette_b[colour]);
			}
			off++;
		}
	}
}

void towns_state::towns_crtc_draw_layer(bitmap_rgb32 &bitmap,const rectangle* rect,int layer)
{
	int line;
	int scanline;
	int height;

	if(layer == 0)
	{
		scanline = rect->min_y;
		height = (rect->max_y - rect->min_y);
		if(m_video.towns_crtc_reg[27] & 0x0010)
			height /= 2;
		switch(m_video.towns_video_reg[0] & 0x03)
		{
			case 0x01:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x0010)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
			case 0x02:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_256(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x0010)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_256(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
			case 0x03:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x0010)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
		}
	}
	else
	{
		scanline = rect->min_y;
		height = (rect->max_y - rect->min_y);
		if(m_video.towns_crtc_reg[27] & 0x1000)
			height /= 2;
		switch(m_video.towns_video_reg[0] & 0x0c)
		{
			case 0x04:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x1000)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
			case 0x08:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_256(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x1000)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_256(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
			case 0x0c:
				for(line=0;line<height;line++)
				{
					towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
					scanline++;
					if(m_video.towns_crtc_reg[27] & 0x1000)  // vertical zoom
					{
						towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
						scanline++;
					}
				}
				break;
		}
	}
}

void towns_state::render_text_char(UINT8 x, UINT8 y, UINT8 ascii, UINT16 jis, UINT8 attr)
{
	UINT32 rom_addr;
	UINT32 vram_addr;
	UINT16 linesize = m_video.towns_crtc_reg[24] * 4;
	UINT8 code_h,code_l;
	UINT8 colour;
	UINT8 data;
	UINT8 temp;
	UINT8* font_rom = memregion("user")->base();
	int a,b;

	// all characters are 16 pixels high
	vram_addr = (x * 4) + (y * (linesize * 16));

	if((attr & 0xc0) == 0)
		rom_addr = 0x3d800 + (ascii * 128);
	else
	{
		code_h = (jis & 0xff00) >> 8;
		code_l = jis & 0x00ff;
		if(code_h < 0x30)
		{
			rom_addr = ((code_l & 0x1f) << 4)
								| (((code_l - 0x20) & 0x20) << 8)
								| (((code_l - 0x20) & 0x40) << 6)
								| ((code_h & 0x07) << 9);
		}
		else if(code_h < 0x70)
		{
			rom_addr = ((code_l & 0x1f) << 4)
								+ (((code_l - 0x20) & 0x60) << 8)
								+ ((code_h & 0x0f) << 9)
								+ (((code_h - 0x30) & 0x70) * 0xc00)
								+ 0x8000;
		}
		else
		{
			rom_addr = ((code_l & 0x1f) << 4)
								| (((code_l - 0x20) & 0x20) << 8)
								| (((code_l - 0x20) & 0x40) << 6)
								| ((code_h & 0x07) << 9)
								| 0x38000;
		}
	}
	colour = attr & 0x07;
	if(attr & 0x20)
		colour |= 0x08;

	for(a=0;a<16;a++)  // for each scanline
	{
		if((attr & 0xc0) == 0)
			data = font_rom[0x180000 + rom_addr + a];
		else
		{
			if((attr & 0xc0) == 0x80)
				data = font_rom[0x180000 + rom_addr + (a*2)];
			else
				data = font_rom[0x180000 + rom_addr + (a*2) + 1];
		}

		if(attr & 0x08)
			data = ~data;  // inverse

		// and finally, put the data in VRAM
		for(b=0;b<8;b+=2)
		{
			temp = 0;
			if(data & (1<<b))
				temp |= ((colour & 0x0f) << 4);
			if(data & (1<<(b+1)))
				temp |= (colour & 0x0f);
			//m_towns_gfxvram[0x40000+vram_addr+(b/2)] = temp;
		}

		vram_addr += linesize;
		vram_addr &= 0x3ffff;
	}
}

void towns_state::draw_text_layer()
{
/*
 *  Text format
 *  2 bytes per character at both 0xc8000 and 0xca000
 *  0xc8xxx: Byte 1: ASCII character
 *           Byte 2: Attributes
 *             bits 2-0: GRB (or is it BRG?)
 *             bit 3: Inverse
 *             bit 4: Blink
 *             bit 5: high brightness
 *             bits 7-6: Kanji high/low
 *
 *  If either bits 6 or 7 are high, then a fullwidth Kanji character is displayed
 *  at this location.  The character displayed is represented by a 2-byte
 *  JIS code at the same offset at 0xca000.
 *
 *  The video hardware renders text to VRAM layer 1, there is no separate text layer
 */
	int x,y,c = 0;

	for(y=0;y<40;y++)
	{
		for(x=0;x<80;x++)
		{
			render_text_char(x,y,m_towns_txtvram[c],((m_towns_txtvram[c+0x2000] << 8)|(m_towns_txtvram[c+0x2001])),m_towns_txtvram[c+1]);
			c+=2;
		}
	}
}

TIMER_CALLBACK_MEMBER(towns_state::towns_sprite_done)
{
	// sprite drawing is complete, lower flag
	m_video.towns_sprite_flag = 0;
	if(m_video.towns_sprite_page != 0)
		m_video.towns_crtc_reg[21] |= 0x8000;
	else
		m_video.towns_crtc_reg[21] &= ~0x8000;
}

TIMER_CALLBACK_MEMBER(towns_state::towns_vblank_end)
{
	// here we'll clear the vsync signal, I presume it goes low on it's own eventually
	device_t* dev = (device_t*)ptr;
	downcast<pic8259_device *>(dev)->ir3_w(0);  // IRQ11 = VSync
	if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set low\n");
	m_video.towns_vblank_flag = 0;
}

INTERRUPT_GEN_MEMBER(towns_state::towns_vsync_irq)
{
	pic8259_device* dev = m_pic_slave;
	dev->ir3_w(1);  // IRQ11 = VSync
	if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set high\n");
	m_video.towns_vblank_flag = 1;
	machine().scheduler().timer_set(machine().primary_screen->time_until_vblank_end(), timer_expired_delegate(FUNC(towns_state::towns_vblank_end),this), 0, (void*)dev);
	if(m_video.towns_tvram_enable)
		draw_text_layer();
	if(m_video.towns_sprite_reg[1] & 0x80)
		draw_sprites(&m_video.towns_crtc_layerscr[1]);
}

void towns_state::video_start()
{
	m_video.towns_vram_wplane = 0x00;
	m_video.towns_sprite_page = 0;
	m_video.sprite_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(towns_state::towns_sprite_done),this));
}

UINT32 towns_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	bitmap.fill(0x00000000, cliprect);

	if(!(m_video.towns_video_reg[1] & 0x01))
	{
		if(!machine().input().code_pressed(KEYCODE_Q))
		{
			if((m_video.towns_layer_ctrl & 0x03) != 0)
				towns_crtc_draw_layer(bitmap,&m_video.towns_crtc_layerscr[1],1);
		}
		if(!machine().input().code_pressed(KEYCODE_W))
		{
			if((m_video.towns_layer_ctrl & 0x0c) != 0)
				towns_crtc_draw_layer(bitmap,&m_video.towns_crtc_layerscr[0],0);
		}
	}
	else
	{
		if(!machine().input().code_pressed(KEYCODE_Q))
		{
			if((m_video.towns_layer_ctrl & 0x0c) != 0)
				towns_crtc_draw_layer(bitmap,&m_video.towns_crtc_layerscr[0],0);
		}
		if(!machine().input().code_pressed(KEYCODE_W))
		{
			if((m_video.towns_layer_ctrl & 0x03) != 0)
				towns_crtc_draw_layer(bitmap,&m_video.towns_crtc_layerscr[1],1);
		}
	}

#if 0
#ifdef SPR_DEBUG
	if(machine().input().code_pressed(KEYCODE_O))
		pshift+=0x80;
	if(machine().input().code_pressed(KEYCODE_I))
		pshift-=0x80;
	popmessage("Pixel shift = %08x",pshift);
#endif
#endif

#ifdef CRTC_REG_DISP
	popmessage("CRTC: %i %i %i %i %i %i %i %i %i\n%i %i %i %i | %i %i %i %i\n%04x %i %i %i | %04x %i %i %i\nZOOM: %04x\nVideo: %02x %02x\nText=%i Spr=%02x\nReg28=%04x",
		m_video.towns_crtc_reg[0],m_video.towns_crtc_reg[1],m_video.towns_crtc_reg[2],m_video.towns_crtc_reg[3],
		m_video.towns_crtc_reg[4],m_video.towns_crtc_reg[5],m_video.towns_crtc_reg[6],m_video.towns_crtc_reg[7],
		m_video.towns_crtc_reg[8],
		m_video.towns_crtc_reg[9],m_video.towns_crtc_reg[10],m_video.towns_crtc_reg[11],m_video.towns_crtc_reg[12],
		m_video.towns_crtc_reg[13],m_video.towns_crtc_reg[14],m_video.towns_crtc_reg[15],m_video.towns_crtc_reg[16],
		m_video.towns_crtc_reg[17],m_video.towns_crtc_reg[18],m_video.towns_crtc_reg[19],m_video.towns_crtc_reg[20],
		m_video.towns_crtc_reg[21],m_video.towns_crtc_reg[22],m_video.towns_crtc_reg[23],m_video.towns_crtc_reg[24],
		m_video.towns_crtc_reg[27],m_video.towns_video_reg[0],m_video.towns_video_reg[1],m_video.towns_tvram_enable,m_video.towns_sprite_reg[1] & 0x80,
		m_video.towns_crtc_reg[28]);
#endif

	return 0;
}