413 lines
15 KiB
C#
413 lines
15 KiB
C#
using System.IO;
|
|
|
|
namespace MAME.Core
|
|
{
|
|
/*public enum eeprom_command
|
|
{
|
|
COMMAND_INVALID,
|
|
COMMAND_READ,
|
|
COMMAND_WRITE,
|
|
COMMAND_ERASE,
|
|
COMMAND_LOCK,
|
|
COMMAND_UNLOCK,
|
|
COMMAND_WRITEALL,
|
|
COMMAND_ERASEALL,
|
|
COMMAND_COPY_EEPROM_TO_RAM,
|
|
COMMAND_COPY_RAM_TO_EEPROM
|
|
}
|
|
public enum eeprom_state
|
|
{
|
|
STATE_IN_RESET,
|
|
STATE_WAIT_FOR_START_BIT,
|
|
STATE_WAIT_FOR_COMMAND,
|
|
STATE_READING_DATA,
|
|
STATE_WAIT_FOR_DATA,
|
|
STATE_WAIT_FOR_COMPLETION
|
|
};
|
|
public enum eeprom_event
|
|
{
|
|
EVENT_CS_RISING_EDGE = 1 << 0,
|
|
EVENT_CS_FALLING_EDGE = 1 << 1,
|
|
EVENT_CLK_RISING_EDGE = 1 << 2,
|
|
EVENT_CLK_FALLING_EDGE = 1 << 3
|
|
};*/
|
|
public class Eeprom
|
|
{
|
|
public static int serial_count;
|
|
public static byte[] serial_buffer = new byte[40];
|
|
public static byte[] eeprom_data = new byte[0x80];
|
|
private static byte[] cmd_read;
|
|
private static byte[] cmd_write;
|
|
private static byte[] cmd_erase;
|
|
private static byte[] cmd_lock, cmd_unlock;
|
|
public static int eeprom_data_bits;
|
|
public static int eeprom_read_address;
|
|
public static int eeprom_clock_count;
|
|
public static int latch, sending;
|
|
public static int address_bits, data_bits;
|
|
public static LineState reset_line, clock_line;
|
|
public static int locked;
|
|
public static int enable_multi_read;
|
|
public static int reset_delay, reset_delay1;
|
|
private static bool eeprom_command_match(byte[] buf, byte[] cmd, int len)
|
|
{
|
|
int ibuf = 0, idx = 0;
|
|
if (cmd.Length == 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (len == 0)
|
|
{
|
|
return false;
|
|
}
|
|
for (; len > 0;)
|
|
{
|
|
byte b = buf[ibuf];
|
|
byte c = cmd[idx];
|
|
if ((b == 0) || (c == 0))
|
|
return (b == c);
|
|
switch (c)
|
|
{
|
|
case (byte)'0':
|
|
case (byte)'1':
|
|
if (b != c)
|
|
{
|
|
return false;
|
|
}
|
|
ibuf++;
|
|
len--;
|
|
idx++;
|
|
break;
|
|
case (byte)'X':
|
|
case (byte)'x':
|
|
ibuf++;
|
|
len--;
|
|
idx++;
|
|
break;
|
|
case (byte)'*':
|
|
break;
|
|
}
|
|
}
|
|
return (idx >= cmd.Length);
|
|
}
|
|
public static void eeprom_init()
|
|
{
|
|
serial_count = 0;
|
|
latch = 0;
|
|
reset_line = LineState.ASSERT_LINE;
|
|
clock_line = LineState.ASSERT_LINE;
|
|
eeprom_read_address = 0;
|
|
sending = 0;
|
|
reset_delay1 = 0;
|
|
switch (Machine.sBoard)
|
|
{
|
|
case "CPS-1"://pang3
|
|
cmd_read = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'0' };
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'1' };
|
|
cmd_erase = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'1' };
|
|
cmd_lock = new byte[] { };
|
|
cmd_unlock = new byte[] { };
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 0;
|
|
address_bits = 6;
|
|
data_bits = 16;
|
|
break;
|
|
case "CPS-1(QSound)":
|
|
cmd_read = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'0' };
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'1' };
|
|
cmd_erase = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'1' };
|
|
cmd_lock = new byte[] { };
|
|
cmd_unlock = new byte[] { };
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 0;
|
|
address_bits = 7;
|
|
data_bits = 8;
|
|
break;
|
|
case "CPS2":
|
|
cmd_read = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'0' };
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'1' };
|
|
cmd_erase = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'1' };
|
|
cmd_lock = new byte[] { };
|
|
cmd_unlock = new byte[] { };
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 0;
|
|
address_bits = 6;
|
|
data_bits = 16;
|
|
break;
|
|
case "Taito B":
|
|
cmd_read = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'0' };
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'1' };
|
|
cmd_erase = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'1' };
|
|
cmd_lock = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0' };
|
|
cmd_unlock = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'0', (byte)'1', (byte)'1', (byte)'0', (byte)'0', (byte)'0', (byte)'0' };
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 1;
|
|
address_bits = 6;
|
|
data_bits = 16;
|
|
break;
|
|
case "Konami 68000":
|
|
cmd_read = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'0', (byte)'0', (byte)'0' };
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'1', (byte)'1', (byte)'0', (byte)'0' };
|
|
cmd_erase = new byte[] { };
|
|
cmd_lock = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0' };
|
|
cmd_unlock = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'0', (byte)'1', (byte)'1', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0', (byte)'0' };
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 1;
|
|
address_bits = 7;
|
|
data_bits = 8;
|
|
switch (Machine.sName)
|
|
{
|
|
case "thndrx2":
|
|
case "thndrx2a":
|
|
case "thndrx2j":
|
|
case "prmrsocr":
|
|
case "prmrsocrj":
|
|
cmd_write = new byte[] { (byte)'0', (byte)'1', (byte)'0', (byte)'1', (byte)'0', (byte)'0' };
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
switch (Machine.sName)
|
|
{
|
|
case "pang3":
|
|
case "pang3r1":
|
|
case "pang3j":
|
|
case "pang3b":
|
|
for (int i = 0; i < 0x80; i++)
|
|
{
|
|
eeprom_data[i] = 0xff;
|
|
}
|
|
locked = 0;
|
|
address_bits = 6;
|
|
data_bits = 16;
|
|
break;
|
|
}
|
|
}
|
|
private static void eeprom_write(int bit)
|
|
{
|
|
if (serial_count >= 40 - 1)
|
|
{
|
|
return;
|
|
}
|
|
serial_buffer[serial_count++] = (bit != 0 ? (byte)'1' : (byte)'0');
|
|
serial_buffer[serial_count] = 0; /* nul terminate so we can treat it as a string */
|
|
if ((serial_count > address_bits) && eeprom_command_match(serial_buffer, cmd_read, serial_count - address_bits))
|
|
{
|
|
int i, address;
|
|
address = 0;
|
|
for (i = serial_count - address_bits; i < serial_count; i++)
|
|
{
|
|
address <<= 1;
|
|
if (serial_buffer[i] == (byte)'1')
|
|
{
|
|
address |= 1;
|
|
}
|
|
}
|
|
if (data_bits == 16)
|
|
{
|
|
eeprom_data_bits = (eeprom_data[2 * address + 0] << 8) + eeprom_data[2 * address + 1];
|
|
}
|
|
else
|
|
{
|
|
eeprom_data_bits = eeprom_data[address];
|
|
}
|
|
eeprom_read_address = address;
|
|
eeprom_clock_count = 0;
|
|
sending = 1;
|
|
serial_count = 0;
|
|
}
|
|
else if ((serial_count > address_bits) && eeprom_command_match(serial_buffer, cmd_erase, serial_count - address_bits))
|
|
{
|
|
int i, address;
|
|
address = 0;
|
|
for (i = serial_count - address_bits; i < serial_count; i++)
|
|
{
|
|
address <<= 1;
|
|
if (serial_buffer[i] == '1')
|
|
{
|
|
address |= 1;
|
|
}
|
|
}
|
|
if (locked == 0)
|
|
{
|
|
if (data_bits == 16)
|
|
{
|
|
eeprom_data[2 * address + 0] = 0x00;
|
|
eeprom_data[2 * address + 1] = 0x00;
|
|
}
|
|
else
|
|
{
|
|
eeprom_data[address] = 0x00;
|
|
}
|
|
}
|
|
serial_count = 0;
|
|
}
|
|
else if ((serial_count > (address_bits + data_bits)) && eeprom_command_match(serial_buffer, cmd_write, serial_count - (address_bits + data_bits)))
|
|
{
|
|
int i, address, data;
|
|
address = 0;
|
|
for (i = serial_count - data_bits - address_bits; i < (serial_count - data_bits); i++)
|
|
{
|
|
address <<= 1;
|
|
if (serial_buffer[i] == '1')
|
|
{
|
|
address |= 1;
|
|
}
|
|
}
|
|
data = 0;
|
|
for (i = serial_count - data_bits; i < serial_count; i++)
|
|
{
|
|
data <<= 1;
|
|
if (serial_buffer[i] == '1')
|
|
{
|
|
data |= 1;
|
|
}
|
|
}
|
|
if (locked == 0)
|
|
{
|
|
if (data_bits == 16)
|
|
{
|
|
eeprom_data[2 * address + 0] = (byte)(data >> 8);
|
|
eeprom_data[2 * address + 1] = (byte)(data & 0xff);
|
|
}
|
|
else
|
|
{
|
|
eeprom_data[address] = (byte)data;
|
|
}
|
|
}
|
|
serial_count = 0;
|
|
}
|
|
else if (eeprom_command_match(serial_buffer, cmd_lock, serial_count))
|
|
{
|
|
locked = 1;
|
|
serial_count = 0;
|
|
}
|
|
else if (eeprom_command_match(serial_buffer, cmd_unlock, serial_count))
|
|
{
|
|
locked = 0;
|
|
serial_count = 0;
|
|
}
|
|
}
|
|
private static void eeprom_reset()
|
|
{
|
|
serial_count = 0;
|
|
sending = 0;
|
|
reset_delay = reset_delay1;
|
|
}
|
|
public static void eeprom_write_bit(int bit)
|
|
{
|
|
latch = bit;
|
|
}
|
|
public static int eeprom_read_bit()
|
|
{
|
|
int res;
|
|
if (sending == 1)
|
|
{
|
|
res = (eeprom_data_bits >> data_bits) & 1;
|
|
}
|
|
else
|
|
{
|
|
if (reset_delay > 0)
|
|
{
|
|
reset_delay--;
|
|
res = 0;
|
|
}
|
|
else
|
|
{
|
|
res = 1;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
public static int eeprom_bit_r()
|
|
{
|
|
return eeprom_read_bit();
|
|
}
|
|
public static void eeprom_set_cs_line(LineState state)
|
|
{
|
|
reset_line = state;
|
|
if (reset_line != LineState.CLEAR_LINE)
|
|
{
|
|
eeprom_reset();
|
|
}
|
|
}
|
|
public static void eeprom_set_clock_line(LineState state)
|
|
{
|
|
if (state == LineState.PULSE_LINE || (clock_line == LineState.CLEAR_LINE && state != LineState.CLEAR_LINE))
|
|
{
|
|
if (reset_line == LineState.CLEAR_LINE)
|
|
{
|
|
if (sending == 1)
|
|
{
|
|
if (eeprom_clock_count == data_bits && enable_multi_read != 0)
|
|
{
|
|
eeprom_read_address = (eeprom_read_address + 1) & ((1 << address_bits) - 1);
|
|
if (data_bits == 16)
|
|
{
|
|
eeprom_data_bits = (eeprom_data[2 * eeprom_read_address + 0] << 8) + eeprom_data[2 * eeprom_read_address + 1];
|
|
}
|
|
else
|
|
{
|
|
eeprom_data_bits = eeprom_data[eeprom_read_address];
|
|
}
|
|
eeprom_clock_count = 0;
|
|
}
|
|
eeprom_data_bits = (eeprom_data_bits << 1) | 1;
|
|
eeprom_clock_count++;
|
|
}
|
|
else
|
|
{
|
|
eeprom_write(latch);
|
|
}
|
|
}
|
|
}
|
|
clock_line = state;
|
|
}
|
|
public static void SaveStateBinary(BinaryWriter writer)
|
|
{
|
|
writer.Write(eeprom_data);
|
|
writer.Write(serial_buffer);
|
|
writer.Write((int)clock_line);
|
|
writer.Write((int)reset_line);
|
|
writer.Write(locked);
|
|
writer.Write(serial_count);
|
|
writer.Write(latch);
|
|
writer.Write(reset_delay);
|
|
writer.Write(sending);
|
|
writer.Write(eeprom_clock_count);
|
|
writer.Write(eeprom_data_bits);
|
|
writer.Write(eeprom_read_address);
|
|
}
|
|
public static void LoadStateBinary(BinaryReader reader)
|
|
{
|
|
eeprom_data = reader.ReadBytes(0x80);
|
|
serial_buffer = reader.ReadBytes(40);
|
|
clock_line = (LineState)reader.ReadInt32();
|
|
reset_line = (LineState)reader.ReadInt32();
|
|
locked = reader.ReadInt32();
|
|
serial_count = reader.ReadInt32();
|
|
latch = reader.ReadInt32();
|
|
reset_delay = reader.ReadInt32();
|
|
sending = reader.ReadInt32();
|
|
eeprom_clock_count = reader.ReadInt32();
|
|
eeprom_data_bits = reader.ReadInt32();
|
|
eeprom_read_address = reader.ReadInt32();
|
|
}
|
|
}
|
|
}
|