summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/6883sam.h
blob: 0817ab375031ac40dc61e28f0984593648d9098a (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                 







                                                                            

                              
 
            
 
 
                                                            
                                                
                                                                              
 
                                          
                                                                                        
 





                                                                            
                                                               

       
                                                                                                      


                              















                                                    

                      
                                      

                       
                                              
 


                                                          
                                                       



                                                                                                                                                          
                                                                 

                                        
                                                   

                                             
                                   





                                                        
                                                          






                                        
                                                                              

       
                                                                                                        
 
                                                                                                                                          
 
                                                      
         

                                        

         
                                    
                                                                                                





















                                                                                         
                                                              








                                                                            
                                 


                                                 

        

                                                                         

                       

                                                    



                                                       



                                                                          
                                                         



                                                 
                                                                                        

                


                                                 
                                               

                                                 
                                                                                                                                                                               

          
                                      
                               
 
                      
                                                
                                               









                                                 
                                                     

                    


                                                     

                               
                                                      

                                  

                                       



                                                                   
                                   

                                                                                               







                                                          
                                
                                                                    














                                                                   
                                   

                                                                                               







                                                              
                                
                                                                    










                                                   
                                                                                                                                                   


                                   

  
                                            
 
                                
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/***************************************************************************

    6883sam.h

    Motorola 6883 Synchronous Address Multiplexer

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

#ifndef MAME_MACHINE_6883SAM_H
#define MAME_MACHINE_6883SAM_H

#pragma once


#define MCFG_SAM6883_ADD(_tag, _clock, _cputag, _cpuspace) \
	MCFG_DEVICE_ADD(_tag, SAM6883, _clock) \
	downcast<sam6883_device &>(*device).configure_cpu(_cputag, _cpuspace);

#define MCFG_SAM6883_RES_CALLBACK(_read) \
	devcb = &downcast<sam6883_device &>(*device).set_res_rd_callback(DEVCB_##_read);


//**************************************************************************
//  SAM6883 CORE
//**************************************************************************

// base class so that GIME emulation can use some functionality
class sam6883_friend_device_interface : public device_interface
{
public:
	sam6883_friend_device_interface(const machine_config &mconfig, device_t &device, int divider);

protected:
	// SAM state constants
	static const uint16_t SAM_STATE_TY = 0x8000;
	static const uint16_t SAM_STATE_M1 = 0x4000;
	static const uint16_t SAM_STATE_M0 = 0x2000;
	static const uint16_t SAM_STATE_R1 = 0x1000;
	static const uint16_t SAM_STATE_R0 = 0x0800;
	static const uint16_t SAM_STATE_P1 = 0x0400;
	static const uint16_t SAM_STATE_F6 = 0x0200;
	static const uint16_t SAM_STATE_F5 = 0x0100;
	static const uint16_t SAM_STATE_F4 = 0x0080;
	static const uint16_t SAM_STATE_F3 = 0x0040;
	static const uint16_t SAM_STATE_F2 = 0x0020;
	static const uint16_t SAM_STATE_F1 = 0x0010;
	static const uint16_t SAM_STATE_F0 = 0x0008;
	static const uint16_t SAM_STATE_V2 = 0x0004;
	static const uint16_t SAM_STATE_V1 = 0x0002;
	static const uint16_t SAM_STATE_V0 = 0x0001;

	// incidentals
	cpu_device *            m_cpu;

	// device state
	uint16_t                  m_sam_state;

	// base clock divider (/4 for MC6883, /8 for GIME)
	int m_divider;

	ATTR_FORCE_INLINE uint16_t display_offset(void)
	{
		return ((m_sam_state & (SAM_STATE_F0|SAM_STATE_F1|SAM_STATE_F2|SAM_STATE_F3|SAM_STATE_F4|SAM_STATE_F5|SAM_STATE_F6)) / SAM_STATE_F0) << 9;
	}

	ATTR_FORCE_INLINE uint16_t alter_sam_state(offs_t offset)
	{
		/* determine the mask */
		uint16_t mask = 1 << (offset >> 1);

		/* determine the new state */
		uint16_t new_state;
		if (offset & 0x0001)
			new_state = m_sam_state | mask;
		else
			new_state = m_sam_state & ~mask;

		/* specify the new state */
		uint16_t xorval = m_sam_state ^ new_state;
		m_sam_state = new_state;
		return xorval;
	}

	void update_cpu_clock(void);
};

class sam6883_device : public device_t, public sam6883_friend_device_interface
{
public:
	sam6883_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	template <class Object> devcb_base &set_res_rd_callback(Object &&cb) { return m_read_res.set_callback(std::forward<Object>(cb)); }

	void configure_cpu(const char *tag, int space)
	{
		m_cpu_tag = tag;
		m_cpu_space_ref = space;
	}

	// called to configure banks
	void configure_bank(int bank, uint8_t *memory, uint32_t memory_size, bool is_read_only);
	void configure_bank(int bank, read8_delegate rhandler, write8_delegate whandler);

	// typically called by VDG
	ATTR_FORCE_INLINE DECLARE_READ8_MEMBER( display_read )
	{
		if (offset == (offs_t) ~0)
		{
			/* the VDG is telling the counter to reset */
			m_counter = display_offset();
			m_counter_xdiv = 0;
			m_counter_ydiv = 0;
		}
		else if ((offset & 1) != (m_counter & 0x0001))
		{
			/* DA0 has been toggled - first bump B0-B3 of the counter */
			bool bit3_carry = (m_counter & 0x000F) == 0x000F;
			m_counter = (m_counter & ~0x000F) | ((m_counter + 1) & 0x000F);

			/* and apply the carry (if applicable */
			if (bit3_carry)
				counter_carry_bit3();
		}
		return m_read_res(m_counter & m_counter_mask);
	}

	DECLARE_WRITE_LINE_MEMBER( hs_w );

	// typically called by machine
	address_space *mpu_address_space(void) const { return m_cpu_space; }
	void set_bank_offset(int bank, offs_t offset);

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_post_load() override;

private:
	// represents an external memory bank - memory or IO that the SAM
	// points to with the S2/S1/S0 output
	struct sam_bank
	{
		uint8_t *             m_memory;
		uint32_t              m_memory_size;
		offs_t              m_memory_offset;
		bool                m_memory_read_only;
		read8_delegate      m_rhandler;
		write8_delegate     m_whandler;
	};

	// represents one of the memory "spaces" (e.g. - $8000-$9FFF) that
	// can ultimately point to a bank
	template <uint16_t _addrstart, uint16_t _addrend>
	class sam_space
	{
	public:
		sam_space(sam6883_device &owner);
		void point(const sam_bank &bank, uint16_t offset, uint32_t length = ~0);

	private:
		sam6883_device &    m_owner;
		memory_bank *       m_read_bank;
		memory_bank *       m_write_bank;
		uint32_t              m_length;

		address_space &cpu_space() const;
		void point_specific_bank(const sam_bank &bank, uint32_t offset, uint32_t mask, memory_bank *&memory_bank, uint32_t addrstart, uint32_t addrend, bool is_write);
	};

	const char *        m_cpu_tag;
	int    m_cpu_space_ref;

	// incidentals
	address_space *             m_cpu_space;
	devcb_read8                 m_read_res;
	sam_bank                    m_banks[8];
	sam_space<0x0000, 0x7FFF>   m_space_0000;
	sam_space<0x8000, 0x9FFF>   m_space_8000;
	sam_space<0xA000, 0xBFFF>   m_space_A000;
	sam_space<0xC000, 0xFEFF>   m_space_C000;
	sam_space<0xFF00, 0xFF1F>   m_space_FF00;
	sam_space<0xFF20, 0xFF3F>   m_space_FF20;
	sam_space<0xFF40, 0xFF5F>   m_space_FF40;
	sam_space<0xFF60, 0xFFBF>   m_space_FF60;
	sam_space<0xFFE0, 0xFFFF>   m_space_FFE0;
	uint16_t                      m_counter_mask;

	// SAM state
	uint16_t                      m_counter;
	uint8_t                       m_counter_xdiv;
	uint8_t                       m_counter_ydiv;

	// dummy scratch memory
	uint8_t                       m_dummy[0x8000];

	// typically called by CPU
	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	// called when there is a carry out of bit 3 on the counter
	ATTR_FORCE_INLINE void counter_carry_bit3(void)
	{
		uint8_t x_division;
		switch((m_sam_state & (SAM_STATE_V2|SAM_STATE_V1|SAM_STATE_V0)) / SAM_STATE_V0)
		{
			case 0x00:  x_division = 1; break;
			case 0x01:  x_division = 3; break;
			case 0x02:  x_division = 1; break;
			case 0x03:  x_division = 2; break;
			case 0x04:  x_division = 1; break;
			case 0x05:  x_division = 1; break;
			case 0x06:  x_division = 1; break;
			case 0x07:  x_division = 1; break;
			default:
				fatalerror("Should not get here\n");
				return;
		}

		if (++m_counter_xdiv >= x_division)
		{
			m_counter_xdiv = 0;
			m_counter ^= 0x0010;
			if ((m_counter & 0x0010) == 0x0000)
				counter_carry_bit4();
		}
	}

	// called when there is a carry out of bit 4 on the counter
	ATTR_FORCE_INLINE void counter_carry_bit4(void)
	{
		uint8_t y_division;
		switch((m_sam_state & (SAM_STATE_V2|SAM_STATE_V1|SAM_STATE_V0)) / SAM_STATE_V0)
		{
			case 0x00:  y_division = 12;    break;
			case 0x01:  y_division = 1;     break;
			case 0x02:  y_division = 3;     break;
			case 0x03:  y_division = 1;     break;
			case 0x04:  y_division = 2;     break;
			case 0x05:  y_division = 1;     break;
			case 0x06:  y_division = 1;     break;
			case 0x07:  y_division = 1;     break;
			default:
				fatalerror("Should not get here\n");
				return;
		}

		if (++m_counter_ydiv >= y_division)
		{
			m_counter_ydiv = 0;
			m_counter += 0x0020;
		}
	}

	// other members
	void configure_bank(int bank, uint8_t *memory, uint32_t memory_size, bool is_read_only, read8_delegate rhandler, write8_delegate whandler);
	void horizontal_sync(void);
	void update_state(void);
	void update_memory(void);
};

DECLARE_DEVICE_TYPE(SAM6883, sam6883_device)

#endif // MAME_MACHINE_6883SAM_H