summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/apple2.cpp
blob: a555b69d9f4838feccb4260f738640f94d412797 (plain) (tree)
1
2
3
4
5
6
7
8

                               





                                                                            


                                                                            
                            


                             
                             
                             
 
                     
 






                       
                                                         
 



                                      






                                                                             
                                            



 
                                                                          
 
                               
                                    
                               

 





                                                                               
                                          












                                                    
 





                                  
 
                                         
 
                                                            






                                   

                               



                                                 
                               
         
                                                            
                         
                                                                          


                                
                                                

                                                            


                                                        
                                                                                                                                 
 
                                                                           


                                                   

                                                                                       
                 
                                        
                                                     

                                                             
                                     












                                                                                                    
                                                               



                                                                                   
                                                            
                                                                            
                                                                     





                                                                                    
                                                                       

                                                                                        
                                             
                                                                       

                                                                                        
                                                
                                                                       



                                                                                                                                                     
                                 




                                                                                   
                                                                      



                                         

                                                                  

                                                                            
                                                                          




                                                         
                                                                                      
                                        
                                                                                     



                                                       

                                                                                      



                                                 
                                                                


                                                         

                                                                                 



                                                   

                                                                                         
                 
                                        



                                                                

                                                             
                                     












                                                                                                    
                                                            
                                                                             
                                                                     







                                                                                     
                                                                        

                                                                                        
                                             
                                                                        

                                                                                        
                                                
                                                                        









                                                                                    

                                                                  

                                                                             
                                                                          





                                                         
                                                                                       

                                                     
                                                                              
                                                
                                                                                              




                                                       

                                                                                       



                                                 
                                                                


                                                         

                                                                                   






                                         
                                                  
 
                               









                                                                             
                                              
         
                                           












                                                                                                                        




                                                                                








                                          
                                    












                                                                                        




                                                                       



                                         
                                              

                                                        
                         

                               
                                     
 
                              
                 

                                               
                 
 
                                             
                                                           
 


                                                       
                                                                    
                 








                                                
                 

                       

                             
                      
         
                                       

                       
 
                                     
                                                   
 
                                              
                                  
         
                                                            
         


                                                   
                                                              
 
                       
         
                                                       

                                                          

                                               

                 
                                          


                                            
                                            







                                                
                                                      
 
                                  
         
                                                                                      


                                                                
                                               

                 
                                                          


            
                                                         


                                            

                                              





                                                


                                          
                                                      
 
                                  
         
                                                          


            

                                                  








                                                
                                                      

                                            
                                  
         
                                                                                      


                                                                
                                               
                 
                                                          


            
                                                         


                                            

                                              





                                                

                    
                                                      
 
                                  
         
                                                                                      


                                                                
                                               
                 
                                                          


            

                                                  








                                                
                                                      

                                            
                                  
         
                                                                                                                   
                 
                                                 
                                               
                 
                                                          


            
                                                         


                                            

                                              





                                                

                                          
                                                      
 
                                  
         
                                                                                      


                                                                
                                               
                 
                                                          


            

                                                  





                                         
                                               


                                                   
                                       

         
                                            



                                          
                                               

                                                   
                                    
                                       
         





                                                
                                                             
 
                                  
         
                                                           

         
                                            





                                                
                                                             
 
                                  
         
                                                           






                                                
                                                             
 
                                  
         
                                                                     

         
                                            





                                                
                                                             
 
                                  
         
                                                                   






                                                
                                                         
 
                                  
         
                                                                

         
                                            





                                                
                                                         
 
                                  
         
                                                                       






                                                
                                                         
 
                                  
         
                                                                            

         
                                            





                                                
                                                         
 
                                  
         
                                                                            





                                                                                                        

                                                                                                                                        




                                                                                                        

                                                                                                                                        







                                                                                                        
                                                                                                                                          
                                                                                                                                            


            
                                                                                                                                          
                                                                                                                                            





                                                                                                        

                                                                                                                                        






                                                                                                        
                                                                                                                                          
                                                                                                                                            


            
                                                                                                                                          
                                                                                                                                            





                                                                                                        
                                                                                                                                      
                                                                                                                                        




















                                                                                                        









                                                                      














                                                                                                        

                                                                                                                                 


            

                                                                                       





                                                                                                        
 

                                                                                                                         

                                                                                                                                 


            

                                                                                       





                                                                                                        
                                                                             
         

                                                                                                                                     


            
                                                        








                                                                                                        

                                                         




                                                                                     

                                                                                                                                         


                    

                                                                 







                                                                                                        
                                    



                                                        


                                                                                                                                                        
                            


                                                                                                                                                        









                                                                                                         


                                                                                                                                                           
                            


                                                                                                                                                           








                                                                 
                                                             
         





                                                                                                        
                                    


                                               
                                                                                                                                                








                                                                                                         
                                                                                                                                                   








                                                                      
                                                             
         







































                                                          
                                                             
 
                                                                              
                                                                         



                                    

                         

                                   

                         
 
                                                                                     
                                 
 
                               










                                                                             
                                                  
 
































                                                                                                
                                                                                  


                                 



                                                   





























































































                                                                                                    
                                                                                                       







                                                                             
                                  
 

                          
                         

                                     
 






                                                                   
                                                            
 


                                                                                                        
 
                               
 
                                                            
 

                                                    
 
                                                      

                                       

 

                                    

                                                                     
 




                                                                             
                                                            



                               
                                                           

                                                                     















                                                                                              




                                                                            



                        

                                                                            


























































                                                            
                                                                       













                                                                  
                                                                       













                                                                  
                                                                       













                                                                  
                                                                       













                                                                   
                                                                       













                                                                   
                                                                       













                                                                   
                                                                       













                                                                   
                                                                       













                                                                   
                                                                       



















                                                    





                                                    





                                                    





                                                    






























                                                            
                                                                       














                                                                  
                                                                       







                                 

                                                   




                                                                  
                                                                       



                       



                                 






                                                                  
                                                                       







                                 

                                                   




                                                                   
                                                                       



                       



                                 






                                                                   
                                                                       


                       
 










                                                                   
                                                                       














                                                                   
                                                                       














                                                                   
                                                                       






                                 






                                                                            
                           
 
                                              


                                                       
                                                
































                                                                            
                      

                                 
                                                     









                                                                            
                                                             
 
                                              





                                                                  
                                                                                                    







                                                                                                          
                                                                                                    





                                                                                                          















                                                                            
                                       
                                        
                     










                                                                            
                                              


                                                   
                                            












                                                                            
                                                                                                











                                                                            
                                              


                            
                                                                                                            
 
                                                
                                                             

                 
                                            




















                                                                            
                                              
         
                              
 



                                                  
                                                                 


                                                      
                                                                 

                         







                                               
                                                             
         
                                            


















                                                                            


                                            
                                              





                                                    
                                                       
                                         
                                                                                              








                                                                  
                                                                         


                                                                    
                                                                         


                                                                                                                 
                                                                         


                                                       
                                                                                           


                                                       
                                                                                           


                                                       
                                                                                           


                                                       
                                                                                           


                                                                

                                                                                                         
                                                                    












                                                                            
                                              





                                                                           



                                                                                                            












                                                                            
                                           
                            
         
                                                                     



                                                                                          









                                                                             
                                     
 
                                                                                    

 
                                      



                                                    
                                                                 



                                                                            
                                               






                                                     
                                                



















                                                                            
                                       




                                                                
                                        







                                                                    
                                                     

                                                                            
                              


                                        
                                               






                                                        
                                                









                                                            
                                                                 



                                                                            
                                               






                                                     
                                                















                                                                            
                                               






                                                          
                                                








                                                              
                                                      
 


                                                                                 




                                               

                                                              
 


                                                         







                                                                             
                                       
 
                        

                          
 
                                           


                                                                     
                                                                          
 
                                  
                                                                  
         
                                                                      

         
                                  

                                                                                                                           

                                                          

                                                           

                       

                                                          

                                                   
 
                                     
                                                                                             
 
                                   
 
 
                                                                   

                                     
 
                         
 
                             




                                               
                                                     


                                      
                                          
 
                                  
 
                                                 

 
                                         
 
                                                                                      
 
                                                 

 
                                           

                                



                                                                              

                                                                        





                                                   
                                          



                                     


                                  
                             




                                               
                                           
                                      

 
                                           

                                     
 

                                 
 
                             
 
                                          
                                                           
                                                 










                                        



                                               
                                           
                                      

 
                                             

                                     
                                          
 

                                                                                              
 
                                 
 
                             




                                               
                                                     
                                      

 
                                          

                                     
                                          
 

                                                                                              
 
                                
 
                             




                                               
                                                     
                                      

 
                                         

                                     
                                          











                                                                                              
                                                     


                                      
                                         

                                     
 

                                                                                              
 
                               
 
                             




                                               
                                           
                                      

 
                                                        
 

                                                     



                                             






                                                                                              
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                           
 

                                                                                   
 

                                                                                   
 






















                                                                                                  

                                                                                                  











                                                                                                  
 





















                                                
                                            
 
                            
























































                                                        
                                             








                                                                  
                                                                             







                                                        

                                                   


                                             





                                                                                                              



                                            
                                                                    

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

  apple2.c

  Machine file to handle emulation of the Apple II series.

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

#include "emu.h"
#include "includes/apple2.h"

#include "imagedev/flopdrv.h"
#include "machine/appldriv.h"
#include "machine/applefdc.h"
#include "machine/sonydriv.h"

#include "debugger.h"


#ifdef MAME_DEBUG
#define VERBOSE 1
#else
#define VERBOSE 0
#endif /* MAME_DEBUG */

#define LOG(x)  do { if (VERBOSE) logerror x; } while (0)

#define PROFILER_C00X   PROFILER_USER2
#define PROFILER_C01X   PROFILER_USER2
#define PROFILER_C08X   PROFILER_USER2
#define PROFILER_A2INT  PROFILER_USER2

/* -----------------------------------------------------------------------
 * New Apple II memory manager
 * ----------------------------------------------------------------------- */

READ8_MEMBER(apple2_state::read_floatingbus)
{
	return apple2_getfloatingbusvalue();
}



void apple2_state::apple2_setup_memory(const apple2_memmap_config *config)
{
	m_mem_config = *config;
	m_current_meminfo = nullptr;
	apple2_update_memory();
}

void apple2_state::langcard_touch(offs_t offset)
{
	uint32_t val, mask;

	//logerror("language card bankswitch read, offset: $c08%0x\n", offset);

	// determine which flags to change
	mask = VAR_LCWRITE | VAR_LCRAM | VAR_LCRAM2;
	val = 0;

	if (offset & 0x01)
		val |= VAR_LCWRITE;

	switch(offset & 0x03)
	{
		case 0x03:
		case 0x00:
			val |= VAR_LCRAM;
			break;
	}

	if ((offset & 0x08) == 0)
		val |= VAR_LCRAM2;

	// change the flags
	apple2_setvar(val, mask);
}

void apple2_state::apple2_update_memory()
{
	address_space& space = m_maincpu->space(AS_PROGRAM);
	int i, bank;
	char rbank[10], wbank[10];
	int full_update = 0;
	apple2_meminfo meminfo;
	read8_delegate *rh;
	write8_delegate *wh;
	offs_t begin, end_r, end_w;
	uint8_t *rbase, *wbase;
	uint32_t offset;
	bank_disposition_t bank_disposition;
	int wh_nop = 0;

	/* need to build list of current info? */
	if (!m_current_meminfo)
	{
		for (i = 0; m_mem_config.memmap[i].end; i++)
			;
		m_current_meminfo = std::make_unique<apple2_meminfo[]>(i);
		full_update = 1;
	}

	/* loop through the entire memory map */
	bank = m_mem_config.first_bank;
	for (i = 0; m_mem_config.memmap[i].get_meminfo; i++)
	{
		/* retrieve information on this entry */
		memset(&meminfo, 0, sizeof(meminfo));
		m_mem_config.memmap[i].get_meminfo(machine(),m_mem_config.memmap[i].begin, m_mem_config.memmap[i].end, &meminfo);

		bank_disposition = m_mem_config.memmap[i].bank_disposition;

		/* do we need to memory reading? */
		if (full_update
			|| (meminfo.read_mem != m_current_meminfo[i].read_mem)
			|| (meminfo.read_handler != m_current_meminfo[i].read_handler))
		{
			rbase = nullptr;
			sprintf(rbank,"bank%d",bank);
			begin = m_mem_config.memmap[i].begin;
			end_r = m_mem_config.memmap[i].end;
			rh = nullptr;

			LOG(("apple2_update_memory():  Updating RD {%06X..%06X} [#%02d] --> %08X\n",
				begin, end_r, bank, meminfo.read_mem));

			/* read handling */
			if (meminfo.read_handler)
			{
				/* handler */
				rh = meminfo.read_handler;
			}
			else if (meminfo.read_mem == APPLE2_MEM_FLOATING)
			{
				/* floating RAM */
				rh = &read_delegates_master[0];
			}
			else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_AUX)
			{
				/* auxillary memory */
				assert(m_mem_config.auxmem);
				offset = meminfo.read_mem & APPLE2_MEM_MASK;
				rbase = &m_mem_config.auxmem[offset];
			}
			else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_SLOT)
			{
				// slots 1-2
				if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0)
				{
					rh = &read_delegates_master[1];
				}
				else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x200)
				{   // slot 3
					rh = &read_delegates_master[2];
				}
				else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x300)
				{   // slots 4-7
					rh = &read_delegates_master[3];
				}
				else
				{
					printf("ERROR: Unhandled case for APPLE2_MEM_SLOT write_mem = %x!\n", (meminfo.write_mem & APPLE2_MEM_MASK));
				}
			}
			else if ((meminfo.read_mem & 0xC0000000) == APPLE2_MEM_ROM)
			{
				/* ROM */
				offset = meminfo.read_mem & APPLE2_MEM_MASK;
				rbase = &m_rom[offset % m_rom_length];
			}
			else
			{
				/* RAM */
				if (end_r >= m_ram->size())
					end_r = m_ram->size() - 1;
				offset = meminfo.read_mem & APPLE2_MEM_MASK;
				if (end_r >= begin)
					rbase = &m_ram->pointer()[offset];
			}

			/* install the actual handlers */
			if (begin <= end_r) {
				if (rh) {
					space.install_read_handler(begin, end_r, *rh);
				} else {
					space.install_read_bank(begin, end_r, rbank);
				}
			}

			/* did we 'go past the end?' */
			if (end_r < m_mem_config.memmap[i].end)
				space.nop_read(end_r + 1, m_mem_config.memmap[i].end);

			/* set the memory bank */
			if (rbase)
			{
				membank(rbank)->set_base(rbase);
			}

			/* record the current settings */
			m_current_meminfo[i].read_mem = meminfo.read_mem;
			m_current_meminfo[i].read_handler = meminfo.read_handler;
		}

		/* do we need to memory writing? */
		if (full_update
			|| (meminfo.write_mem != m_current_meminfo[i].write_mem)
			|| (meminfo.write_handler != m_current_meminfo[i].write_handler))
		{
			wbase = nullptr;
			if (bank_disposition == A2MEM_MONO)
				sprintf(wbank,"bank%d",bank);
			else if (bank_disposition == A2MEM_DUAL)
				sprintf(wbank,"bank%d",bank+1);
			begin = m_mem_config.memmap[i].begin;
			end_w = m_mem_config.memmap[i].end;
			wh = nullptr;

			LOG(("apple2_update_memory():  Updating WR {%06X..%06X} [#%02d] --> %08X\n",
				begin, end_w, bank, meminfo.write_mem));

			/* write handling */
			if (meminfo.write_handler)
			{
				/* handler */
				wh = meminfo.write_handler;
			}
			else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_AUX)
			{
				/* auxillary memory */
				assert(m_mem_config.auxmem);
				offset = meminfo.write_mem & APPLE2_MEM_MASK;
				wbase = &m_mem_config.auxmem[offset];
			}
			else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_SLOT)
			{
				/* slot RAM/ROM */

				// slots 1-2
				if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0)
				{
					wh = &write_delegates_master[0];
				}
				else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x200)
				{   // slot 3
					wh = &write_delegates_master[1];
				}
				else if ((meminfo.write_mem & APPLE2_MEM_MASK) == 0x300)
				{   // slots 4-7
					wh = &write_delegates_master[2];
				}
			}
			else if ((meminfo.write_mem & 0xC0000000) == APPLE2_MEM_ROM)
			{
				/* ROM */
				wh_nop = 1;
			}
			else
			{
				/* RAM */
				if (end_w >= m_ram->size())
					end_w = m_ram->size() - 1;
				offset = meminfo.write_mem & APPLE2_MEM_MASK;
				if (end_w >= begin)
					wbase = &m_ram->pointer()[offset];
			}


			/* install the actual handlers */
			if (begin <= end_w) {
				if (wh) {
					space.install_write_handler(begin, end_w, *wh);
				} else {
					if (wh_nop) {
						space.nop_write(begin, end_w);
					} else {
						space.install_write_bank(begin, end_w, wbank);
					}
				}
			}

			/* did we 'go past the end?' */
			if (end_w < m_mem_config.memmap[i].end)
				space.nop_write(end_w + 1, m_mem_config.memmap[i].end);

			/* set the memory bank */
			if (wbase)
			{
				membank(wbank)->set_base(wbase);
			}

			/* record the current settings */
			m_current_meminfo[i].write_mem = meminfo.write_mem;
			m_current_meminfo[i].write_handler = meminfo.write_handler;
		}
		bank += bank_disposition;
	}
}



void apple2_state::apple2_update_memory_postload()
{
	apple2_update_memory();
}



/* -----------------------------------------------------------------------
 * Apple II memory map
 * ----------------------------------------------------------------------- */

READ8_MEMBER(apple2_state::apple2_c0xx_r)
{
	if(!machine().side_effects_disabled())
	{
		read8_delegate handlers[] =
		{
			read8_delegate(FUNC(apple2_state::apple2_c00x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c01x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c02x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c03x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c03x_r), this),   // not called here, handled elsewhere
			read8_delegate(FUNC(apple2_state::apple2_c05x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c06x_r), this),
			read8_delegate(FUNC(apple2_state::apple2_c07x_r), this)
		};

		offset &= 0x7F;

		/* normal handler */
		if (offset / 0x10 != 4)
		{
			return handlers[offset / 0x10](space, offset % 0x10, 0);
		}
	}

	return 0;
}



WRITE8_MEMBER(apple2_state::apple2_c0xx_w)
{
	write8_delegate handlers[] =
	{
		write8_delegate(FUNC(apple2_state::apple2_c00x_w), this),
		write8_delegate(FUNC(apple2_state::apple2_c01x_w), this),
		write8_delegate(FUNC(apple2_state::apple2_c02x_w), this),
		write8_delegate(FUNC(apple2_state::apple2_c03x_w), this),
		write8_delegate(FUNC(apple2_state::apple2_c03x_w), this),      // unused
		write8_delegate(FUNC(apple2_state::apple2_c05x_w), this),
		write8_delegate(FUNC(apple2_state::apple2_c05x_w), this),      // unused
		write8_delegate(FUNC(apple2_state::apple2_c07x_w), this)
	};

	offset &= 0x7F;

	/* normal handler */
	if (((offset / 0x10) != 4) && (offset / 0x10) != 6)
	{
		handlers[offset / 0x10](space, offset % 0x10, data, 0);
	}
}

READ8_MEMBER(apple2_state::apple2_c080_r)
{
	if(!machine().side_effects_disabled())
	{
		device_a2bus_card_interface *slotdevice;
		int slot;

		offset &= 0x7F;
		slot = offset / 0x10;

		if (slot == 0)
		{
			langcard_touch(offset);
			return 0;
		}

		/* now identify the device */
		slotdevice = m_a2bus->get_a2bus_card(slot);

		/* and if we can, read from the slot */
		if (slotdevice != nullptr)
		{
			return slotdevice->read_c0nx(offset % 0x10);
		}
	}

	return 0;
}


WRITE8_MEMBER(apple2_state::apple2_c080_w)
{
	device_a2bus_card_interface *slotdevice;
	int slot;

	offset &= 0x7F;
	slot = offset / 0x10;

	if (slot == 0)
	{
		langcard_touch(offset);
		return;
	}

	/* now identify the device */
	slotdevice = m_a2bus->get_a2bus_card(slot);

	/* and if we can, write to the slot */
	if (slotdevice != nullptr)
	{
		slotdevice->write_c0nx(offset % 0x10, data);
	}
}

/* returns default CnXX slotram for a slot space */
int8_t apple2_state::apple2_slotram_r(int slotnum, int offset)
{
	if (m_slot_ram)
	{
		if (!machine().side_effects_disabled())
		{
//          printf("slotram_r: taking cnxx_slot to -1\n");
			m_a2_cnxx_slot = -1;
			apple2_update_memory();
		}

		return m_slot_ram[offset];
	}

	// else fall through to floating bus
	return apple2_getfloatingbusvalue();
}

READ8_MEMBER(apple2_state::apple2_c1xx_r )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = ((offset>>8) & 0xf) + 1;
	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	if (slotdevice != nullptr)
	{
		if ((slotdevice->take_c800()) && (!machine().side_effects_disabled()))
		{
//          printf("c1xx_r: taking cnxx_slot to %d\n", slotnum);
			m_a2_cnxx_slot = slotnum;
			apple2_update_memory();
		}

		return slotdevice->read_cnxx(offset&0xff);
	}
	else
	{
		return apple2_slotram_r(slotnum, offset);
	}

	// else fall through to floating bus
	// never executed
	//return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_c1xx_w )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = ((offset>>8) & 0xf) + 1;

	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	if (slotdevice != nullptr)
	{
		slotdevice->write_cnxx(offset&0xff, data);
	}
	else
	{
		if (m_slot_ram)
			m_slot_ram[offset] = data;
	}
}

READ8_MEMBER(apple2_state::apple2_c3xx_r )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = 3;
	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	// is a card installed in this slot?
	if (slotdevice != nullptr)
	{
		if ((slotdevice->take_c800()) && (!machine().side_effects_disabled()))
		{
//          printf("c3xx_r: taking cnxx_slot to %d\n", slotnum);
			m_a2_cnxx_slot = slotnum;
			apple2_update_memory();
		}
		return slotdevice->read_cnxx(offset&0xff);
	}
	else
	{
		return apple2_slotram_r(slotnum, offset);
	}

	// else fall through to floating bus
	// never executed
	//return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_c3xx_w )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = 3;
	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	if (slotdevice != nullptr)
	{
		if ((slotdevice->take_c800()) && (!machine().side_effects_disabled()))
		{
//          printf("c3xx_w: taking cnxx_slot to %d\n", slotnum);
			m_a2_cnxx_slot = slotnum;
			apple2_update_memory();
		}
		slotdevice->write_cnxx(offset&0xff, data);
	}
	else
	{
		if (m_slot_ram)
			m_slot_ram[offset] = data;
	}
}

READ8_MEMBER(apple2_state::apple2_c4xx_r )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = ((offset>>8) & 0xf) + 4;
	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	// is a card installed in this slot?
	if (slotdevice != nullptr)
	{
		if (slotdevice->take_c800() && (m_a2_cnxx_slot != slotnum) && (!machine().side_effects_disabled()))
		{
			m_a2_cnxx_slot = slotnum;
			apple2_update_memory();
		}
		return slotdevice->read_cnxx(offset&0xff);
	}
	else
	{
		return apple2_slotram_r(slotnum, offset);
	}

	// else fall through to floating bus
	// never executed
	//return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER ( apple2_state::apple2_c4xx_w )
{
	int slotnum;
	device_a2bus_card_interface *slotdevice;

	slotnum = ((offset>>8) & 0xf) + 4;
	slotdevice = m_a2bus->get_a2bus_card(slotnum);

	if (slotdevice != nullptr)
	{
		if ((slotdevice->take_c800()) && (!machine().side_effects_disabled()))
		{
//          printf("c4xx_w: taking cnxx_slot to %d\n", slotnum);
			m_a2_cnxx_slot = slotnum;
			apple2_update_memory();
		}
		slotdevice->write_cnxx(offset&0xff, data);
	}
	else
	{
		if (m_slot_ram)
			m_slot_ram[offset] = data;
	}
}

READ8_MEMBER(apple2_state::apple2_cfff_r)
{
	// debugger guard
	if (!machine().side_effects_disabled())
	{
//      printf("cfff_r: taking cnxx_slot to -1\n");
		m_a2_cnxx_slot = -1;
		apple2_update_memory();
	}

	return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_cfff_w)
{
	if (!machine().side_effects_disabled())
	{
//      printf("cfff_w: taking cnxx_slot to -1\n");
		m_a2_cnxx_slot = -1;
		apple2_update_memory();
	}
}

READ8_MEMBER(apple2_state::apple2_c800_r )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);

	if (slotdevice != nullptr)
	{
		return slotdevice->read_c800(offset&0xfff);
	}

	return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_c800_w )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);

	if (slotdevice != nullptr)
	{
		slotdevice->write_c800(offset&0xfff, data);
	}
}

READ8_MEMBER(apple2_state::apple2_ce00_r )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);

	if (slotdevice != nullptr)
	{
		return slotdevice->read_c800((offset&0xfff) + 0x600);
	}

	return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_ce00_w )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_a2_cnxx_slot);

	if (slotdevice != nullptr)
	{
		slotdevice->write_c800((offset&0xfff)+0x600, data);
	}
}

READ8_MEMBER(apple2_state::apple2_inh_d000_r )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);

	if (slotdevice != nullptr)
	{
		return slotdevice->read_inh_rom(offset & 0xfff);
	}

	return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_inh_d000_w )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);

	if (slotdevice != nullptr)
	{
		return slotdevice->write_inh_rom(offset & 0xfff, data);
	}
}

READ8_MEMBER(apple2_state::apple2_inh_e000_r )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);

	if (slotdevice != nullptr)
	{
		return slotdevice->read_inh_rom((offset & 0x1fff) + 0x1000);
	}

	return apple2_getfloatingbusvalue();
}

WRITE8_MEMBER(apple2_state::apple2_inh_e000_w )
{
	device_a2bus_card_interface *slotdevice;

	slotdevice = m_a2bus->get_a2bus_card(m_inh_slot);

	if (slotdevice != nullptr)
	{
		slotdevice->write_inh_rom((offset & 0x1fff) + 0x1000, data);
	}
}

static void apple2_mem_0000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	meminfo->read_handler       = (state->m_flags & VAR_ALTZP)  ? &state->read_delegates_0000[0] : &state->read_delegates_0000[1];
	meminfo->write_handler      = (state->m_flags & VAR_ALTZP)  ? &state->write_delegates_0000[0] : &state->write_delegates_0000[1];
}

static void apple2_mem_0200(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	meminfo->read_handler       = (state->m_flags & VAR_RAMRD)  ? &state->read_delegates_0200[0] : &state->read_delegates_0200[1];
	meminfo->write_handler      = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0200[0] : &state->write_delegates_0200[1];
}

static void apple2_mem_0400(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	if (state->m_flags & VAR_80STORE)
	{
		meminfo->read_handler   = (state->m_flags & VAR_PAGE2)  ? &state->read_delegates_0400[0] : &state->read_delegates_0400[1];
		meminfo->write_handler  = (state->m_flags & VAR_PAGE2)  ? &state->write_delegates_0400[0] : &state->write_delegates_0400[1];
	}
	else
	{
		meminfo->read_handler   = (state->m_flags & VAR_RAMRD)  ? &state->read_delegates_0400[0] : &state->read_delegates_0400[1];
		meminfo->write_handler  = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0400[0] : &state->write_delegates_0400[1];
	}
}

static void apple2_mem_0800(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	meminfo->read_handler       = (state->m_flags & VAR_RAMRD)  ? &state->read_delegates_0800[0] : &state->read_delegates_0800[1];
	meminfo->write_handler      = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_0800[0] : &state->write_delegates_0800[1];
}

static void apple2_mem_2000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	if ((state->m_flags & (VAR_80STORE|VAR_HIRES)) == (VAR_80STORE|VAR_HIRES))
	{
		meminfo->read_handler   = (state->m_flags & VAR_PAGE2)  ? &state->read_delegates_2000[0] : &state->read_delegates_2000[1];
		meminfo->write_handler  = (state->m_flags & VAR_PAGE2)  ? &state->write_delegates_2000[0] : &state->write_delegates_2000[1];
	}
	else
	{
		meminfo->read_handler   = (state->m_flags & VAR_RAMRD)  ? &state->read_delegates_2000[0] : &state->read_delegates_2000[1];
		meminfo->write_handler  = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_2000[0] : &state->write_delegates_2000[1];
	}
}

static void apple2_mem_4000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	meminfo->read_handler       = (state->m_flags & VAR_RAMRD)  ? &state->read_delegates_4000[0] : &state->read_delegates_4000[1];
	meminfo->write_handler      = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_4000[0] : &state->write_delegates_4000[1];
}

static void apple2_mem_C000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	meminfo->read_handler = &state->rd_c000;
	meminfo->write_handler = &state->wd_c000;
}

static void apple2_mem_C080(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	meminfo->read_handler = &state->rd_c080;
	meminfo->write_handler = &state->wd_c080;
}

static void tk2000_mem_C100(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	if (state->m_flags & VAR_TK2000RAM)
	{
		meminfo->read_mem = 0x00C100;
		meminfo->write_mem = 0x00C100;
	}
	else
	{
		meminfo->read_mem = (begin & 0x3fff) | APPLE2_MEM_ROM;
		meminfo->write_mem = 0x00C100;
	}
}

static void apple2_mem_CFFF(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	meminfo->read_handler = &state->rd_cfff;
	meminfo->write_handler = &state->wd_cfff;
}

static void apple2_mem_Cx00(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	if (state->m_flags & VAR_INTCXROM)
	{
		meminfo->read_mem       = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
		meminfo->write_mem      = APPLE2_MEM_FLOATING;
	}
	else
	{
		meminfo->read_mem       = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
		meminfo->write_mem      = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
	}
}

static void apple2_mem_C300(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	if (((state->m_flags & (VAR_INTCXROM|VAR_SLOTC3ROM)) != VAR_SLOTC3ROM) && !(state->m_flags_mask & VAR_SLOTC3ROM))
	{
		meminfo->read_mem       = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
		meminfo->write_mem      = APPLE2_MEM_FLOATING;
	}
	else
	{
		meminfo->read_mem       = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
		meminfo->write_mem      = ((begin & 0x0FFF) - 0x100) | APPLE2_MEM_SLOT;
	}
}

static void apple2_mem_C800(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	if ((state->m_flags & VAR_INTCXROM) || (state->m_a2_cnxx_slot == -1))
	{
		meminfo->read_mem           = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
		meminfo->write_mem          = APPLE2_MEM_FLOATING;
	}
	else
	{
		meminfo->read_handler = &state->rd_c800;
		meminfo->write_handler = &state->wd_c800;
	}
}

static void apple2_mem_CE00(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();
	if ((state->m_flags & VAR_ROMSWITCH) && !strcmp(machine.system().name, "apple2cp"))
	{
		meminfo->read_mem       = APPLE2_MEM_AUX;
		meminfo->write_mem      = APPLE2_MEM_AUX;
	}
	else
	{
		if ((state->m_flags & VAR_INTCXROM) || (state->m_a2_cnxx_slot == -1))
		{
			meminfo->read_mem       = (begin & 0x0FFF) | (state->m_flags & VAR_ROMSWITCH ? 0x4000 : 0x0000) | APPLE2_MEM_ROM;
			meminfo->write_mem      = APPLE2_MEM_FLOATING;
		}
		else
		{
			meminfo->read_handler = &state->rd_ce00;
			meminfo->write_handler = &state->wd_ce00;
		}
	}
}

static void apple2_mem_D000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	if (state->m_inh_slot == -1)
	{
		if (state->m_flags & VAR_LCRAM)
		{
			if (state->m_flags & VAR_LCRAM2)
			{
				meminfo->read_handler = (state->m_flags & VAR_ALTZP)  ? &state->read_delegates_c000[0] : &state->read_delegates_c000[1];
			}
			else
			{
				meminfo->read_handler = (state->m_flags & VAR_ALTZP)  ? &state->read_delegates_d000[0] : &state->read_delegates_d000[1];
			}
		}
		else
		{
			meminfo->read_mem       = (state->m_flags & VAR_ROMSWITCH) ? 0x005000 : 0x001000;
			meminfo->read_mem       |= APPLE2_MEM_ROM;
		}

		if (state->m_flags & VAR_LCWRITE)
		{
			if (state->m_flags & VAR_LCRAM2)
			{
				meminfo->write_handler  = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_c000[0] : &state->write_delegates_c000[1];
			}
			else
			{
				meminfo->write_handler  = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_d000[0] : &state->write_delegates_d000[1];
			}
		}
		else
		{
			meminfo->write_mem = APPLE2_MEM_FLOATING;
		}
	}
	else
	{
		meminfo->read_handler = &state->rd_inh_d000;
		meminfo->write_handler = &state->wd_inh_d000;
	}
}

static void apple2_mem_E000(running_machine &machine, offs_t begin, offs_t end, apple2_meminfo *meminfo)
{
	apple2_state *state = machine.driver_data<apple2_state>();

	if (state->m_inh_slot == -1)
	{
		if (state->m_flags & VAR_LCRAM)
		{
			meminfo->read_handler = (state->m_flags & VAR_ALTZP)  ? &state->read_delegates_e000[0] : &state->read_delegates_e000[1];
		}
		else
		{
			meminfo->read_mem       = (state->m_flags & VAR_ROMSWITCH) ? 0x006000 : 0x002000;
			meminfo->read_mem       |= APPLE2_MEM_ROM;
		}

		if (state->m_flags & VAR_LCWRITE)
		{
			meminfo->write_handler  = (state->m_flags & VAR_ALTZP) ? &state->write_delegates_e000[0] : &state->write_delegates_e000[1];
		}
		else
		{
			meminfo->write_mem      = APPLE2_MEM_FLOATING;
		}
	}
	else
	{
		meminfo->read_handler = &state->rd_inh_e000;
		meminfo->write_handler = &state->wd_inh_e000;
	}
}



static const apple2_memmap_entry apple2_memmap_entries[] =
{
	{ 0x0000, 0x01FF, apple2_mem_0000, A2MEM_MONO },
	{ 0x0200, 0x03FF, apple2_mem_0200, A2MEM_DUAL },
	{ 0x0400, 0x07FF, apple2_mem_0400, A2MEM_DUAL },
	{ 0x0800, 0x1FFF, apple2_mem_0800, A2MEM_DUAL },
	{ 0x2000, 0x3FFF, apple2_mem_2000, A2MEM_DUAL },
	{ 0x4000, 0xBFFF, apple2_mem_4000, A2MEM_DUAL },
	{ 0xC000, 0xC07F, apple2_mem_C000, A2MEM_IO },
	{ 0xC080, 0xC0FF, apple2_mem_C080, A2MEM_IO },
	{ 0xC100, 0xC2FF, apple2_mem_Cx00, A2MEM_MONO },
	{ 0xC300, 0xC3FF, apple2_mem_C300, A2MEM_MONO },
	{ 0xC400, 0xC7FF, apple2_mem_Cx00, A2MEM_MONO },
	{ 0xC800, 0xCDFF, apple2_mem_C800, A2MEM_MONO },
	{ 0xCE00, 0xCFFE, apple2_mem_CE00, A2MEM_MONO },
	{ 0xCFFF, 0xCFFF, apple2_mem_CFFF, A2MEM_IO },
	{ 0xD000, 0xDFFF, apple2_mem_D000, A2MEM_DUAL },
	{ 0xE000, 0xFFFF, apple2_mem_E000, A2MEM_DUAL },
	{ 0 }
};


static const apple2_memmap_entry tk2000_memmap_entries[] =
{
	{ 0x0000, 0x01FF, apple2_mem_0000, A2MEM_MONO },
	{ 0x0200, 0x03FF, apple2_mem_0200, A2MEM_DUAL },
	{ 0x0400, 0x07FF, apple2_mem_0400, A2MEM_DUAL },
	{ 0x0800, 0x1FFF, apple2_mem_0800, A2MEM_DUAL },
	{ 0x2000, 0x3FFF, apple2_mem_2000, A2MEM_DUAL },
	{ 0x4000, 0xBFFF, apple2_mem_4000, A2MEM_DUAL },
	{ 0xC000, 0xC07F, apple2_mem_C000, A2MEM_IO },
	{ 0xC080, 0xC0FF, apple2_mem_C080, A2MEM_IO },
	{ 0xC100, 0xFFFF, tk2000_mem_C100, A2MEM_DUAL },
	{ 0 }
};

void apple2_state::apple2_setvar(uint32_t val, uint32_t mask)
{
	LOG(("apple2_setvar(): val=0x%06x mask=0x%06x pc=0x%04x\n", val, mask,
					(unsigned int) m_maincpu->pc()));

	assert((val & mask) == val);

	/* apply mask and set */
	val &= m_a2_mask;
	val |= m_a2_set;

	/* change the softswitch */
	m_flags &= ~mask;
	m_flags |= val;

	// disable flags that don't apply (INTCXROM/SLOTC3ROM on II/II+ for instance)
	m_flags &= ~m_flags_mask;

	apple2_update_memory();
}



/* -----------------------------------------------------------------------
 * Floating bus code
 *
 *     preliminary floating bus video scanner code - look for comments
 *     with FIX:
 * ----------------------------------------------------------------------- */

uint8_t apple2_state::apple2_getfloatingbusvalue()
{
	enum
	{
		// scanner types
		kScannerNone = 0, kScannerApple2, kScannerApple2e,

		// scanner constants
		kHBurstClock      =    53, // clock when Color Burst starts
		kHBurstClocks     =     4, // clocks per Color Burst duration
		kHClock0State     =  0x18, // H[543210] = 011000
		kHClocks          =    65, // clocks per horizontal scan (including HBL)
		kHPEClock         =    40, // clock when HPE (horizontal preset enable) goes low
		kHPresetClock     =    41, // clock when H state presets
		kHSyncClock       =    49, // clock when HSync starts
		kHSyncClocks      =     4, // clocks per HSync duration
		kNTSCScanLines    =   262, // total scan lines including VBL (NTSC)
		kNTSCVSyncLine    =   224, // line when VSync starts (NTSC)
		kPALScanLines     =   312, // total scan lines including VBL (PAL)
		kPALVSyncLine     =   264, // line when VSync starts (PAL)
		kVLine0State      = 0x100, // V[543210CBA] = 100000000
		kVPresetLine      =   256, // line when V state presets
		kVSyncLines       =     4, // lines per VSync duration
		kClocksPerVSync   = kHClocks * kNTSCScanLines // FIX: NTSC only?
	};

	// vars
	//
	int i, Hires, Mixed, Page2, _80Store, ScanLines, /* VSyncLine, ScanCycles,*/
		h_clock, h_state, h_0, h_1, h_2, h_3, h_4, h_5,
		v_line, v_state, v_A, v_B, v_C, v_0, v_1, v_2, v_3, v_4, /* v_5, */
		_hires, addend0, addend1, addend2, sum, address;

	// video scanner data
	//
	i = m_maincpu->total_cycles() % kClocksPerVSync; // cycles into this VSync

	// machine state switches
	//
	Hires    = (m_flags & VAR_HIRES) ? 1 : 0;
	Mixed    = (m_flags & VAR_MIXED) ? 1 : 0;
	Page2    = (m_flags & VAR_PAGE2) ? 1 : 0;
	_80Store = (m_flags & VAR_80STORE) ? 1 : 0;

	// calculate video parameters according to display standard
	//
	ScanLines  = 1 ? kNTSCScanLines : kPALScanLines; // FIX: NTSC only?
	// VSyncLine  = 1 ? kNTSCVSyncLine : kPALVSyncLine; // FIX: NTSC only?
	// ScanCycles = ScanLines * kHClocks;

	// calculate horizontal scanning state
	//
	h_clock = (i + kHPEClock) % kHClocks; // which horizontal scanning clock
	h_state = kHClock0State + h_clock; // H state bits
	if (h_clock >= kHPresetClock) // check for horizontal preset
	{
		h_state -= 1; // correct for state preset (two 0 states)
	}
	h_0 = (h_state >> 0) & 1; // get horizontal state bits
	h_1 = (h_state >> 1) & 1;
	h_2 = (h_state >> 2) & 1;
	h_3 = (h_state >> 3) & 1;
	h_4 = (h_state >> 4) & 1;
	h_5 = (h_state >> 5) & 1;

	// calculate vertical scanning state
	//
	v_line  = i / kHClocks; // which vertical scanning line
	v_state = kVLine0State + v_line; // V state bits
	if ((v_line >= kVPresetLine)) // check for previous vertical state preset
	{
		v_state -= ScanLines; // compensate for preset
	}
	v_A = (v_state >> 0) & 1; // get vertical state bits
	v_B = (v_state >> 1) & 1;
	v_C = (v_state >> 2) & 1;
	v_0 = (v_state >> 3) & 1;
	v_1 = (v_state >> 4) & 1;
	v_2 = (v_state >> 5) & 1;
	v_3 = (v_state >> 6) & 1;
	v_4 = (v_state >> 7) & 1;
	//v_5 = (v_state >> 8) & 1;

	// calculate scanning memory address
	//
	_hires = Hires;
	if (Hires && Mixed && (v_4 & v_2))
	{
		_hires = 0; // (address is in text memory)
	}

	addend0 = 0x68; // 1            1            0            1
	addend1 =              (h_5 << 5) | (h_4 << 4) | (h_3 << 3);
	addend2 = (v_4 << 6) | (v_3 << 5) | (v_4 << 4) | (v_3 << 3);
	sum     = (addend0 + addend1 + addend2) & (0x0F << 3);

	address = 0;
	address |= h_0 << 0; // a0
	address |= h_1 << 1; // a1
	address |= h_2 << 2; // a2
	address |= sum;      // a3 - aa6
	address |= v_0 << 7; // a7
	address |= v_1 << 8; // a8
	address |= v_2 << 9; // a9
	address |= ((_hires) ? v_A : (1 ^ (Page2 & (1 ^ _80Store)))) << 10; // a10
	address |= ((_hires) ? v_B : (Page2 & (1 ^ _80Store))) << 11; // a11
	if (_hires) // hires?
	{
		// Y: insert hires only address bits
		//
		address |= v_C << 12; // a12
		address |= (1 ^ (Page2 & (1 ^ _80Store))) << 13; // a13
		address |= (Page2 & (1 ^ _80Store)) << 14; // a14
	}
	else
	{
		// N: text, so no higher address bits unless Apple ][, not Apple //e
		//
		if ((1) && // Apple ][? // FIX: check for Apple ][? (FB is most useful in old games)
			(kHPEClock <= h_clock) && // Y: HBL?
			(h_clock <= (kHClocks - 1)))
		{
			address |= 1 << 12; // Y: a12 (add $1000 to address!)
		}
	}

	// update VBL' state
	//
	if (v_4 & v_3) // VBL?
	{
		//CMemory::mState &= ~CMemory::kVBLBar; // Y: VBL' is false // FIX: MESS?
	}
	else
	{
		//CMemory::mState |= CMemory::kVBLBar; // N: VBL' is true // FIX: MESS?
	}

	return m_ram->pointer()[address % m_ram->size()]; // FIX: this seems to work, but is it right!?
}



/* -----------------------------------------------------------------------
 * Machine reset
 * ----------------------------------------------------------------------- */

void apple2_state::machine_reset()
{
	int need_intcxrom;

	m_reset_flag = 0;
	m_rambase = m_ram->pointer();
	apple2_refresh_delegates();

	need_intcxrom = !strcmp(machine().system().name, "apple2c")
		|| !strcmp(machine().system().name, "apple2c0")
		|| !strcmp(machine().system().name, "apple2c3")
		|| !strcmp(machine().system().name, "apple2c4")
		|| !strcmp(machine().system().name, "prav8c")
		|| !strcmp(machine().system().name, "apple2cp")
		|| !strncmp(machine().system().name, "apple2g", 7);
	apple2_setvar(need_intcxrom ? VAR_INTCXROM : 0, ~0);

	// IIgs ROM 0 cannot boot unless language card bank 2 is write-enabled (but read ROM) on startup
	// Peter Ferrie reports this is also the default on the IIe/IIc at least
	apple2_setvar(VAR_LCWRITE|VAR_LCRAM2, VAR_LCWRITE | VAR_LCRAM | VAR_LCRAM2);

	m_a2_speaker_state = 0;

	m_a2_cnxx_slot = -1; // bank in ROM at C800 on reset

	m_joystick_x1_time = m_joystick_y1_time = 0;
	m_joystick_x2_time = m_joystick_y2_time = 0;

	memset(m_exp_regs, 0, sizeof(uint8_t) * 0x10);
	m_exp_wptr = m_exp_liveptr = 0;

}

int apple2_state::a2_no_ctrl_reset()
{
	return ((m_kbrepeat.found() && !m_resetdip.found()) ||
			(m_resetdip.found() && !m_resetdip->read()));
}

/* -----------------------------------------------------------------------
 * Apple II interrupt; used to force partial updates
 * ----------------------------------------------------------------------- */

TIMER_DEVICE_CALLBACK_MEMBER(apple2_state::apple2_interrupt)
{
	int scanline = param;

	if((scanline % 8) == 0)
		m_screen->update_partial(m_screen->vpos());
	if ((m_kbspecial->read() & 0x80) &&
		(a2_no_ctrl_reset() || (m_kbspecial->read() & 0x08)))
	{
			if (!m_reset_flag)
			{
				m_reset_flag = 1;
				/* using PULSE_LINE does not allow us to press and hold key */
				m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
			}
			return;
	}

	if (m_reset_flag)
	{
		m_reset_flag = 0;
		m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
		machine().schedule_soft_reset();
	}
}



/***************************************************************************
    apple2_mainramxx00_r
    apple2_mainramxx00_w
    apple2_auxramxx00_r
    apple2_auxramxx00_w
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_mainram0000_r )
{
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainram0200_r )
{
	offset += 0x200;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainram0400_r )
{
	offset += 0x400;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainram0800_r )
{
	offset += 0x800;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainram2000_r )
{
	offset += 0x2000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainram4000_r )
{
	offset += 0x4000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainramc000_r )
{
	offset += 0xc000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainramd000_r )
{
	offset += 0xd000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_mainrame000_r )
{
	offset += 0xe000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram0000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x10000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram0200_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0x200);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x10200;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram0400_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0x400);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x10400;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram0800_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0x800);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x10800;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram2000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0x2000);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x12000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxram4000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0x4000);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x14000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxramc000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0xc000);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x1c000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxramd000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0xd000);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x1d000;
	return m_rambase[offset];
}

READ8_MEMBER ( apple2_state::apple2_auxrame000_r )
{
	if (m_auxslotdevice)
	{
		return m_auxslotdevice->read_auxram(offset+0xe000);
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return 0xff;
	}

	offset += 0x1e000;
	return m_rambase[offset];
}


WRITE8_MEMBER ( apple2_state::apple2_mainram0000_w )
{
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainram0200_w )
{
	offset += 0x200;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainram0400_w )
{
	offset += 0x400;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainram0800_w )
{
	offset += 0x800;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainram2000_w )
{
	offset += 0x2000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainram4000_w )
{
	offset += 0x4000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainramc000_w )
{
	offset += 0xc000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainramd000_w )
{
	offset += 0xd000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_mainrame000_w )
{
	offset += 0xe000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram0000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x10000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram0200_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0x200, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x10200;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram0400_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0x400, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x10400;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram0800_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0x800, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x10800;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram2000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0x2000, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x12000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxram4000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0x4000, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x14000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxramc000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0xc000, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x1c000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxramd000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0xd000, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x1d000;
	m_rambase[offset] = data;
}

WRITE8_MEMBER ( apple2_state::apple2_auxrame000_w )
{
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_auxram(offset+0xe000, data);
		return;
	}
	else if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		return;
	}

	offset += 0x1e000;
	m_rambase[offset] = data;
}

/***************************************************************************
  apple2_c00x_r
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_c00x_r )
{
	uint8_t result = 0;

	if(!machine().side_effects_disabled())
	{
		/* Read the keyboard data and strobe */
		g_profiler.start(PROFILER_C00X);
		result = m_transchar | m_strobe;
		g_profiler.stop();
	}



	return result;
}



/***************************************************************************
  apple2_c00x_w

  C000  80STOREOFF
  C001  80STOREON - use 80-column memory mapping
  C002  RAMRDOFF
  C003  RAMRDON - read from aux 48k
  C004  RAMWRTOFF
  C005  RAMWRTON - write to aux 48k
  C006  INTCXROMOFF
  C007  INTCXROMON
  C008  ALTZPOFF
  C009  ALTZPON - use aux ZP, stack and language card area
  C00A  SLOTC3ROMOFF
  C00B  SLOTC3ROMON - use external slot 3 ROM
  C00C  80COLOFF
  C00D  80COLON - use 80-column display mode
  C00E  ALTCHARSETOFF
  C00F  ALTCHARSETON - use alt character set
***************************************************************************/

WRITE8_MEMBER ( apple2_state::apple2_c00x_w )
{
	uint32_t mask;

	mask = 1 << (offset / 2);
	apple2_setvar((offset & 1) ? mask : 0, mask);
}



/***************************************************************************
  apple2_c01x_r
***************************************************************************/

READ8_MEMBER( apple2_state::apple2_c01x_r )
{
	uint8_t result = apple2_getfloatingbusvalue() & 0x7F;

	if(!machine().side_effects_disabled())
	{
		g_profiler.start(PROFILER_C01X);

		LOG(("a2 softswitch_r: %04x\n", offset + 0xc010));
		switch (offset)
		{
			case 0x00:          result |= m_transchar | m_strobe;  m_strobe = 0;  break;
			case 0x01:          result |= (m_flags & VAR_LCRAM2)        ? 0x80 : 0x00;  break;
			case 0x02:          result |= (m_flags & VAR_LCRAM)     ? 0x80 : 0x00;  break;
			case 0x03:          result |= (m_flags & VAR_RAMRD)     ? 0x80 : 0x00;  break;
			case 0x04:          result |= (m_flags & VAR_RAMWRT)        ? 0x80 : 0x00;  break;
			case 0x05:          result |= (m_flags & VAR_INTCXROM)  ? 0x80 : 0x00;  break;
			case 0x06:          result |= (m_flags & VAR_ALTZP)     ? 0x80 : 0x00;  break;
			case 0x07:          result |= (m_flags & VAR_SLOTC3ROM) ? 0x80 : 0x00;  break;
			case 0x08:          result |= (m_flags & VAR_80STORE)   ? 0x80 : 0x00;  break;
			case 0x09:          result |= !m_screen->vblank()     ? 0x80 : 0x00;  break;
			case 0x0A:          result |= (m_flags & VAR_TEXT)      ? 0x80 : 0x00;  break;
			case 0x0B:          result |= (m_flags & VAR_MIXED)     ? 0x80 : 0x00;  break;
			case 0x0C:          result |= (m_flags & VAR_PAGE2)     ? 0x80 : 0x00;  break;
			case 0x0D:          result |= (m_flags & VAR_HIRES)     ? 0x80 : 0x00;  break;
			case 0x0E:          result |= (m_flags & VAR_ALTCHARSET)    ? 0x80 : 0x00;  break;
			case 0x0F:          result |= (m_flags & VAR_80COL)     ? 0x80 : 0x00;  break;
		}

		g_profiler.stop();
	}

	return result;
}



/***************************************************************************
  apple2_c01x_w
***************************************************************************/

WRITE8_MEMBER( apple2_state::apple2_c01x_w )
{
	/* Clear the keyboard strobe */
	g_profiler.start(PROFILER_C01X);
	m_strobe = 0;
	g_profiler.stop();
}



/***************************************************************************
  apple2_c02x_r
***************************************************************************/

READ8_MEMBER( apple2_state::apple2_c02x_r )
{
	if(!machine().side_effects_disabled())
	{
		apple2_c02x_w(space, offset, 0, 0);
	}
	return apple2_getfloatingbusvalue();
}



/***************************************************************************
  apple2_c02x_w
***************************************************************************/

WRITE8_MEMBER( apple2_state::apple2_c02x_w )
{
	switch(offset)
	{
		case 0x08:
			apple2_setvar((m_flags & VAR_ROMSWITCH) ^ VAR_ROMSWITCH, VAR_ROMSWITCH);
			break;
	}
}



/***************************************************************************
  apple2_c03x_r
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_c03x_r )
{
	if(!machine().side_effects_disabled())
	{
		if (!offset)
		{
			speaker_sound_device *speaker = machine().device<speaker_sound_device>("a2speaker");

			m_a2_speaker_state ^= 1;
			speaker->level_w(m_a2_speaker_state);
		}
	}
	return apple2_getfloatingbusvalue();
}



/***************************************************************************
  apple2_c03x_w
***************************************************************************/

WRITE8_MEMBER ( apple2_state::apple2_c03x_w )
{
	apple2_c03x_r(space, offset, 0);
}



/***************************************************************************
  apple2_c05x_r
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_c05x_r )
{
	if(!machine().side_effects_disabled())
	{
		uint32_t mask;

		if (m_machinetype == TK2000)
		{
			if (offset == 0xa)  // RAM
			{
				apple2_setvar(VAR_TK2000RAM, ~0);
			}
			else if (offset == 0xb) // ROM
			{
				apple2_setvar(0, ~VAR_TK2000RAM);
			}
		}

		/* ANx has reverse SET logic */
		if (offset >= 8)
		{
			offset ^= 1;
		}

		mask = 0x100 << (offset / 2);
		apple2_setvar((offset & 1) ? mask : 0, mask);
	}
	return apple2_getfloatingbusvalue();
}



/***************************************************************************
  apple2_c05x_w
***************************************************************************/

WRITE8_MEMBER ( apple2_state::apple2_c05x_w )
{
	apple2_c05x_r(space, offset, 0);
}



/***************************************************************************
  apple2_c06x_r
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_c06x_r )
{
	int result = 0;
	if(!machine().side_effects_disabled())
	{
		switch (offset & 0x0F)
		{
			case 0x00:
				/* Cassette input */
				{
					if (m_cassette)
					{
						result = m_cassette->input() > 0.0 ? 0x80 : 0;
					}
					else
					{
						result = 0;
					}
				}
				break;
			case 0x01:
				/* Open-Apple/Joystick button 0 */
				result = apple2_pressed_specialkey(0x10);
				break;
			case 0x02:
				/* Closed-Apple/Joystick button 1 */
				result = apple2_pressed_specialkey(0x20);
				break;
			case 0x03:
				/* Joystick button 2. Later revision motherboards connected this to SHIFT also */
				result = apple2_pressed_specialkey(0x40);
				break;
			case 0x04:
				/* X Joystick 1 axis */
				result = machine().time().as_double() < m_joystick_x1_time;
				break;
			case 0x05:
				/* Y Joystick 1 axis */
				result = machine().time().as_double() < m_joystick_y1_time;
				break;
			case 0x06:
				/* X Joystick 2 axis */
				result = machine().time().as_double() < m_joystick_x2_time;
				break;
			case 0x07:
				/* Y Joystick 2 axis */
				result = machine().time().as_double() < m_joystick_y2_time;
				break;
			default:
				/* c060 Empty Cassette head read
				 * and any other non joystick c06 port returns this according to applewin
				 */
				return apple2_getfloatingbusvalue();
		}
	}
	return result ? 0x80 : 0x00;
}



/***************************************************************************
  apple2_c07x_r
***************************************************************************/

READ8_MEMBER ( apple2_state::apple2_c07x_r )
{
	if(!machine().side_effects_disabled())
	{
		double x_calibration = attotime::from_usec(12).as_double();
		double y_calibration = attotime::from_usec(13).as_double();

		if (offset == 0)
		{
			m_joystick_x1_time = machine().time().as_double() + x_calibration * m_joy1x->read();
			m_joystick_y1_time = machine().time().as_double() + y_calibration * m_joy1y->read();
			m_joystick_x2_time = machine().time().as_double() + x_calibration * m_joy2x->read();
			m_joystick_y2_time = machine().time().as_double() + y_calibration * m_joy2y->read();
		}
	}
	return 0;
}



/***************************************************************************
  apple2_c07x_w
***************************************************************************/

WRITE8_MEMBER ( apple2_state::apple2_c07x_w )
{
	// this a machine with an aux slot?
	if (m_auxslotdevice)
	{
		m_auxslotdevice->write_c07x(space, offset&0xf, data);
	}

	// AE RamWorks manual indicates that even if the auxslot card sees the c07x write,
	// so does the motherboard and it will trigger the paddles.  So always call this.
	apple2_c07x_r(space, offset, 0);
}



/* -----------------------------------------------------------------------
 * Floppy disk controller
 * ----------------------------------------------------------------------- */


int apple2_state::apple2_fdc_has_35()
{
	return (floppy_get_count(machine())); // - apple525_get_count(machine)) > 0;
}

int apple2_state::apple2_fdc_has_525()
{
	return 1; //apple525_get_count(machine) > 0;
}

static void apple2_fdc_set_lines(device_t *device, uint8_t lines)
{
	apple2_state *state = device->machine().driver_data<apple2_state>();
	if (state->m_fdc_diskreg & 0x40)
	{
		if (state->apple2_fdc_has_35())
		{
			/* slot 5: 3.5" disks */
			sony_set_lines(device,lines);
		}
	}
	else
	{
		if (state->apple2_fdc_has_525())
		{
			/* slot 6: 5.25" disks */
			apple525_set_lines(device,lines);
		}
	}
}



static void apple2_fdc_set_enable_lines(device_t *device,int enable_mask)
{
	apple2_state *state = device->machine().driver_data<apple2_state>();
	int slot5_enable_mask = 0;
	int slot6_enable_mask = 0;

	if (state->m_fdc_diskreg & 0x40)
		slot5_enable_mask = enable_mask;
	else
		slot6_enable_mask = enable_mask;

	if (state->apple2_fdc_has_35())
	{
		/* set the 3.5" enable lines */
		sony_set_enable_lines(device,slot5_enable_mask);
	}

	if (state->apple2_fdc_has_525())
	{
		/* set the 5.25" enable lines */
		apple525_set_enable_lines(device,slot6_enable_mask);
	}
}



static uint8_t apple2_fdc_read_data(device_t *device)
{
	apple2_state *state = device->machine().driver_data<apple2_state>();
	uint8_t result = 0x00;

	if (state->m_fdc_diskreg & 0x40)
	{
		if (state->apple2_fdc_has_35())
		{
			/* slot 5: 3.5" disks */
			result = sony_read_data(device);
		}
	}
	else
	{
		if (state->apple2_fdc_has_525())
		{
			/* slot 6: 5.25" disks */
			result = apple525_read_data(device);
		}
	}
	return result;
}



static void apple2_fdc_write_data(device_t *device, uint8_t data)
{
	apple2_state *state = device->machine().driver_data<apple2_state>();
	if (state->m_fdc_diskreg & 0x40)
	{
		if (state->apple2_fdc_has_35())
		{
			/* slot 5: 3.5" disks */
			sony_write_data(device,data);
		}
	}
	else
	{
		if (state->apple2_fdc_has_525())
		{
			/* slot 6: 5.25" disks */
			apple525_write_data(device,data);
		}
	}
}



static int apple2_fdc_read_status(device_t *device)
{
	apple2_state *state = device->machine().driver_data<apple2_state>();
	int result = 0;

	if (state->m_fdc_diskreg & 0x40)
	{
		if (state->apple2_fdc_has_35())
		{
			/* slot 5: 3.5" disks */
			result = sony_read_status(device);
		}
	}
	else
	{
		if (state->apple2_fdc_has_525())
		{
			/* slot 6: 5.25" disks */
			result = apple525_read_status(device);
		}
	}
	return result;
}


void apple2_state::apple2_iwm_setdiskreg(uint8_t data)
{
	m_fdc_diskreg = data & 0xC0;
	if (apple2_fdc_has_35())
		sony_set_sel_line( machine().device("fdc"),m_fdc_diskreg & 0x80);
}


const applefdc_interface apple2_fdc_interface =
{
	apple2_fdc_set_lines,           /* set_lines */
	apple2_fdc_set_enable_lines,    /* set_enable_lines */

	apple2_fdc_read_data,           /* read_data */
	apple2_fdc_write_data,          /* write_data */
	apple2_fdc_read_status          /* read_status */
};



/* -----------------------------------------------------------------------
 * Driver init
 * ----------------------------------------------------------------------- */

void apple2_state::apple2_init_common()
{
	m_inh_slot = -1;
	m_flags = 0;
	m_fdc_diskreg = 0;

	// do these lookups once at startup
	m_rom = memregion("maincpu")->base();
	m_rom_length = memregion("maincpu")->bytes() & ~0xFFF;
	m_slot_length = memregion("maincpu")->bytes() - m_rom_length;
	m_slot_ram = (m_slot_length > 0) ? &m_rom[m_rom_length] : nullptr;

	m_auxslotdevice = nullptr;
	if (m_machinetype == APPLE_IIE || m_machinetype == TK3000)
	{
		m_auxslotdevice = m_a2eauxslot->get_a2eauxslot_card();
	}

	/* state save registers */
	save_item(NAME(m_flags));
	machine().save().register_postload(save_prepost_delegate(FUNC(apple2_state::apple2_update_memory_postload), this));

	/* --------------------------------------------- *
	 * set up the softswitch mask/set                *
	 * --------------------------------------------- */
	m_a2_mask = ~0;
	m_a2_set = 0;

	/* disable VAR_ROMSWITCH if the ROM is only 16k */
	if (memregion("maincpu")->bytes() < 0x8000)
		m_a2_mask &= ~VAR_ROMSWITCH;

	if (m_ram->size() <= 64*1024)
		m_a2_mask &= ~(VAR_RAMRD | VAR_RAMWRT | VAR_80STORE | VAR_ALTZP | VAR_80COL);

	apple2_refresh_delegates();
}

void apple2_state::apple2eplus_init_common(void *apple2cp_ce00_ram)
{
	apple2_memmap_config mem_cfg;

	m_flags_mask = 0;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)apple2cp_ce00_ram;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,apple2c)
{
	m_machinetype = APPLE_IIC;

	apple2eplus_init_common((void *)nullptr);
}

MACHINE_START_MEMBER(apple2_state,tk3000)
{
	m_machinetype = TK3000; // enhanced IIe clone with Z80 keyboard scanner subcpu

	apple2eplus_init_common((void *)nullptr);
}

MACHINE_START_MEMBER(apple2_state,apple2cp)
{
	void *apple2cp_ce00_ram;

	/* there appears to be some hidden RAM that is swapped in on the Apple
	 * IIc plus; I have not found any official documentation but the BIOS
	 * clearly uses this area as writeable memory */
	apple2cp_ce00_ram = auto_alloc_array(machine(), uint8_t, 0x200);
	memset(apple2cp_ce00_ram, 0, sizeof(uint8_t) * 0x200);

	m_machinetype = APPLE_IICPLUS;

	apple2eplus_init_common(apple2cp_ce00_ram);
}

MACHINE_START_MEMBER(apple2_state,apple2e)
{
	apple2_memmap_config mem_cfg;

	m_flags_mask = 0;

	m_machinetype = APPLE_IIE;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)nullptr;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,laser128)
{
	apple2_memmap_config mem_cfg;

	m_flags_mask = 0;
	m_machinetype = LASER128;

	apple2_init_common();

	// 1 MB of expansion RAM in slot 5
	m_exp_ram = std::make_unique<uint8_t[]>(1024*1024);
	memset(m_exp_ram.get(), 0xff, 1024*1024);

	m_exp_bankhior = 0xf0;
	m_exp_addrmask = 0xfffff;

	// save memory expansion vars
	save_item(NAME(m_exp_regs));
	save_item(NAME(m_exp_wptr));
	save_item(NAME(m_exp_liveptr));
	save_item(NAME(m_exp_bankhior));
	save_item(NAME(m_exp_addrmask));

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)nullptr;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,apple2orig)
{
	apple2_memmap_config mem_cfg;
	void *apple2cp_ce00_ram = nullptr;

	// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
	m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;

	m_machinetype = APPLE_II;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)apple2cp_ce00_ram;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,space84)
{
	apple2_memmap_config mem_cfg;
	void *apple2cp_ce00_ram = nullptr;

	// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
	m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;

	m_machinetype = SPACE84;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)apple2cp_ce00_ram;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,laba2p)
{
	apple2_memmap_config mem_cfg;
	void *apple2cp_ce00_ram = nullptr;

	// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
	m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;

	m_machinetype = LABA2P;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = apple2_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)apple2cp_ce00_ram;
	apple2_setup_memory(&mem_cfg);
}

MACHINE_START_MEMBER(apple2_state,tk2000)
{
	apple2_memmap_config mem_cfg;

	// II and II+ have no internal ROM or internal slot 3 h/w, so don't allow these states
	m_flags_mask = VAR_INTCXROM|VAR_SLOTC3ROM;

	m_machinetype = TK2000;

	apple2_init_common();

	/* setup memory */
	memset(&mem_cfg, 0, sizeof(mem_cfg));
	mem_cfg.first_bank = 1;
	mem_cfg.memmap = tk2000_memmap_entries;
	mem_cfg.auxmem = (uint8_t*)nullptr;
	apple2_setup_memory(&mem_cfg);
}

int apple2_state::apple2_pressed_specialkey(uint8_t key)
{
	return (m_kbspecial.read_safe(0) & key)
		|| (m_joybuttons.read_safe(0) & key);
}

void apple2_state::apple2_refresh_delegates()
{
	read_delegates_master[0] = read8_delegate(FUNC(apple2_state::read_floatingbus), this);
	read_delegates_master[1] = read8_delegate(FUNC(apple2_state::apple2_c1xx_r), this);
	read_delegates_master[2] = read8_delegate(FUNC(apple2_state::apple2_c3xx_r), this);
	read_delegates_master[3] = read8_delegate(FUNC(apple2_state::apple2_c4xx_r), this);
	write_delegates_master[0] = write8_delegate(FUNC(apple2_state::apple2_c1xx_w), this);
	write_delegates_master[1] = write8_delegate(FUNC(apple2_state::apple2_c3xx_w), this);
	write_delegates_master[2] = write8_delegate(FUNC(apple2_state::apple2_c4xx_w), this);

	rd_c000 = read8_delegate(FUNC(apple2_state::apple2_c0xx_r), this);
	wd_c000 = write8_delegate(FUNC(apple2_state::apple2_c0xx_w), this);

	rd_c080 = read8_delegate(FUNC(apple2_state::apple2_c080_r), this);
	wd_c080 = write8_delegate(FUNC(apple2_state::apple2_c080_w), this);

	rd_cfff = read8_delegate(FUNC(apple2_state::apple2_cfff_r), this);
	wd_cfff = write8_delegate(FUNC(apple2_state::apple2_cfff_w), this);

	rd_c800 = read8_delegate(FUNC(apple2_state::apple2_c800_r), this);
	wd_c800 = write8_delegate(FUNC(apple2_state::apple2_c800_w), this);

	rd_ce00 = read8_delegate(FUNC(apple2_state::apple2_ce00_r), this);
	wd_ce00 = write8_delegate(FUNC(apple2_state::apple2_ce00_w), this);

	rd_inh_d000 = read8_delegate(FUNC(apple2_state::apple2_inh_d000_r), this);
	wd_inh_d000 = write8_delegate(FUNC(apple2_state::apple2_inh_d000_w), this);

	rd_inh_e000 = read8_delegate(FUNC(apple2_state::apple2_inh_e000_r), this);
	wd_inh_e000 = write8_delegate(FUNC(apple2_state::apple2_inh_e000_w), this);

	read_delegates_0000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0000_r), this);
	read_delegates_0000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0000_r), this);
	read_delegates_0200[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0200_r), this);
	read_delegates_0200[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0200_r), this);
	read_delegates_0400[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0400_r), this);
	read_delegates_0400[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0400_r), this);
	read_delegates_0800[0] = read8_delegate(FUNC(apple2_state::apple2_auxram0800_r), this);
	read_delegates_0800[1] = read8_delegate(FUNC(apple2_state::apple2_mainram0800_r), this);
	read_delegates_2000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram2000_r), this);
	read_delegates_2000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram2000_r), this);
	read_delegates_4000[0] = read8_delegate(FUNC(apple2_state::apple2_auxram4000_r), this);
	read_delegates_4000[1] = read8_delegate(FUNC(apple2_state::apple2_mainram4000_r), this);
	read_delegates_c000[0] = read8_delegate(FUNC(apple2_state::apple2_auxramc000_r), this);
	read_delegates_c000[1] = read8_delegate(FUNC(apple2_state::apple2_mainramc000_r), this);
	read_delegates_d000[0] = read8_delegate(FUNC(apple2_state::apple2_auxramd000_r), this);
	read_delegates_d000[1] = read8_delegate(FUNC(apple2_state::apple2_mainramd000_r), this);
	read_delegates_e000[0] = read8_delegate(FUNC(apple2_state::apple2_auxrame000_r), this);
	read_delegates_e000[1] = read8_delegate(FUNC(apple2_state::apple2_mainrame000_r), this);

	write_delegates_0000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0000_w), this);
	write_delegates_0000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0000_w), this);
	write_delegates_0200[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0200_w), this);
	write_delegates_0200[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0200_w), this);
	write_delegates_0400[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0400_w), this);
	write_delegates_0400[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0400_w), this);
	write_delegates_0800[0] = write8_delegate(FUNC(apple2_state::apple2_auxram0800_w), this);
	write_delegates_0800[1] = write8_delegate(FUNC(apple2_state::apple2_mainram0800_w), this);
	write_delegates_2000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram2000_w), this);
	write_delegates_2000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram2000_w), this);
	write_delegates_4000[0] = write8_delegate(FUNC(apple2_state::apple2_auxram4000_w), this);
	write_delegates_4000[1] = write8_delegate(FUNC(apple2_state::apple2_mainram4000_w), this);
	write_delegates_c000[0] = write8_delegate(FUNC(apple2_state::apple2_auxramc000_w), this);
	write_delegates_c000[1] = write8_delegate(FUNC(apple2_state::apple2_mainramc000_w), this);
	write_delegates_d000[0] = write8_delegate(FUNC(apple2_state::apple2_auxramd000_w), this);
	write_delegates_d000[1] = write8_delegate(FUNC(apple2_state::apple2_mainramd000_w), this);
	write_delegates_e000[0] = write8_delegate(FUNC(apple2_state::apple2_auxrame000_w), this);
	write_delegates_e000[1] = write8_delegate(FUNC(apple2_state::apple2_mainrame000_w), this);
}

READ_LINE_MEMBER(apple2_state::ay3600_shift_r)
{
	// either shift key
	if (m_kbspecial->read() & 0x06)
	{
		return ASSERT_LINE;
	}

	return CLEAR_LINE;
}

READ_LINE_MEMBER(apple2_state::ay3600_control_r)
{
	if (m_kbspecial->read() & 0x08)
	{
		return ASSERT_LINE;
	}

	return CLEAR_LINE;
}

static const uint8_t a2_key_remap[0x32][4] =
{
/*    norm shft ctrl both */
	{ 0x33,0x23,0x33,0x23 },    /* 3 #     00     */
	{ 0x34,0x24,0x34,0x24 },    /* 4 $     01     */
	{ 0x35,0x25,0x35,0x25 },    /* 5 %     02     */
	{ 0x36,0x5e,0x35,0x53 },    /* 6 ^     03     */
	{ 0x37,0x26,0x37,0x26 },    /* 7 &     04     */
	{ 0x38,0x2a,0x38,0x2a },    /* 8 *     05     */
	{ 0x39,0x28,0x39,0x28 },    /* 9 (     06     */
	{ 0x30,0x29,0x30,0x29 },    /* 0 )     07     */
	{ 0x3b,0x3a,0x3b,0x3a },    /* ; :     08     */
	{ 0x2d,0x5f,0x2d,0x1f },    /* - _     09     */
	{ 0x51,0x51,0x11,0x11 },    /* q Q     0a     */
	{ 0x57,0x57,0x17,0x17 },    /* w W     0b     */
	{ 0x45,0x45,0x05,0x05 },    /* e E     0c     */
	{ 0x52,0x52,0x12,0x12 },    /* r R     0d     */
	{ 0x54,0x54,0x14,0x14 },    /* t T     0e     */
	{ 0x59,0x59,0x19,0x19 },    /* y Y     0f     */
	{ 0x55,0x55,0x15,0x15 },    /* u U     10     */
	{ 0x49,0x49,0x09,0x09 },    /* i I     11     */
	{ 0x4f,0x4f,0x0f,0x0f },    /* o O     12     */
	{ 0x50,0x50,0x10,0x10 },    /* p P     13     */
	{ 0x44,0x44,0x04,0x04 },    /* d D     14     */
	{ 0x46,0x46,0x06,0x06 },    /* f F     15     */
	{ 0x47,0x47,0x07,0x07 },    /* g G     16     */
	{ 0x48,0x48,0x08,0x08 },    /* h H     17     */
	{ 0x4a,0x4a,0x0a,0x0a },    /* j J     18     */
	{ 0x4b,0x4b,0x0b,0x0b },    /* k K     19     */
	{ 0x4c,0x4c,0x0c,0x0c },    /* l L     1a     */
	{ 0x3d,0x2b,0x3d,0x2b },    /* = +     1b     */
	{ 0x08,0x08,0x08,0x08 },    /* Left    1c     */
	{ 0x15,0x15,0x15,0x15 },    /* Right   1d     */
	{ 0x5a,0x5a,0x1a,0x1a },    /* z Z     1e     */
	{ 0x58,0x58,0x18,0x18 },    /* x X     1f     */
	{ 0x43,0x43,0x03,0x03 },    /* c C     20     */
	{ 0x56,0x56,0x16,0x16 },    /* v V     21     */
	{ 0x42,0x42,0x02,0x02 },    /* b B     22     */
	{ 0x4e,0x4e,0x0e,0x0e },    /* n N     23     */
	{ 0x4d,0x4d,0x0d,0x0d },    /* m M     24     */
	{ 0x2c,0x3c,0x2c,0x3c },    /* , <     25     */
	{ 0x2e,0x3e,0x2e,0x3e },    /* . >     26     */
	{ 0x2f,0x3f,0x2f,0x3f },    /* / ?     27     */
	{ 0x53,0x53,0x13,0x13 },    /* s S     28     */
	{ 0x32,0x40,0x32,0x00 },    /* 2 @     29     */
	{ 0x31,0x21,0x31,0x31 },    /* 1 !     2a     */
	{ 0x9b,0x9b,0x9b,0x9b },    /* Escape  2b     */
	{ 0x41,0x41,0x01,0x01 },    /* a A     2c     */
	{ 0x20,0x20,0x20,0x20 },    /* Space   2d     */
	{ 0x00,0x00,0x00,0x00 },    /* 0x2e unused    */
	{ 0x00,0x00,0x00,0x00 },    /* 0x2f unused    */
	{ 0x00,0x00,0x00,0x00 },    /* 0x30 unused    */
	{ 0x0d,0x0d,0x0d,0x0d },    /* Enter   31     */
};

WRITE_LINE_MEMBER(apple2_state::ay3600_data_ready_w)
{
	if (state == ASSERT_LINE)
	{
		int mod = 0;
		m_lastchar = m_ay3600->b_r();

		mod = (m_kbspecial->read() & 0x06) ? 0x01 : 0x00;
		mod |= (m_kbspecial->read() & 0x08) ? 0x02 : 0x00;

		m_transchar = a2_key_remap[m_lastchar&0x3f][mod];

		if (m_transchar != 0)
		{
			m_strobe = 0x80;
//          printf("new char = %04x (%02x)\n", m_lastchar&0x3f, m_transchar);
		}
	}
}

WRITE_LINE_MEMBER(apple2_state::ay3600_iie_data_ready_w)
{
	if (state == ASSERT_LINE)
	{
		uint8_t *decode = m_kbdrom->base();
		uint16_t trans;

		m_lastchar = m_ay3600->b_r();

		trans = m_lastchar & ~(0x1c0);  // clear the 3600's control/shift stuff
		trans |= (m_lastchar & 0x100)>>2;   // bring the 0x100 bit down to the 0x40 place
		trans <<= 2;                    // 4 entries per key
		trans |= (m_kbspecial->read() & 0x06) ? 0x00 : 0x01;    // shift is bit 1 (active low)
		trans |= (m_kbspecial->read() & 0x08) ? 0x00 : 0x02;    // control is bit 2 (active low)
		trans |= (m_kbspecial->read() & 0x01) ? 0x0000 : 0x0200;    // caps lock is bit 9 (active low)

		m_transchar = decode[trans];
		m_strobe = 0x80;

//      printf("new char = %04x (%02x)\n", m_lastchar, m_transchar);
	}
}