summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/bus/snes/sa1.cpp
blob: b25a06d5255ded4ecc9ad5f0a3ba1e4c1e4badfe (plain) (tree)
1
2
3
4
5
6
7
8
                       
                                             
                                                                                                            
 
                                          
 
      
                                                            


                                                                                                           
                                           













                                                                        
                                                                                                                

                                 
 
               
                      

                                   
                               


                                                                                                                     
                      

                                                                          
                                                

                                                            
                                                                     









                                                                      

                      
                                                                                                       
                                                                   





                                                                                                                    

                                                                                                             
                
                
 



                              
 

                              
                                
                              




                                                   
                                                                                    

 
                                                                                                               












                                                                                                                                                   




                                   



                         
















































                                            



                                   
                                                          
 
                          







                         
                         
                        
                         
                        
                         



                               
                               





                              
                                                










                            

                                       


                          


                                                            

 
 



                                                    

                                  

                                                                         
                                       


            
                                      
         




















                                                                               



                                                    


                                                                  
                       
                                                        










                                                                                               
                                                 

                                                                
                                                 

                                                                
                                                 

                                                                      
                                                                                        

                                                                
                                                             









                                                                      
                                   
 
                                                                                                                           
 
                           
         


                                                
 





                                                                                      
                                          



                                                                                                         
                                                                          


                                                                                                         
                                                                          


                                                                     
                                                                          





                                                                     
                                                                                                             


                                                                     
                                                                                   






                                                          

                                          
                 
                                           


                                                          
                                            

                                                                     
                                                                                                       







                                                                             
 



                                   
                                           
 
                                   



                                          
                                           


 
                      
                                                  
 
                             

                                                                                      


                           
                                          
                                                                    

                              
                                         
                                                                  

                              





                                                    

                              

                                                    

                              

                                                    

                              

                                                    

                              
                                              
                                                                   

                              
                                               
                                                                   

                              
                                                
                                                                    

                              
                                                
                                                                    

                              
                                                
                                                                    

                              

                                                             

                              

                                                   
                                                                                                                                                                                        


                                                           

                              

                                                    
                                                                                                                                                                                        
                                                

                                               





                                                               
 

                                                           










                                                                                     
                                                              
 

                                                                                      


                           
                                             
                                                   
                                                                    
                         
                                                
                                                                                    
                         

                                                                         
                                                 




                                                                                     
                                          
 



                                                     

                                               
                                                            


                                               
                                                            
                         
                                      


                                                                    
                                          
                                              
                                      


                                                                    
                                                                


                                                              
                                                                           



                                                                   


                                                                          

                                              


                                                                          

                                                 


                                                                        

                                            


                                                                        

                                               


                                                                        

                                            


                                                                        

                                               

                              



                                               
                                                             
                                                 
                         








                                                                       
                                                                               

                                      


                                                                    
                                         
                                             
                                      


                                                                    
















                                                              

                              

                                                                             

                              

                                                                             

                              

                                                                             

                              

                                                                             







                                                                       

                                                                     

                              

                                                                     

                              

                                                                     

                              

                                                                     






















                                                    
                                                                      


                                                           

                                                                                      






















                                                                                        
                                                       
                                          


                                                                                    
                                             






                                                                       

                              

                                                                           

                              

                                                                           

                              

                                                                            

                              

                                                                           

                              

                                                                           



                                                                                                       
                                                       

                                 
                                                                                            
                                 
                                                               

                                 
                              
                           
                                                             
                                                                            

                                              
                                                                                                      
                                 
                                                          
                                                       

                                 


                                                                         

                                            


                                                                         

                                               


                                                                 
                                                                                 
















                              

                                                               

                                                                      
                                                                                                
                                 
                                                    
                                                               
                                 
                         

                              



                                                  

                              

                                                              

                              

                                                                     

                              

                                                              

                              





                                                                     
                                                                                           






                                                               


                                                                                                            



                                                                             
                                                                                              
                                                                      





                                                                                         

                              












                                                                 

                              

                                                                 

                              

                                                                 

                              


                                                                  






                                                                                                         
                                                  



                                              
                                                              



                                              


























































                                                                                                                   
                                                   
 
                  
                     
 
                            

                                                                                                            




                                               
                              
                                                              
 
                       
                           
 


                               
                                            
                            
                             



                             
                                            
                            
                             
         
 
                                       
                                                                        

 
                                                               
 
                     
 
                            

                                                                                                    

                              
                                                              

                       
 
                       
                           
 


                               


                                                            



                             


                                                            
         
 
                                                                   
                                                                                                         








                                                    
                                             
 
                 
 




                                                                                       


                                                        
                                                                                                      
                                                         
                                                                                           

                                                                          
                             




                                                                              
                                                                                                       
                                                         
                                                                                           
                                                                          
 
                             





                                                                                                          
                                             
 
                 
 


                                                                   
                                                                                                      
                                                         
                                                                                           
                                                                          
 
                             




                                                                              
                                                                                                       
                                                         
                                                                                           
                                                                          
 
                             


                                                                              
                                                                                                                                
                                   
                                                                                                                                
                                   
                                                                                                                                
            
                                                                                                                                

 
                                                         


 
                                                         


 
                                                
 
                                           
 
                                                                       
                                                                        
 
                                                                       
                                                                             

                                                                       
                                                                                                    

                                                    
                                                                                                                                                  
 



                    
                                                            
 
                                           
 
                                                                       
                                                                
 
                                                                       

                                                                             
                                                                       

                                                                                             
                                                    
                                                                                                                                           










                                                                                            
                                               
 
                                           
 




                                             
                                                                                     
                                                                       
                                                                                       
                                                                       
                                                                                     

                                          
                                                                                                                                                   
                    
                                                       

                                                                                                                                       

            
                                               

 
                                               
 
                                           
 




                                             
                                                                                     
                                                                       
                                                                                       
                                                                       
                                                                                     

                                          
                                                                                                                                                   
                                          


                                                
                                          


                                            
                                          


                                                
                                          


                                            
                                          


                                                  
                                          


                                              
                    
                                                       

                                                                                                                                       

                                   
                                                                                                   
                                                         
                                                                                                       

                                                                                    

 
                                                          
 
                                           




                                             
                                                                                     
                                                                       
                                                                                
                                                                       
                                                                                     

                                          
                                                                                                                                             


         
                                                          

                                                    
                                                                                               
                                                         
                                                                                                 
            
                                       

 

                                              
                                                                                                   
                                        
                                                                                                   
 

 




                                                                 
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli, R. Belmont
/***********************************************************************************************************

 SA-1 add-on chip emulation (for SNES/SFC)

 Note:
 - SA-1 register description below is based on no$cash docs.
 - about bankswitch handling: no matter what is ROM size, at loading the ROM is mirrored up to 8MB and a
   rom_bank_map[0x100] array is built as a lookup table for 256x32KB banks filling the 8MB accessible ROM
   area; this allows to handle any 0-7 value written to CXB/DXB/EXB/FXB SA-1 registers without any masking!
 - about BWRAM "bitmap mode": in 2bits mode
     600000h.Bit0-1 mirrors to 400000h.Bit0-1
     600001h.Bit0-1 mirrors to 400000h.Bit2-3
     600002h.Bit0-1 mirrors to 400000h.Bit4-5
     600003h.Bit0-1 mirrors to 400000h.Bit6-7
     ...
   in 4bits mode
     600000h.Bit0-3 mirrors to 400000h.Bit0-3
     600001h.Bit0-3 mirrors to 400000h.Bit4-7
     600002h.Bit0-3 mirrors to 400001h.Bit0-3
     600003h.Bit0-3 mirrors to 400001h.Bit4-7
     ...
   to handle the separate modes, bitmap accesses go to offset + 0x100000

 TODO:
 - test case for BWRAM & IRAM write protect (bsnes does not seem to ever protect either, so it's not implemented
   for the moment)
 - almost everything CPU related!

 Compatibility:
    asahishi: plays OK
    daisenx2: plays OK
    derbyjo2: hangs going into game
    dbzhypd, dbzhypdj: plays OK
    habumeij: boots, goes into game, on-screen timer counts down after SA-1 is enabled but controls aren't responsive
    haruaug3a, pebble, haruaug3: uses SA-1 DMA
    itoibass: boots, some missing gfx
    jikkparo: plays OK
    jl96drem: plays OK
    jumpind: boots and runs, uses SA-1 normal DMA only but has corrupt gfx
    kakinoki: S-CPU crashes after pressing start
    kirby3j, kirby3: uses SA-1 DMA
    kirbysdb, kirbyss, kirbyfun, kirbysd, kirbysda: plays OK
    marvelou: plays OK, uses SA-1 normal DMA only but has corrupt gfx
    miniyonk: plays OK
    panicbw: plays OK
    pgaeuro, pgaeurou, pga96, pga96u, pga, pgaj: plays OK
    przeo, przeou: plays OK
    prokishi: plays OK
    rinkaiho: plays OK
    saikouso: plays OK
    sdf1gpp, sdf1gp: corrupt menu gfx, hangs going into game (I think)
    sdgungnx: plays OK
    shinshog: plays OK
    shogisai: plays OK
    shogisa2: plays OK
    smrpgj, smrpg: needs SA-1 character conversion for level up Bonus Chance (possible to get past now)
    srobotg: some corrupt in-game GFX, may be SNES rendering errors
    sshogi3: plays OK
    taikyoid: plays OK
    takemiya: plays OK
 [Note: for Igo & Shougi games, "plays OK" means you can get ingame and the CPU replies to your moves... subtle bugs
 might indeed exist...]

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

#include "emu.h"
#include "sa1.h"

#define SA1_IRQ_SCPU    (0x80)
#define SA1_IRQ_TIMER   (0x40)
#define SA1_IRQ_DMA     (0x20)
#define SA1_NMI_SCPU    (0x10)

#define SCPU_IRQ_SA1    (0x80)
#define SCPU_IRQV_ALT   (0x40)
#define SCPU_IRQ_CHARCONV (0x20)
#define SCPU_NMIV_ALT   (0x10)

//-------------------------------------------------
//  constructor
//-------------------------------------------------

DEFINE_DEVICE_TYPE(SNS_LOROM_SA1, sns_sa1_device, "sns_rom_sa1", "SNES Cart + SA-1")


sns_sa1_device::sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, SNS_LOROM_SA1, tag, owner, clock)
	, device_sns_cart_interface(mconfig, *this)
	, m_sa1(*this, "sa1cpu")
	, m_sa1_ctrl(0), m_scpu_sie(0), m_sa1_reset(0), m_sa1_nmi(0), m_sa1_irq(0), m_scpu_ctrl(0), m_sa1_sie(0)
	, m_irq_vector(0), m_nmi_vector(0)
	, m_hcount(0), m_vcount(0)
	, m_bank_c_hi(0), m_bank_c_rom(0), m_bank_d_hi(0), m_bank_d_rom(0), m_bank_e_hi(0), m_bank_e_rom(0), m_bank_f_hi(0), m_bank_f_rom(0)
	, m_bwram_snes(0), m_bwram_sa1(0), m_bwram_sa1_source(0), m_bwram_sa1_format(0), m_bwram_write_snes(0), m_bwram_write_sa1(0), m_bwpa_sa1(0)
	, m_iram_write_snes(0), m_iram_write_sa1(0)
	, m_dma_ctrl(0), m_dma_ccparam(0), m_src_addr(0), m_dst_addr(0), m_dma_cnt(0)
	, m_math_ctlr(0), m_math_overflow(0), m_math_a(0), m_math_b(0), m_math_res(0)
	, m_vda(0), m_vbit(0), m_vlen(0), m_drm(0), m_scpu_flags(0), m_sa1_flags(0), m_hcr(0), m_vcr(0)
{
}


void sns_sa1_device::device_start()
{
	m_scpu_ctrl = 0;
	m_nmi_vector = 0;
	m_bank_c_hi = 0;
	m_bank_c_rom = 0;

	save_item(NAME(m_internal_ram));
	save_item(NAME(m_sa1_ctrl));
	save_item(NAME(m_scpu_sie));
	save_item(NAME(m_sa1_reset));
	save_item(NAME(m_sa1_nmi));
	save_item(NAME(m_sa1_irq));
	save_item(NAME(m_scpu_ctrl));
	save_item(NAME(m_sa1_sie));
	save_item(NAME(m_irq_vector));
	save_item(NAME(m_nmi_vector));
	save_item(NAME(m_hcount));
	save_item(NAME(m_vcount));
	save_item(NAME(m_bank_c_hi));
	save_item(NAME(m_bank_c_rom));
	save_item(NAME(m_bank_d_hi));
	save_item(NAME(m_bank_d_rom));
	save_item(NAME(m_bank_e_hi));
	save_item(NAME(m_bank_e_rom));
	save_item(NAME(m_bank_f_hi));
	save_item(NAME(m_bank_f_rom));
	save_item(NAME(m_bwram_snes));
	save_item(NAME(m_bwram_sa1));
	save_item(NAME(m_bwram_sa1_source));
	save_item(NAME(m_bwram_sa1_format));
	save_item(NAME(m_bwram_write_snes));
	save_item(NAME(m_bwram_write_sa1));
	save_item(NAME(m_bwpa_sa1));
	save_item(NAME(m_iram_write_snes));
	save_item(NAME(m_iram_write_sa1));
	save_item(NAME(m_dma_ctrl));
	save_item(NAME(m_dma_ccparam));
	save_item(NAME(m_src_addr));
	save_item(NAME(m_dst_addr));
	save_item(NAME(m_dma_cnt));
	save_item(NAME(m_brf_reg));
	save_item(NAME(m_math_ctlr));
	save_item(NAME(m_math_overflow));
	save_item(NAME(m_math_a));
	save_item(NAME(m_math_b));
	save_item(NAME(m_math_res));
	save_item(NAME(m_vda));
	save_item(NAME(m_vbit));
	save_item(NAME(m_vlen));
	save_item(NAME(m_drm));
	save_item(NAME(m_scpu_flags));
	save_item(NAME(m_sa1_flags));
	save_item(NAME(m_hcr));
	save_item(NAME(m_vcr));
}

void sns_sa1_device::device_reset()
{
	memset(m_internal_ram, 0, sizeof(m_internal_ram));

	m_sa1_ctrl = 0x20;
	m_scpu_ctrl = 0;
	m_irq_vector = 0;
	m_nmi_vector = 0;
	m_hcount = 0;
	m_vcount = 0;
	m_bank_c_hi = 0;
	m_bank_c_rom = 0;
	m_bank_d_hi = 0;
	m_bank_d_rom = 1;
	m_bank_e_hi = 0;
	m_bank_e_rom = 2;
	m_bank_f_hi = 0;
	m_bank_f_rom = 3;
	m_bwram_snes = 0;
	m_bwram_sa1 = 0;
	m_bwram_sa1_source = 0;
	m_bwram_sa1_format = 0;
	m_bwram_write_snes = 1;
	m_bwram_write_sa1 = 1;
	m_bwpa_sa1 = 0x0f;
	m_iram_write_snes = 1;
	m_iram_write_sa1 = 1;
	m_src_addr = 0;
	m_dst_addr = 0;
	memset(m_brf_reg, 0, sizeof(m_brf_reg));
	m_math_ctlr = 0;
	m_math_overflow = 0;
	m_math_a = 0;
	m_math_b = 0;
	m_math_res = 0;
	m_vda = 0;
	m_vbit = 0;
	m_vlen = 0;
	m_drm = 0;
	m_hcr = 0;
	m_vcr = 0;
	m_scpu_sie = m_sa1_sie = 0;
	m_scpu_flags = m_sa1_flags = 0;
	m_dma_ctrl = 0;
	m_dma_ccparam = 0;
	m_dma_cnt = 0;

	// sa-1 CPU starts out not running?
	m_sa1->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
}


/*-------------------------------------------------
 mapper specific handlers
 -------------------------------------------------*/

void sns_sa1_device::recalc_irqs()
{
	if (m_scpu_flags & m_scpu_sie & (SCPU_IRQ_SA1|SCPU_IRQ_CHARCONV))
	{
		write_irq(ASSERT_LINE);
	}
	else
	{
		write_irq(CLEAR_LINE);
	}

	if (m_sa1_flags & m_sa1_sie & (SA1_IRQ_SCPU|SA1_IRQ_TIMER|SA1_IRQ_DMA))
	{
		m_sa1->set_input_line(G65816_LINE_IRQ, ASSERT_LINE);
	}
	else
	{
		m_sa1->set_input_line(G65816_LINE_IRQ, CLEAR_LINE);
	}

	if (m_sa1_flags & m_sa1_sie & SA1_NMI_SCPU)
	{
		m_sa1->set_input_line(G65816_LINE_NMI, ASSERT_LINE);
	}
	else
	{
		m_sa1->set_input_line(G65816_LINE_NMI, CLEAR_LINE);
	}
}


/*-------------------------------------------------
  RAM / SRAM / Registers
 -------------------------------------------------*/


// handle this separately to avoid accessing recursively the regs?

template <bool SA1Read>
uint8_t sns_sa1_device::var_length_read(uint32_t offset)
{
	// handle 0xffea/0xffeb/0xffee/0xffef
	if ((offset & 0xffffe0) == 0x00ffe0)
	{
		if (offset == 0xffea && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 0) & 0xff;
		if (offset == 0xffeb && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 8) & 0xff;
		if (offset == 0xffee && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 0) & 0xff;
		if (offset == 0xffef && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 8) & 0xff;
	}

	if ((offset & 0xc08000) == 0x008000)  //$00-3f:8000-ffff
		return read_l(offset & 0x7fffff);

	if ((offset & 0xc08000) == 0x808000)  //$80-bf:8000-ffff
		return read_h(offset & 0x7fffff);

	if ((offset & 0xc00000) == 0xc00000)  //$c0-ff:0000-ffff
		return read_h(offset & 0x7fffff);

	if ((offset & 0x40e000) == 0x006000)  //$00-3f|80-bf:6000-7fff
		return read_bwram<SA1Read>((m_bwram_snes * 0x2000) + (offset & 0x1fff));

	if ((offset & 0xf00000) == 0x400000)  //$40-4f:0000-ffff
		return read_bwram<SA1Read>(offset & 0xfffff);

	if ((offset & 0x40f800) == 0x000000)  //$00-3f|80-bf:0000-07ff
		return read_iram(offset);

	if ((offset & 0x40f800) == 0x003000)  //$00-3f|80-bf:3000-37ff
		return read_iram(offset);

	return 0;
}

void sns_sa1_device::dma_transfer()
{
//  printf("DMA src %08x (%d), dst %08x (%d) cnt %d\n", m_src_addr, m_dma_ctrl & 3, m_dst_addr, m_dma_ctrl & 4, m_dma_cnt);

	while (m_dma_cnt--)
	{
		uint8_t data = 0; // open bus?
		uint32_t dma_src = m_src_addr++;
		uint32_t dma_dst = m_dst_addr++;

		// source and destination cannot be the same
		// source = { 0=ROM, 1=BWRAM, 2=IRAM }
		// destination = { 0=IRAM, 1=BWRAM }
		if ((m_dma_ctrl & 0x03) == 1 && (m_dma_ctrl & 0x04) == 0x04) continue;
		if ((m_dma_ctrl & 0x03) == 2 && (m_dma_ctrl & 0x04) == 0x00) continue;

		switch (m_dma_ctrl & 0x03)
		{
			case 0: // ROM
				if ((dma_src & 0x408000) == 0x008000 && (dma_src & 0x800000) == 0x000000)
				{
					data = read_l(dma_src & 0x7fffff);
				}
				if ((dma_src & 0x408000) == 0x008000 && (dma_src & 0x800000) == 0x800000)
				{
					data = read_h(dma_src & 0x7fffff);
				}
				if ((dma_src & 0xc00000) == 0xc00000)
				{
					data = read_h(dma_src & 0x7fffff);
				}
				break;

			case 1: // BWRAM
				if ((dma_src & 0x40e000) == 0x006000)
				{
					data = read_bwram<true>((m_bwram_sa1 * 0x2000) + (dma_src & 0x1fff));
				}
				if ((dma_src & 0xf00000) == 0x400000)
				{
					data = read_bwram<true>(dma_src & 0xfffff);
				}
				break;

			case 2: // IRAM
				data = read_iram(dma_src);
				break;
		}

		switch (m_dma_ctrl & 0x04)
		{
			case 0x00:  // IRAM
				write_iram(dma_dst, data);
				break;

			case 0x04:  // BWRAM
				if ((dma_dst & 0x40e000) == 0x006000)
				{
					write_bwram((m_bwram_sa1 * 0x2000) + (dma_dst & 0x1fff), data);
				}
				if ((dma_dst & 0xf00000) == 0x400000)
				{
					write_bwram(dma_dst & 0xfffff, data);
				}
				break;
		}
	}

	m_sa1_flags |= SA1_IRQ_DMA;
	recalc_irqs();
}

void sns_sa1_device::dma_cctype1_transfer()
{
	m_cconv1_dma_active = true;
	m_scpu_flags |= SCPU_IRQ_CHARCONV;
	recalc_irqs();
}

void sns_sa1_device::dma_cctype2_transfer()
{
}

template<bool SA1Read>
uint8_t sns_sa1_device::read_regs(uint32_t offset)
{
	uint8_t value = 0xff;
	offset &= 0x1ff;    // $2200 + offset gives the reg value to compare with docs

	switch (offset)
	{
		case 0x100:
			// S-CPU Flag Read
			value = (m_scpu_ctrl & 0x0f) | m_scpu_flags;
			break;
		case 0x101:
			// SA-1 Flag Read
			value = (m_sa1_ctrl & 0x0f) | m_sa1_flags;
			break;
		case 0x102:
			// H-Count Read Low
			//latch counters
			m_hcr = m_hcount >> 2;
			m_vcr = m_vcount;
			//then return h-count
			value = (m_hcr >> 0) & 0xff;
			break;
		case 0x103:
			// H-Count Read High
			value = (m_hcr >> 8) & 0xff;
			break;
		case 0x104:
			// V-Count Read Low
			value = (m_vcr >> 0) & 0xff;
			break;
		case 0x105:
			// V-Count Read High
			value = (m_vcr >> 8) & 0xff;
			break;
		case 0x106:
			// Math Result bits0-7
			value = (uint64_t)(m_math_res >> 0) & 0xff;
			break;
		case 0x107:
			// Math Result bits8-15
			value = (uint64_t)(m_math_res >> 8) & 0xff;
			break;
		case 0x108:
			// Math Result bits16-23
			value = (uint64_t)(m_math_res >> 16) & 0xff;
			break;
		case 0x109:
			// Math Result bits24-31
			value = (uint64_t)(m_math_res >> 24) & 0xff;
			break;
		case 0x10a:
			// Math Result bits32-39
			value = (uint64_t)(m_math_res >> 32) & 0xff;
			break;
		case 0x10b:
			// Math Overflow (above 40bit result)
			value = m_math_overflow;
			break;
		case 0x10c:
			// Var-Length Read Port Low
			{
				uint32_t data = (var_length_read<SA1Read>(m_vda + 0) <<  0) | (var_length_read<SA1Read>(m_vda + 1) <<  8) | (var_length_read<SA1Read>(m_vda + 2) << 16);
				data >>= m_vbit;
				value = (data >> 0) & 0xff;
			}
			break;
		case 0x10d:
			// Var-Length Read Port High
			{
				uint32_t data = (var_length_read<SA1Read>(m_vda + 0) <<  0) | (var_length_read<SA1Read>(m_vda + 1) <<  8) | (var_length_read<SA1Read>(m_vda + 2) << 16);
				data >>= m_vbit;

				if (m_drm == 1)
				{
					//auto-increment mode
					m_vbit += m_vlen;
					m_vda += (m_vbit >> 3);
					m_vbit &= 7;
				}

				value = (data >> 8) & 0xff;
			}
			break;
		case 0x10e:
			// SNES  VC    Version Code Register (R)
			break;
		default:
			logerror("SA-1 Read access to an unmapped reg (%x)", offset);
			break;
	}
	return value;
}

void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
{
	offset &= 0x1ff;    // $2200 + offset gives the reg value to compare with docs

	switch (offset)
	{
		case 0x000:
			// SA-1 control flags
//          printf("%02x to SA-1 control\n", data);
			if ((BIT(data, 5)) && !(BIT(m_sa1_ctrl, 5)))
			{
//              printf("Engaging SA-1 reset\n");
				m_sa1->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
			}
			else if (!(BIT(data, 5)) && (BIT(m_sa1_ctrl, 5)))
			{
//              printf("Releasing SA-1 reset\n");
				m_sa1->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
				m_sa1->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
				m_sa1->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
			}

			m_sa1_ctrl = data;

			// message to S-CPU
			m_scpu_ctrl &= 0xf0;
			m_scpu_ctrl |= (data & 0x0f);

			if (BIT(m_sa1_ctrl, 7))
			{
				m_sa1_flags |= SA1_IRQ_SCPU;
			}
			if (BIT(m_sa1_ctrl, 4))
			{
				m_sa1_flags |= SA1_NMI_SCPU;
			}
			recalc_irqs();
			break;
		case 0x001:
			// SNES  SIE   00h   SNES CPU Int Enable (W)
			m_scpu_sie = data;
//          printf("S-CPU IE = %02x\n", data);
			recalc_irqs();
			break;
		case 0x002:
			// SNES  SIC   00h   SNES CPU Int Clear  (W)
			if (BIT(data, 7))   // ack IRQ from SA-1
			{
				m_scpu_flags &= ~SCPU_IRQ_SA1;
			}
			if (BIT(data, 5))   // ack character conversion IRQ
			{
				m_scpu_flags &= ~SCPU_IRQ_CHARCONV;
			}
			recalc_irqs();
			break;
		case 0x003:
			// SNES  CRV   -     SA-1 CPU Reset Vector Lsb (W)
			m_sa1_reset &= 0xff00;
			m_sa1_reset |= data;
			break;
		case 0x004:
			// SNES  CRV   -     SA-1 CPU Reset Vector Msb (W)
			m_sa1_reset &= 0x00ff;
			m_sa1_reset |= (data<<8);
			break;
		case 0x005:
			// SNES  CNV   -     SA-1 CPU NMI Vector Lsb (W)
			m_sa1_nmi &= 0xff00;
			m_sa1_nmi |= data;
			break;
		case 0x006:
			// SNES  CNV   -     SA-1 CPU NMI Vector Msb (W)
			m_sa1_nmi &= 0x00ff;
			m_sa1_nmi |= (data<<8);
			break;
		case 0x007:
			// SNES  CIV   -     SA-1 CPU IRQ Vector Lsb (W)
			m_sa1_irq &= 0xff00;
			m_sa1_irq |= data;
			break;
		case 0x008:
			// SNES  CIV   -     SA-1 CPU IRQ Vector Msb (W)
			m_sa1_irq &= 0x00ff;
			m_sa1_irq |= (data<<8);
			break;
		case 0x009:
			// S-CPU control flags
			m_scpu_ctrl = data;
			if (m_scpu_ctrl & 0x80)
			{
				m_scpu_flags |= SCPU_IRQ_SA1;
//              printf("SA-1 cause S-CPU IRQ\n");
			}

			// message to SA-1
			m_sa1_ctrl &= 0xf0;
			m_sa1_ctrl |= (data & 0x0f);

			// clear IRQ/NMI override flags in flags word
			m_scpu_flags &= ~(SCPU_IRQV_ALT|SCPU_NMIV_ALT);

			// and set them
			m_scpu_flags |= (data & (SCPU_IRQV_ALT|SCPU_NMIV_ALT));

			recalc_irqs();
			break;
		case 0x00a:
			// SA-1  CIE   00h   SA-1 CPU Int Enable (W)
			m_sa1_sie = data;
//          printf("SA-1 IE = %02x\n", data);
			recalc_irqs();
			break;
		case 0x00b:
			// SA-1  CIC   00h   SA-1 CPU Int Clear  (W)
			if (BIT(data, 7))
			{
				m_sa1_flags &= ~SA1_IRQ_SCPU;
			}
			if (BIT(data, 6))
			{
				m_sa1_flags &= ~SA1_IRQ_TIMER;
			}
			if (BIT(data, 5))
			{
				m_sa1_flags &= ~SA1_IRQ_DMA;
			}
			if (BIT(data, 4))
			{
				m_sa1_flags &= ~SA1_NMI_SCPU;
			}
			recalc_irqs();
			break;
		case 0x00c:
			// NMI Vector Low
			m_nmi_vector = (m_nmi_vector & 0xff00) | (data << 0);
			break;
		case 0x00d:
			// NMI Vector High
			m_nmi_vector = (m_nmi_vector & 0x00ff) | (data << 8);
			break;
		case 0x00e:
			// IRQ Vector Low
			m_irq_vector = (m_irq_vector & 0xff00) | (data << 0);
			break;
		case 0x00f:
			// IRQ Vector High
			m_irq_vector = (m_irq_vector & 0x00ff) | (data << 8);
			break;
		case 0x010:
			// SA-1  TMC   00h   H/V Timer Control (W)
			break;
		case 0x011:
			// SA-1  CTR   -     SA-1 CPU Timer Restart (W)
			break;
		case 0x012:
			// H-Count Low
			m_hcount = (m_hcount & 0xff00) | (data << 0);
			break;
		case 0x013:
			// H-Count High
			m_hcount = (m_hcount & 0x00ff) | (data << 8);
			break;
		case 0x014:
			// V-Count Low
			m_vcount = (m_vcount & 0xff00) | (data << 0);
			break;
		case 0x015:
			// V-Count High
			m_vcount = (m_vcount & 0x00ff) | (data << 8);
			break;
		case 0x020:
			// ROM 1MB bank for [c0-cf]
			m_bank_c_hi = BIT(data, 7);
			m_bank_c_rom = data & 0x07;
			break;
		case 0x021:
			// ROM 1MB bank for [d0-df]
			m_bank_d_hi = BIT(data, 7);
			m_bank_d_rom = data & 0x07;
			break;
		case 0x022:
			// ROM 1MB bank for [e0-ef]
			m_bank_e_hi = BIT(data, 7);
			m_bank_e_rom = data & 0x07;
			break;
		case 0x023:
			// ROM 1MB bank for [f0-ff]
			m_bank_f_hi = BIT(data, 7);
			m_bank_f_rom = data & 0x07;
			break;
		case 0x024:
			// BWRAM bank from SNES side
			m_bwram_snes = data & 0x1f; // max 32x8K banks
			break;
		case 0x025:
			// BWRAM bank & type from SA-1 side
			m_bwram_sa1_source = BIT(data, 7);  // 0 = normal, 1 = bitmap?
			m_bwram_sa1 = data & 0x7f;  // up to 128x8K banks here?
			break;
		case 0x026:
			// enable writing to BWRAM from SNES
			m_bwram_write_snes = BIT(data, 7);
			break;
		case 0x027:
			// enable writing to BWRAM from SA-1
			m_bwram_write_sa1 = BIT(data, 7);
			break;
		case 0x028:
			// write protected area at bottom of BWRAM
			m_bwpa_sa1 = 0x100 * (data & 0x0f);
			break;
		case 0x029:
			// enable writing to IRAM from SNES (1 bit for each 0x100 chunk)
			m_iram_write_snes = data;
			break;
		case 0x02a:
			// enable writing to IRAM from SA-1 (1 bit for each 0x100 chunk)
			m_iram_write_sa1 = data;
			break;
		case 0x030:
			// SA-1  DCNT  00h   DMA Control (W)
//          printf("%02x to SA-1 DMA control\n", data);
			m_dma_ctrl = data;
			break;
		case 0x031:
			// Both  CDMA  00h   Character Conversion DMA Parameters (W)
			m_dma_ccparam = data;
			m_dma_cconv_size = (data >> 2) & 7;
			if (m_dma_cconv_size > 5) m_dma_cconv_size = 5;
			m_dma_cconv_bits = data & 3;
			if (m_dma_cconv_bits > 2) m_dma_cconv_bits = 2;

			if (BIT(data, 7))
				m_cconv1_dma_active = false;
			break;
		case 0x032:
			// DMA Source Device Start Address Low
			m_src_addr = (m_src_addr & 0xffff00) | (data << 0);
			break;
		case 0x033:
			// DMA Source Device Start Address Mid
			m_src_addr = (m_src_addr & 0xff00ff) | (data << 8);
			break;
		case 0x034:
			// DMA Source Device Start Address High
			m_src_addr = (m_src_addr & 0x00ffff) | (data << 16);
			break;
		case 0x035:
			// DMA Dest Device Start Address Low
			m_dst_addr = (m_dst_addr & 0xffff00) | (data << 0);
			break;
		case 0x036:
			// DMA Dest Device Start Address Mid
			m_dst_addr = (m_dst_addr & 0xff00ff) | (data << 8);
			if (m_dma_ctrl & 0x80)
			{
				if (!(m_dma_ctrl & 0x20) && !(m_dma_ctrl & 0x04)) // Normal DMA to IRAM
				{
					dma_transfer();
				}

				if (m_dma_ctrl & 0x20 && m_dma_ctrl & 0x10) // CC DMA Type 1
				{
					dma_cctype1_transfer();
				}
			}
			break;
		case 0x037:
			// DMA Dest Device Start Address High
			m_dst_addr = (m_dst_addr & 0x00ffff) | (data << 16);
			if (m_dma_ctrl & 0x80)
			{
				if (!(m_dma_ctrl & 0x20) && m_dma_ctrl & 0x04)  // Normal DMA to BWRAM
				{
//                  printf("SA-1: normal DMA to BWRAM\n");
					dma_transfer();
				}
			}
			break;
		case 0x038:
			// SA-1  DTC   -     DMA Terminal Counter Lsb (W)
			m_dma_cnt &= 0xff00;
			m_dma_cnt |= data;
			break;
		case 0x039:
			// SA-1  DTC   -     DMA Terminal Counter Msb (W)
			m_dma_cnt &= 0x00ff;
			m_dma_cnt |= (data<<8);
			break;
		case 0x03f:
			// Format for BWRAM when mapped to bitmap
			m_bwram_sa1_format = BIT(data, 7);  // 0 = 4bit, 1 = 2bit
			break;
		case 0x040:
		case 0x041:
		case 0x042:
		case 0x043:
		case 0x044:
		case 0x045:
		case 0x046:
		case 0x047:
		case 0x048:
		case 0x049:
		case 0x04a:
		case 0x04b:
		case 0x04c:
		case 0x04d:
		case 0x04e:
		case 0x04f:
			// Bit Map Register File (2240h..224Fh)
			m_brf_reg[offset & 0x0f] = data;
			if ((offset & 0x07) == 7 && m_dma_ctrl & 0x80)
			{
				if (m_dma_ctrl & 0x20 && !(m_dma_ctrl & 0x10))  // CC DMA Type 2
				{
//                  printf("SA-1: CC DMA type 2\n");
					dma_cctype2_transfer();
				}
			}
			break;
		case 0x050:
			// Math control
			m_math_ctlr = data & 0x03;
			if (data & 0x02)
				m_math_res = 0;
			break;
		case 0x051:
			// Math A Low
			m_math_a = (m_math_a & 0xff00) | data;
			break;
		case 0x052:
			// Math A High
			m_math_a = (data << 8) | (m_math_a & 0x00ff);
			break;
		case 0x053:
			// Math B Low
			m_math_b = (m_math_b & 0xff00) | data;
			break;
		case 0x054:
			// Math B High
			m_math_b = (data << 8) | (m_math_b & 0x00ff);
			// After Math B has been written, we do math
			switch (m_math_ctlr)
			{
				case 0: //signed multiplication
					m_math_res = (int16_t)m_math_a * (int16_t)m_math_b;
					m_math_b = 0;
					break;
				case 1: //unsigned division
					if (m_math_b == 0)
						m_math_res = 0;
					else
					{
						int16_t  quotient  = (int16_t)m_math_a / (uint16_t)m_math_b;
						uint16_t remainder = (int16_t)m_math_a % (uint16_t)m_math_b;
						m_math_res = (uint64_t)((remainder << 16) | quotient);
					}
					break;
				case 2: //sigma (accumulative multiplication)
				case 3:
					uint64_t acum = (int16_t)m_math_a * (int16_t)m_math_b;
					uint64_t mask = 0xffffffffffU;
					m_math_res += acum;
					m_math_overflow = (m_math_res > mask) ? 0x80 : 0;
					m_math_res &= mask;
					m_math_b = 0;
					break;
			}
			break;
		case 0x058:
			// Var-Length Bit Processing
			m_drm = BIT(data, 7);   // Data Read Mode
			m_vlen = (data & 0x0f);
			if (m_vlen == 0)
				m_vlen = 16;

			if (m_drm == 0)
			{
				//fixed mode
				m_vbit += m_vlen;
				m_vda += (m_vbit >> 3);
				m_vbit &= 7;
			}
			break;
		case 0x059:
			// Var-Length Read Start Address Low
			m_vda = (m_vda & 0xffff00) | (data << 0);
			break;
		case 0x05a:
			// Var-Length Read Start Address Mid
			m_vda = (m_vda & 0xff00ff) | (data << 8);
			break;
		case 0x05b:
			// Var-Length Read Start Address High
			m_vda = (m_vda & 0x00ffff) | (data << 16);
			m_vbit = 0;
			break;
		default:
			logerror("SA-1 Write access to an unmapped reg (%x) with data %x", offset, data);
			break;
	}
}

uint8_t sns_sa1_device::read_iram(uint32_t offset)
{
	return m_internal_ram[offset & 0x7ff];
}

void sns_sa1_device::write_iram(uint32_t offset, uint8_t data)
{
	m_internal_ram[offset & 0x7ff] = data;
}

uint8_t sns_sa1_device::read_cconv1_dma(uint32_t offset)
{
	uint32_t store_mask = (1 << (6 - m_dma_cconv_bits)) - 1;

	if ((offset & store_mask) == 0)
	{
		uint32_t bpp = 2 << (2 - m_dma_cconv_bits);
		uint32_t tile_stride = (8 << m_dma_cconv_size) >> m_dma_cconv_bits;
		uint32_t bwram_addr_mask = m_nvram.size() - 1;
		uint32_t tile = ((offset - m_src_addr) & bwram_addr_mask) >> (6 - m_dma_cconv_bits);
		uint32_t ty = (tile >> m_dma_cconv_size);
		uint32_t tx = tile & ((1 << m_dma_cconv_size) - 1);
		uint32_t bwram_src = m_src_addr + ty * 8 * tile_stride + tx * bpp;

		for (uint32_t y = 0; y < 8; y++)
		{
			uint64_t raw_pixels = 0;
			for (uint64_t bit = 0; bit < bpp; bit++)
			{
				raw_pixels |= (uint64_t)m_nvram[(bwram_src + bit) & bwram_addr_mask] << (bit << 3);
			}
			bwram_src += tile_stride;

			uint8_t linear[8] = {0, 0, 0, 0, 0, 0, 0, 0};
			for (uint32_t x = 0; x < 8; x++)
			{
				linear[0] |= BIT(raw_pixels, 0) << (7 - x);
				linear[1] |= BIT(raw_pixels, 1) << (7 - x);
				if (m_dma_cconv_bits == 2)
				{
					raw_pixels >>= 2;
					continue;
				}
				linear[2] |= BIT(raw_pixels, 2) << (7 - x);
				linear[3] |= BIT(raw_pixels, 3) << (7 - x);
				if (m_dma_cconv_bits == 1)
				{
					raw_pixels >>= 4;
					continue;
				}
				linear[4] |= BIT(raw_pixels, 4) << (7 - x);
				linear[5] |= BIT(raw_pixels, 5) << (7 - x);
				linear[6] |= BIT(raw_pixels, 6) << (7 - x);
				linear[7] |= BIT(raw_pixels, 7) << (7 - x);
				raw_pixels >>= 8;
			}

			for (uint32_t byte = 0; byte < bpp; byte++)
			{
				uint32_t dst_addr = m_dst_addr + (y << 1) + ((byte & 6) << 3) + (byte & 1);
				write_iram(dst_addr, linear[byte]);
			}
		}
	}

	return read_iram(m_dst_addr + (offset & store_mask));
}

template<bool SA1Read>
uint8_t sns_sa1_device::read_bwram(uint32_t offset)
{
	int shift;
	uint8_t mask;

	if (m_nvram.empty())
		return 0xff;    // this should probably never happen, or are there SA-1 games with no BWRAM?

	if (m_cconv1_dma_active && !SA1Read)
	{
		return read_cconv1_dma(offset);
	}

	if (offset < 0x100000)
		return m_nvram[offset & (m_nvram.size() - 1)];

	// Bitmap BWRAM
	offset -= 0x100000;

	if (m_bwram_sa1_format)
	{
		// 2bits mode
		shift = ((offset & 3) << 1);
		mask = 0x03;
		offset >>= 2;
	}
	else
	{
		// 4bits mode
		shift = ((offset & 1) << 2);
		mask = 0x0f;
		offset >>= 1;
	}

	// only return the correct bits
	return (m_nvram[offset & (m_nvram.size() - 1)] >> shift) & mask;
}

void sns_sa1_device::write_bwram(uint32_t offset, uint8_t data)
{
	uint8_t mask;

	if (m_nvram.empty())
		return; // this should probably never happen, or are there SA-1 games with no BWRAM?

	if (offset < 0x100000)
	{
		m_nvram[offset & (m_nvram.size() - 1)] = data;
		return;
	}

	// Bitmap BWRAM
	offset -= 0x100000;

	if (m_bwram_sa1_format)
	{
		// 2bits mode
		data = (data & 0x03) << ((offset & 3) << 1);
		mask = 0x03 << ((offset & 3) << 1);
		offset >>= 2;
	}
	else
	{
		// 4bits mode
		data = (data & 0x0f) << ((offset & 1) << 2);
		mask = 0x0f << ((offset & 1) << 2);
		offset >>= 1;
	}

	// only change the correct bits, keeping the rest untouched
	m_nvram[offset & (m_nvram.size() - 1)] = (m_nvram[offset & (m_nvram.size() - 1)] & ~mask) | data;
}



/*-------------------------------------------------
  Accesses from SNES CPU
 -------------------------------------------------*/


uint8_t sns_sa1_device::read_l(offs_t offset)
{
	int bank;

	if (offset == 0xffea && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 0) & 0xff;
	if (offset == 0xffeb && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 8) & 0xff;
	if (offset == 0xffee && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 0) & 0xff;
	if (offset == 0xffef && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 8) & 0xff;

	// ROM is mapped to [00-3f][8000-ffff] only here
	if (offset < 0x200000)
	{
		if (!m_bank_c_hi)   // when HiROM mapping is disabled, we always access first 1MB here
			bank = (offset / 0x10000) + 0x00;
		else    // when HiROM mapping is enabled, we mirror [c0-cf][0000-ffff] bank
			bank = (offset / 0x10000) + (m_bank_c_rom * 0x20);

		bank &= 0xff;
		return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
	}
	else if (offset < 0x400000)
	{
		offset -= 0x200000;
		if (!m_bank_d_hi)   // when HiROM mapping is disabled, we always access second 1MB here
			bank = (offset / 0x10000) + 0x20;
		else    // when HiROM mapping is enabled, we mirror [d0-df][0000-ffff] bank
			bank = (offset / 0x10000) + (m_bank_d_rom * 0x20);

		bank &= 0xff;
		return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
	}
	else
		return 0; // this should not happen (the driver should only call read_l in the above case)
}

uint8_t sns_sa1_device::read_h(offs_t offset)
{
	int bank;

	// ROM is mapped to [80-bf][8000-ffff] & [c0-ff][0000-ffff]
	if (offset < 0x200000)
	{
		if (!m_bank_e_hi)   // when HiROM mapping is disabled, we always access third 1MB here
			bank = (offset / 0x10000) + 0x40;
		else    // when HiROM mapping is enabled, we mirror [e0-ef][0000-ffff] bank
			bank = (offset / 0x10000) + (m_bank_e_rom * 0x20);

		bank &= 0xff;
		return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
	}
	else if (offset < 0x400000)
	{
		offset -= 0x200000;
		if (!m_bank_f_hi)   // when HiROM mapping is disabled, we always access fourth 1MB here
			bank = (offset / 0x10000) + 0x60;
		else    // when HiROM mapping is enabled, we mirror [f0-ff][0000-ffff] bank
			bank = (offset / 0x10000) + (m_bank_f_rom * 0x20);

		bank &= 0xff;
		return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
	}
	else if (offset < 0x500000)
		return m_rom[rom_bank_map[(m_bank_c_rom * 0x20) + ((offset - 0x400000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
	else if (offset < 0x600000)
		return m_rom[rom_bank_map[(m_bank_d_rom * 0x20) + ((offset - 0x500000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
	else if (offset < 0x700000)
		return m_rom[rom_bank_map[(m_bank_e_rom * 0x20) + ((offset - 0x600000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
	else
		return m_rom[rom_bank_map[(m_bank_f_rom * 0x20) + ((offset - 0x700000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
}

void sns_sa1_device::write_l(offs_t offset, uint8_t data)
{
}

void sns_sa1_device::write_h(offs_t offset, uint8_t data)
{
}

uint8_t sns_sa1_device::chip_read(offs_t offset)
{
	uint16_t address = offset & 0xffff;

	if (offset < 0x400000 && address >= 0x2200 && address < 0x2400)
		return read_regs<false>(address & 0x1ff);   // SA-1 Regs

	if (offset < 0x400000 && address >= 0x3000 && address < 0x3800)
		return read_iram(address & 0x7ff);  // Internal SA-1 RAM (2K)

	if (offset < 0x400000 && address >= 0x6000 && address < 0x8000)
		return read_bwram<false>((m_bwram_snes * 0x2000) + (offset & 0x1fff)); // SA-1 BWRAM

	if (offset >= 0x400000 && offset < 0x500000)
		return read_bwram<false>(offset & 0xfffff);  // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored)

	return 0xff;
}


void sns_sa1_device::chip_write(offs_t offset, uint8_t data)
{
	uint16_t address = offset & 0xffff;

	if (offset < 0x400000 && address >= 0x2200 && address < 0x2400)
		write_regs(address & 0x1ff, data);  // SA-1 Regs

	if (offset < 0x400000 && address >= 0x3000 && address < 0x3800)
		write_iram(address & 0x7ff, data);  // Internal SA-1 RAM (2K)

	if (offset < 0x400000 && address >= 0x6000 && address < 0x8000)
		write_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff), data); // SA-1 BWRAM

	if (offset >= 0x400000 && offset < 0x500000)
		write_bwram(offset & 0xfffff, data);  // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored)
}


/*-------------------------------------------------
  Accesses from SA-1 CPU
 -------------------------------------------------*/

// These handlers basically match the SNES CPU ones, but there is no access to internal
// I/O regs or WRAM, and there are a few additional accesses to IRAM (in [00-3f][0000-07ff])
// and to BWRAM (in [60-6f][0000-ffff], so-called bitmap mode)

uint8_t sns_sa1_device::sa1_hi_r(offs_t offset)
{
	uint16_t address = offset & 0xffff;

	if (offset < 0x400000)
	{
		if (address < 0x6000)
		{
			if (address < 0x0800)
				return read_iram(offset);   // Internal SA-1 RAM (2K)
			else if (address >= 0x2200 && address < 0x2400)
				return read_regs<true>(offset & 0x1ff);    // SA-1 Regs
			else if (address >= 0x3000 && address < 0x3800)
				return read_iram(offset);   // Internal SA-1 RAM (2K)
		}
		else if (address < 0x8000)
			return read_bwram<true>((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000));        // SA-1 BWRAM
		else
			return read_h(offset);   // ROM

		return 0xff;    // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...)
	}
	else
		return read_h(offset);   // ROM
}

uint8_t sns_sa1_device::sa1_lo_r(offs_t offset)
{
	uint16_t address = offset & 0xffff;

	if (offset < 0x400000)
	{
		if (address < 0x6000)
		{
			if (address < 0x0800)
				return read_iram(offset);   // Internal SA-1 RAM (2K)
			else if (address >= 0x2200 && address < 0x2400)
				return read_regs<true>(offset & 0x1ff);    // SA-1 Regs
			else if (address >= 0x3000 && address < 0x3800)
				return read_iram(offset);   // Internal SA-1 RAM (2K)
		}
		else if (address < 0x8000)
			return read_bwram<true>((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000));        // SA-1 BWRAM
		else if (offset == 0xffee)
		{
			return m_sa1_irq & 0xff;
		}
		else if (offset == 0xffef)
		{
			return m_sa1_irq>>8;
		}
		else if (offset == 0xffea)
		{
			return m_sa1_nmi & 0xff;
		}
		else if (offset == 0xffeb)
		{
			return m_sa1_nmi>>8;
		}
		else if (offset == 0xfffc)
		{
			return m_sa1_reset & 0xff;
		}
		else if (offset == 0xfffd)
		{
			return m_sa1_reset>>8;
		}
		else
			return read_l(offset);   // ROM

		return 0xff;    // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...)
	}
	else if (offset < 0x500000)
		return read_bwram<true>(offset & 0xfffff);      // SA-1 BWRAM (not mirrored above!)
	else if (offset >= 0x600000 && offset < 0x700000)
		return read_bwram<true>((offset & 0xfffff) + 0x100000);       // SA-1 BWRAM Bitmap mode
	else
		return 0xff;    // nothing should be mapped here, so maybe open bus?
}

void sns_sa1_device::sa1_hi_w(offs_t offset, uint8_t data)
{
	uint16_t address = offset & 0xffff;
	if (offset < 0x400000)
	{
		if (address < 0x6000)
		{
			if (address < 0x0800)
				write_iram(offset, data);   // Internal SA-1 RAM (2K)
			else if (address >= 0x2200 && address < 0x2400)
				write_regs(offset & 0x1ff, data);   // SA-1 Regs
			else if (address >= 0x3000 && address < 0x3800)
				write_iram(offset, data);   // Internal SA-1 RAM (2K)
		}
		else if (address < 0x8000)
			write_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000), data);        // SA-1 BWRAM
	}
}

void sns_sa1_device::sa1_lo_w(offs_t offset, uint8_t data)
{
	if (offset >= 0x400000 && offset < 0x500000)
		write_bwram(offset & 0xfffff, data);        // SA-1 BWRAM (not mirrored above!)
	else if (offset >= 0x600000 && offset < 0x700000)
		write_bwram((offset & 0xfffff) + 0x100000, data);       // SA-1 BWRAM Bitmap mode
	else
		sa1_hi_w(offset, data);
}

void sns_sa1_device::sa1_map(address_map &map)
{
	map(0x000000, 0x7dffff).rw(FUNC(sns_sa1_device::sa1_lo_r), FUNC(sns_sa1_device::sa1_lo_w));
	map(0x7e0000, 0x7fffff).noprw();
	map(0x800000, 0xffffff).rw(FUNC(sns_sa1_device::sa1_hi_r), FUNC(sns_sa1_device::sa1_hi_w));
}


void sns_sa1_device::device_add_mconfig(machine_config &config)
{
	G65816(config, m_sa1, 10000000);
	m_sa1->set_addrmap(AS_PROGRAM, &sns_sa1_device::sa1_map);
}