summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/m2comm.cpp
blob: 6b43ecdf4287c8a37ea9f9995eaa7c9bc0985b01 (plain) (tree)

























                                                                               








                                                                       
 

                              
 

                              























                                                                                             








                                                                       
 


                                          
 

                                          
                         
                         























                                                                                             








                                                                          
 


                              
 


                              
























                                                                                             














                                                                        

  

                    

                           

                     
 




                                                                            
                                                                                  

                                                   
                                                 

                                                   
                                                       
                  








                                                                            
                                                                                                               
                                                    













                                                                  

                                                                       















                                                   






                                  
                                                     
                                                                                 




                                   
                                          




                                    
                                          
                                                                                        




                                     
                                                         




                                 
                           





                                  
                         





                                
                                                               
                                    


                          



                               
                                                              



                                    







                                                    
                                      









                                                                                                  
 






                                 


                        
                                           








                                    
                         




                    
                        

                               
                                 
         
                                        
                                                                     
                                                                                    
 
                                             


                             


                                                                                   

                                                                     
 
                                        
                 






                                                      


                                           
 
                                          
                                       
                         
                                                                                          

                                                                                                   
                         
 
                                          
                                       
                         
                                                                                            

                                                                                     
                         
 
                                                               
                                                   
                         




                                                            
                                 

                                                              
 



                                                             
                                                 



                                                                                                     
                                                 
                                                    
                                                 
                                                                                               

                                                                    
                                                                               
                                                         
 

                                                                                         

                                                 


                                                             
                                         

















                                                                                                           
                                                 








                                                                                                                                          
                                         
 
                                                                
                                                                            


                                                         
 



                                                                                   
                                                                
                                         



                                                                     


                                                             
                                                                     
                                         



                                                                           

                                                                   
                                                                                                                                          







                                                                          
                                                                    


                                                                       


                                         
                 
 
                                      

                                        
                          
                         


                                                            

                                                            



                                                                                
                                                                                        
                                                 
                                                                                                     
                                                 
















































































                                                                                                             
                                         




                                                                                                     


                                    







                                                                                         
                                         
                                 


                                                              
                         



                                            
 
















                                                                               
                         










                                                                                      
                                 
                                                 
                                 

                         
         








































                                                                                             

      
// license:BSD-3-Clause
// copyright-holders:Ariane Fugmann

/*
Sega MODEL2 COMMUNICATION BOARD 837-10537
( http://images.arianchen.de/sega-comm/daytona_comm.jpg )
|-----------------------------------------------------------------------------|
| |-------------------|                             |-------------------|     |
| |-------------------|                             |-------------------|     |
|          CN5                                               CN4           -- |
| LED    Z80        LH5268A          16726.7        JP6 JP5 JP4 JP1        || |
|                                                                         C|| |
|        315-5751   315-5752                        uPD72103              N|| |
|                                                                     JP7 8|| |
|        LH5268A    LH5268A                                           JP8  || |
|                                                                     JP9  -- |
|        LH5268A    LH5268A                         315-5753A    315-5547     |
|                                                                             |
|                                                                         CN6 |
| CN9                                                                         |
|                                                                         CN7 |
|          CN3                      CN2                      CN1              |
| |-------------------|    |-------------------|    |-------------------|     |
| |-------------------|    |-------------------|    |-------------------|     |
|-----------------------------------------------------------------------------|

    Setup:
        Z80        Zilog Z0840008PSC Z80 CPU (DIP40)
        LH5268A    SHARP LH5268AD-10LL 8k x8 SRAM (DIP28)
        uPD72103   NEC uPD72103 HDLC/Frame Relay Controller (QFP80)
        16726.7    M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-16726')
        315-5751   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5752   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5753A  AMI 18CV8PC-15 PAL (DIP20)
        315-5547   AMI 18CV8PC-25 PAL (DIP20)

    Board:
        837-10537  Daytona USA

    EEPROM:
        16726.7    Daytona USA


Sega PC BD MODEL2 A-CRX COMMUNICATION 837-11525
( http://images.arianchen.de/sega-comm/srally_comm.jpg )
|-------------------------------------------------------------------------------------------|
| |-------------------|                             |-------------------|    |---------|    |
| |-------------------|                             |-------------------|    |---------|    |
|          CN5                                               CN4                CN10        |
| LED    Z80        LH5268A          16726.7        JP6 JP5 JP4 JP1                         |
|                                                                                           |
|        315-5751   315-5752                        uPD72103                                |
|                                                                                           |
|        LH5268A    LH5268A                                                                 |
|                                                                                        -- |
|        LH5268A    LH5268A                         315-5753A    315-5547                || |
|                                                                                       C|| |
|                                                                                       N|| |
| CN9                                                                                   8|| |
|                                                                                   JP7  || |
|          CN3                      CN2                      CN1                    JP8  -- |
| |-------------------|    |-------------------|    |-------------------|           JP9     |
| |-------------------|    |-------------------|    |-------------------|                   |
|-------------------------------------------------------------------------------------------|

    Setup:
        Z80        Zilog Z0840008PSC Z80 CPU (DIP40)
        LH5268A    SHARP LH5268AD-10LL 8k x8 SRAM (DIP28)
        uPD72103   NEC uPD72103 HDLC/Frame Relay Controller (QFP80)
        16726.7    M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-16726')
        315-5751   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5752   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5753A  AMI 18CV8PC-15 PAL (DIP20)
        315-5547   AMI 18CV8PC-25 PAL (DIP20)

    Board:
        837-11525
        837-11572  Sega Rally Championship

    EEPROM:
        16726.7    Sega Rally Championship
        18643.7    ManxTT
        18643A.7   ManxTT


Sega PC BD MODEL2 B-CRX COMMUNICATION 837-11615
( http://images.arianchen.de/sega-comm/model2b-com_top.jpg )
|-------------------------------------------------------------------------------------------|
|                                                                                           |
|  --                                                                                       |
|  ||          18643A.7    MB84256A        Z80                                              |
| C||                                                      MB84256A                         |
| N||  JP9                       uPD72103A 315-5751                                         |
| 8||  JP8                                                 MB84256A                         |
|  ||  JP7                                 315-5752                                         |
|  --                                                      MB84256A                         |
|                                                                                           |
|                                                          MB84256A                         |
|                                          315-5753A                                        |
| LED                                                                                       |
|                                                    315-5547A                              |
|                                                                                           |
|                                                                              CN1          |
|                                                                    |-------------------|  |
|                                                  CN3               |-------------------|  |
|-------------------------------------------------------------------------------------------|

    Setup:
        Z80          Zilog Z0840008PSC Z80 CPU (DIP40)
        MB84256A     Fujitsu MB84256A-70LL 32k x8 SRAM (SDIP28)
        uPD72103A    NEC uPD72103 HDLC/Frame Relay Controller (QFP80)
        18643A.7     M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-18643A')
        315-5751     Lattice GAL16V8B-25LP PAL (DIP20)
        315-5752     Lattice GAL16V8B-25LP PAL (DIP20)
        315-5753A    ICT PEEL18CV8P-15 PAL (DIP20)
        315-5547A    AMI 18CV8PC-25 PAL (DIP20)

    Board:
        837-11615    Virtua On
        837-11615-02 Virtua On

    EEPROM:
        18643.7      Virtua On
        18643A.7     Virtua On




Sega PC BD MODEL2 C-CRX COMMUNICATION 837-12839
|-------------------------------------------------------------------------------------------|
|                                                                                           |
|  --                                                                                       |
|  ||          18643A.7    MB84256A        Z80                                              |
| C||                                                      MB84256A                         |
| N||  JP9                       uPD72103A 315-5751                                         |
| 8||  JP8                                                 MB84256A                         |
|  ||  JP7                                 315-5752                                         |
|  --                                                      MB84256A                         |
|                                                                                           |
|                                                          MB84256A                         |
|                                          315-5753A                                        |
| LED                                                                                       |
|                                                    315-5547A                              |
|                                                                                           |
|                                                                              CN1          |
|                                                                    |-------------------|  |
|                                                  CN3               |-------------------|  |
|-------------------------------------------------------------------------------------------|

    Setup:
        Z80        Zilog Z0840008PSC Z80 CPU (DIP40)
        MB84256A   Fujitsu MB84256A-70LL 32k x8 SRAM (SDIP28)
        uPD72103A  NEC uPD72103 HDLC/Frame Relay Controller (QFP80)
        18643A.7   M27C1001 128k x8 EPROM (DIP32, labelled 'EPR-18643A')
        315-5751   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5752   Lattice GAL16V8B-25LP PAL (DIP20)
        315-5753A  ICT PEEL18CV8P-15 PAL (DIP20)
        315-5547A  AMI 18CV8PC-25 PAL (DIP20)

    Board:
        837-12839  Sega Touring Car Championship

    EEPROM:
        18643A.7   Sega Touring Car Championship
*/

#include "emu.h"
#include "emuopts.h"
#include "machine/m2comm.h"

#define VERBOSE 0
#include "logmacro.h"


//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

DEFINE_DEVICE_TYPE(M2COMM, m2comm_device, "m2comm", "Model 2 Communication Board")

//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------

MACHINE_CONFIG_START(m2comm_device::device_add_mconfig)
MACHINE_CONFIG_END

//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  m2comm_device - constructor
//-------------------------------------------------

m2comm_device::m2comm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, M2COMM, tag, owner, clock)
{
	// prepare localhost "filename"
	m_localhost[0] = 0;
	strcat(m_localhost, "socket.");
	strcat(m_localhost, mconfig.options().comm_localhost());
	strcat(m_localhost, ":");
	strcat(m_localhost, mconfig.options().comm_localport());

	// prepare remotehost "filename"
	m_remotehost[0] = 0;
	strcat(m_remotehost, "socket.");
	strcat(m_remotehost, mconfig.options().comm_remotehost());
	strcat(m_remotehost, ":");
	strcat(m_remotehost, mconfig.options().comm_remoteport());

	m_framesync = mconfig.options().comm_framesync() ? 0x01 : 0x00;
}

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

void m2comm_device::device_start()
{
}

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

void m2comm_device::device_reset()
{
	m_zfg = 0;
	m_cn = 0;
	m_fg = 0;
}

READ8_MEMBER(m2comm_device::zfg_r)
{
	uint8_t result = m_zfg | (~m_fg << 7) | 0x7e;
	LOG("m2comm-zfg_r: read register %02x for value %02x\n", offset, result);
	return result;
}

WRITE8_MEMBER(m2comm_device::zfg_w)
{
	LOG("m2comm-zfg_w: %02x\n", data);
	m_zfg = data & 0x01;
}

READ8_MEMBER(m2comm_device::share_r)
{
	uint8_t result = m_shared[offset];
	LOG("m2comm-share_r: read shared memory %02x for value %02x\n", offset, result);
	return result;
}

WRITE8_MEMBER(m2comm_device::share_w)
{
	LOG("m2comm-share_w: %02x %02x\n", offset, data);
	m_shared[offset] = data;
}

READ8_MEMBER(m2comm_device::cn_r)
{
	return m_cn | 0xfe;
}

WRITE8_MEMBER(m2comm_device::cn_w)
{
	m_cn = data & 0x01;

#ifndef M2COMM_SIMULATION
	if (!m_cn)
		device_reset();
#else
	if (!m_cn)
	{
		// reset command
		osd_printf_verbose("M2COMM: board disabled\n");
		m_linkenable = 0x00;
		m_zfg = 0;
		m_cn = 0;
		m_fg = 0;
	}
	else
	{
		// init command
		osd_printf_verbose("M2COMM: board enabled\n");
		m_linkenable = 0x01;
		m_linkid = 0x00;
		m_linkalive = 0x00;
		m_linkcount = 0x00;
		m_linktimer = 0x00e8; // 58 fps * 4s

		// zero memory
		for (int i = 0; i < 0x4000; i++)
		{
			m_shared[i] = 0x00;
		}

		m_shared[0x01] = 0x02;
		// TODO - check EPR-16726 on Daytona USA and Sega Rally Championship
		// EPR-18643(A) - these are accessed by VirtuaON and Sega Touring Car Championship

		// frameSize - 0x0e00
		m_shared[0x12] = 0x00;
		m_shared[0x13] = 0x0e;

		// frameOffset - 0x01c0
		m_shared[0x14] = 0xc0;
		m_shared[0x15] = 0x01;

		comm_tick();
	}
#endif
}

READ8_MEMBER(m2comm_device::fg_r)
{
#ifdef M2COMM_SIMULATION
	read_fg();
#endif
	return m_fg | (~m_zfg << 7) | 0x7e;
}

WRITE8_MEMBER(m2comm_device::fg_w)
{
	m_fg = data & 0x01;
}

void m2comm_device::check_vint_irq()
{
#ifndef M2COMM_SIMULATION
#else
	comm_tick();
#endif
}

#ifdef M2COMM_SIMULATION
void m2comm_device::comm_tick()
{
	if (m_linkenable == 0x01)
	{
		int frameStart = 0x2000;
		int frameSize = m_shared[0x13] << 8 | m_shared[0x12];
		int frameOffset = frameStart | m_shared[0x15] << 8 | m_shared[0x14];

		int dataSize = frameSize + 1;
		int recv = 0;
		int idx = 0;

		// EPR-16726 uses m_fg for Master/Slave
		// EPR-18643(A) seems to check m_shared[1], with a fallback to m_fg
		bool isMaster = (m_fg == 0x01 || m_shared[1] == 0x01);
		bool isSlave = (m_fg == 0x00 && m_shared[1] == 0x02);
		bool isRelay = (m_fg == 0x00 && m_shared[1] == 0x00);

		if (m_linkalive == 0x02)
		{
			// link failed...
			m_shared[0] = 0xff;
			return;
		}
		else if (m_linkalive == 0x00)
		{
			// link not yet established...
			m_shared[0] = 0x00;
			m_shared[2] = 0xff;
			m_shared[3] = 0xff;

			// check rx socket
			if (!m_line_rx)
			{
				osd_printf_verbose("M2COMM: listen on %s\n", m_localhost);
				uint64_t filesize; // unused
				osd_file::open(m_localhost, OPEN_FLAG_CREATE, m_line_rx, filesize);
			}

			// check tx socket
			if (!m_line_tx)
			{
				osd_printf_verbose("M2COMM: connect to %s\n", m_remotehost);
				uint64_t filesize; // unused
				osd_file::open(m_remotehost, 0, m_line_tx, filesize);
			}

			// if both sockets are there check ring
			if (m_line_rx && m_line_tx)
			{
				m_zfg ^= 0x01;

				// try to read one message
				recv = read_frame(dataSize);
				while (recv > 0)
				{
					// check if message id
					idx = m_buffer0[0];

					// 0xFF - link id
					if (idx == 0xff)
					{
						if (isMaster)
						{
							// master gets first id and starts next state
							m_linkid = 0x01;
							m_linkcount = m_buffer0[1];
							m_linktimer = 0x00;
						}
						else
						{
							// slave get own id, relay does nothing
							if (isSlave)
							{
								m_buffer0[1]++;
							}

							// forward message to other nodes
							send_frame(dataSize);
						}
					}

					// 0xFE - link size
					else if (idx == 0xfe)
					{
						if (isSlave)
						{
							// fetch linkid and linkcount, then decrease linkid
							m_linkid = m_buffer0[1];
							m_linkcount = m_buffer0[2];
							m_buffer0[1]--;

							// forward message to other nodes
							send_frame(dataSize);
						}
						else if (isRelay)
						{
							// fetch linkid and linkcount, then decrease linkid
							m_linkid = 0x00;
							m_linkcount = m_buffer0[2];

							// forward message to other nodes
							send_frame(dataSize);
						}

						// consider it done
						osd_printf_verbose("M2COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
						m_linkalive = 0x01;

						// write to shared mem
						m_shared[0] = 0x01;
						m_shared[2] = m_linkid;
						m_shared[3] = m_linkcount;
					}

					if (m_linkalive == 0x00)
						recv = read_frame(dataSize);
					else
						recv = 0;
				}

				// if we are master and link is not yet established
				if (isMaster && (m_linkalive == 0x00))
				{
					// send first packet
					if (m_linktimer == 0x01)
					{
						m_buffer0[0] = 0xff;
						m_buffer0[1] = 0x01;
						m_buffer0[2] = 0x00;
						send_frame(dataSize);
					}

					// send second packet
					else if (m_linktimer == 0x00)
					{
						m_buffer0[0] = 0xfe;
						m_buffer0[1] = m_linkcount;
						m_buffer0[2] = m_linkcount;
						send_frame(dataSize);

						// consider it done
						osd_printf_verbose("M2COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount);
						m_linkalive = 0x01;

						// write to shared mem
						m_shared[0] = 0x01;
						m_shared[2] = m_linkid;
						m_shared[3] = m_linkcount;
					}

					else if (m_linktimer > 0x01)
					{
						// decrease delay timer
						m_linktimer--;
					}
				}
			}
		}

		// if link established
		if (m_linkalive == 0x01)
		{
			do
			{
				// try to read a message
				recv = read_frame(dataSize);
				while (recv > 0)
				{
					// check if valid id
					idx = m_buffer0[0];
					if (idx >= 0 && idx <= m_linkcount)
					{
						// save message to "ring buffer"
						for (int j = 0x00 ; j < frameSize ; j++)
						{
							m_shared[frameOffset + j] = m_buffer0[1 + j];
						}
						m_zfg ^= 0x01;
						if (isSlave)
							send_data(m_linkid, frameStart, frameSize, dataSize);
						else if (isRelay)
							send_frame(dataSize);
					}
					else
					{
						if (idx == 0xfc)
						{
							// 0xFC - VSYNC
							m_linktimer = 0x00;

							if (!isMaster)
								// forward message to other nodes
								send_frame(dataSize);
						}
					}

					// try to read another message
					recv = read_frame(dataSize);
				}
			}
			while (m_linktimer == 0x01);

			// enable wait for vsync
			m_linktimer = m_framesync;

			if (isMaster)
			{
				// update "ring buffer" if link established
				send_data(m_linkid, frameStart, frameSize, dataSize);

				// send vsync
				m_buffer0[0] = 0xfc;
				m_buffer0[1] = 0x01;
				send_frame(dataSize);
			}

			m_zfg_delay = 0x02;
		}
	}
}

void m2comm_device::read_fg()
{
	if (m_zfg_delay > 0x00)
	{
		m_zfg_delay--;
		return;
	}
	if (m_linkalive == 0x01)
	{
		int frameStart = 0x2000;
		int frameSize = m_shared[0x13] << 8 | m_shared[0x12];
		int frameOffset = frameStart | m_shared[0x15] << 8 | m_shared[0x14];

		int dataSize = frameSize + 1;
		int recv = 0;
		int idx = 0;

		// EPR-16726 uses m_fg for Master/Slave
		// EPR-18643(A) seems to check m_shared[1], with a fallback to m_fg
		bool isMaster = (m_fg == 0x01 || m_shared[1] == 0x01);
		bool isSlave = (m_fg == 0x00 && m_shared[1] == 0x02);
		bool isRelay = (m_fg == 0x00 && m_shared[1] == 0x00);

		do
		{
			// try to read a message
			recv = read_frame(dataSize);
			while (recv > 0)
			{
				// check if valid id
				idx = m_buffer0[0];
				if (idx >= 0 && idx <= m_linkcount)
				{
					// save message to "ring buffer"
					for (int j = 0x00 ; j < frameSize ; j++)
					{
						m_shared[frameOffset + j] = m_buffer0[1 + j];
					}
					m_zfg ^= 0x01;
					if (isSlave)
						send_data(m_linkid, frameStart, frameSize, dataSize);
					else if (isRelay)
						send_frame(dataSize);
				}
				else
				{
					if (idx == 0xfc)
					{
						// 0xFC - VSYNC
						m_linktimer = 0x00;

						if (!isMaster)
							// forward message to other nodes
							send_frame(dataSize);
					}
				}

				// try to read another message
				recv = read_frame(dataSize);
			}
		}
		while (m_linktimer == 0x01);
	}
}

int m2comm_device::read_frame(int dataSize)
{
	if (!m_line_rx)
		return 0;

	// try to read a message
	std::uint32_t recv = 0;
	osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv);
	if (recv > 0)
	{
		// check if message complete
		if (recv != dataSize)
		{
			// only part of a message - read on
			std::uint32_t togo = dataSize - recv;
			int offset = recv;
			while (togo > 0)
			{
				filerr = m_line_rx->read(m_buffer1, 0, togo, recv);
				if (recv > 0)
				{
					for (int i = 0 ; i < recv ; i++)
					{
						m_buffer0[offset + i] = m_buffer1[i];
					}
					togo -= recv;
					offset += recv;
				}
				else if (filerr == osd_file::error::NONE && recv == 0)
				{
					togo = 0;
				}
			}
		}
	}
	else if (filerr == osd_file::error::NONE && recv == 0)
	{
		if (m_linkalive == 0x01)
		{
			osd_printf_verbose("M2COMM: rx connection lost\n");
			m_linkalive = 0x02;
			m_linktimer = 0x00;
			m_line_rx.reset();
		}
	}
	return recv;
}

void m2comm_device::send_data(uint8_t frameType, int frameStart, int frameSize, int dataSize)
{
	m_buffer0[0] = frameType;
	for (int i = 0x0000 ; i < frameSize ; i++)
	{
		m_buffer0[1 + i] = m_shared[frameStart + i];
	}
	send_frame(dataSize);
}

void m2comm_device::send_frame(int dataSize){
	if (!m_line_tx)
		return;

	osd_file::error filerr;
	std::uint32_t written;

	filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written);
	if (filerr != osd_file::error::NONE)
	{
		if (m_linkalive == 0x01)
		{
			osd_printf_verbose("M2COMM: tx connection lost\n");
			m_linkalive = 0x02;
			m_linktimer = 0x00;
			m_line_tx.reset();
		}
	}
}
#endif