summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/ps2mc.cpp
blob: b253f6153b70bb27ac5f09ce2a420a1eba1df0b0 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11



                                                                               
                                                  





                
                

                  

                                                                                   


                                                                        



                                                                                                             



                               














































































































































































                                                                                                                    
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
*   Sony PlayStation 2 memory card device skeleton
*
*   To Do:
*     Everything
*
*/

#include "emu.h"
#include "ps2mc.h"

DEFINE_DEVICE_TYPE(SONYPS2_MC, ps2_mc_device, "ps2mc", "PlayStation 2 Memory Card")

/*static*/ const size_t ps2_mc_device::BUFFER_SIZE = 512; // Total guess
/*static*/ const uint8_t ps2_mc_device::DEFAULT_TERMINATOR = 0x55;

ps2_mc_device::ps2_mc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, SONYPS2_MC, tag, owner, clock)
{
}

ps2_mc_device::~ps2_mc_device()
{
}

void ps2_mc_device::device_start()
{
	save_item(NAME(m_recv_buf));
	save_item(NAME(m_xmit_buf));
	save_item(NAME(m_curr_recv));
	save_item(NAME(m_curr_xmit));
	save_item(NAME(m_end_recv));
	save_item(NAME(m_end_xmit));
	save_item(NAME(m_cmd));
	save_item(NAME(m_cmd_size));
	save_item(NAME(m_terminator));
	save_item(NAME(m_status));
}

void ps2_mc_device::device_reset()
{
	memset(m_recv_buf, 0, BUFFER_SIZE);
	memset(m_xmit_buf, 0, BUFFER_SIZE);

	m_curr_recv = 0;
	m_curr_xmit = 0;

	m_end_recv = 0;
	m_end_xmit = 0;

	m_cmd = 0;
	m_cmd_size = 0;
	m_terminator = DEFAULT_TERMINATOR;
	m_status = 0;
}

void ps2_mc_device::recv_fifo_push(uint8_t data)
{
	if (m_end_recv >= BUFFER_SIZE)
	{
		return;
	}

	m_recv_buf[m_end_recv++] = data;

	//logerror("%s: Receiving %02x from SIO2, new top: %d\n", machine().describe_context(), data, m_end_recv);
}

void ps2_mc_device::xmit_fifo_push(uint8_t data)
{
	if (m_end_xmit >= BUFFER_SIZE)
	{
		return;
	}

	//logerror("%s: Pushing %02x onto transmit FIFO\n", machine().describe_context(), data);

	m_xmit_buf[m_end_xmit++] = data;
}

uint8_t ps2_mc_device::xmit_fifo_pop()
{
	uint8_t ret = 0;
	if (m_curr_xmit < m_end_xmit)
	{
		ret = m_xmit_buf[m_curr_xmit++];
	}
	if (m_curr_xmit >= m_end_xmit)
	{
		m_curr_xmit = 0;
		m_end_xmit = 0;
	}
	return ret;
}

uint8_t ps2_mc_device::recv_fifo_pop()
{
	uint8_t ret = 0;
	if (m_curr_recv < m_end_recv)
	{
		ret = m_recv_buf[m_curr_recv++];
	}
	if (m_curr_recv >= m_end_recv)
	{
		m_curr_recv = 0;
		m_end_recv = 0;
	}
	//logerror("recv_fifo_pop %02x, %d/%d\n", ret, m_curr_recv, m_end_recv);
	return ret;
}

void ps2_mc_device::process_fifos()
{
	m_status = 0;
	m_cmd_size = 0;

	while (recv_fifo_depth())
	{
		const uint8_t data = recv_fifo_pop();
		m_cmd_size++;

		if (m_cmd_size == 1)
		{
			if (data == SIO_DEVICE_ID)
			{
				xmit_fifo_push(0x2b);
			}
			else
			{
				logerror("%s: Unknkown command byte 1: %02x\n", machine().describe_context(), data);
			}
		}
		else if (m_cmd_size == 2)
		{
			process_command(data);
		}
	}

	m_curr_recv = 0;
	m_end_recv = 0;
}

void ps2_mc_device::process_command(uint8_t data)
{
	m_cmd = data;

	switch (m_cmd)
	{
		case CMD_UNKNOWN_F3:
			//logerror("%s: MC command: Unknown 0xf3\n", machine().describe_context());
			cmd_init();
			m_status = 0;
			break;
		case CMD_INIT:
			//logerror("%s: MC command: Init (%02x)\n", machine().describe_context(), m_cmd);
			cmd_init();
			break;
		case CMD_GET_TERM:
			//logerror("%s: MC command: Get Terminator\n", machine().describe_context());
			cmd_get_term();
			break;
		default:
			logerror("%s: Unknown MC command: %02x\n", machine().describe_context(), m_cmd);
			break;
	}
}

void ps2_mc_device::cmd_init()
{
	while (recv_fifo_depth())
	{
		recv_fifo_pop();

		if (m_cmd_size == 2)
		{
			m_status = 0x8c;
			xmit_fifo_push(m_terminator);
		}

		m_cmd_size++;
	}
}

void ps2_mc_device::cmd_get_term()
{
	while (recv_fifo_depth())
	{
		recv_fifo_pop();

		if (m_cmd_size == 2)
		{
			m_status = 0x8b;
			xmit_fifo_push(m_terminator);
			xmit_fifo_push(0x55);
		}

		m_cmd_size++;
	}
}