226 lines
8.5 KiB
C#
226 lines
8.5 KiB
C#
|
using System.IO;
|
|||
|
|
|||
|
namespace MAME.Core
|
|||
|
{
|
|||
|
public class Taitosnd
|
|||
|
{
|
|||
|
public static byte TC0140SYT_PORT01_FULL, TC0140SYT_PORT23_FULL, TC0140SYT_PORT01_FULL_MASTER, TC0140SYT_PORT23_FULL_MASTER;
|
|||
|
public struct TC0140SYT
|
|||
|
{
|
|||
|
public byte[] slavedata;
|
|||
|
public byte[] masterdata;
|
|||
|
public byte mainmode;
|
|||
|
public byte submode;
|
|||
|
public byte status;
|
|||
|
public byte nmi_enabled;
|
|||
|
public byte nmi_req;
|
|||
|
}
|
|||
|
public static TC0140SYT tc0140syt;
|
|||
|
public static void taitosnd_start()
|
|||
|
{
|
|||
|
tc0140syt = new TC0140SYT();
|
|||
|
tc0140syt.slavedata = new byte[4];
|
|||
|
tc0140syt.masterdata = new byte[4];
|
|||
|
tc0140syt.mainmode = 0;
|
|||
|
tc0140syt.submode = 0;
|
|||
|
tc0140syt.status = 0;
|
|||
|
tc0140syt.nmi_enabled = 0;
|
|||
|
tc0140syt.nmi_req = 0;
|
|||
|
TC0140SYT_PORT01_FULL = 0x01;
|
|||
|
TC0140SYT_PORT23_FULL = 0x02;
|
|||
|
TC0140SYT_PORT01_FULL_MASTER = 0x04;
|
|||
|
TC0140SYT_PORT23_FULL_MASTER = 0x08;
|
|||
|
}
|
|||
|
public static void Interrupt_Controller()
|
|||
|
{
|
|||
|
if ((tc0140syt.nmi_req != 0) && (tc0140syt.nmi_enabled != 0))
|
|||
|
{
|
|||
|
Cpuint.cpunum_set_input_line(1, (int)LineState.INPUT_LINE_NMI, LineState.PULSE_LINE);
|
|||
|
tc0140syt.nmi_req = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
public static void taitosound_port_w(int offset, byte data)
|
|||
|
{
|
|||
|
data &= 0x0f;
|
|||
|
tc0140syt.mainmode = data;
|
|||
|
}
|
|||
|
public static void taitosound_comm_w(int offset, byte data)
|
|||
|
{
|
|||
|
data &= 0x0f; /*this is important, otherwise ballbros won't work*/
|
|||
|
switch (tc0140syt.mainmode)
|
|||
|
{
|
|||
|
case 0x00: // mode #0
|
|||
|
tc0140syt.slavedata[tc0140syt.mainmode++] = data;
|
|||
|
break;
|
|||
|
case 0x01: // mode #1
|
|||
|
tc0140syt.slavedata[tc0140syt.mainmode++] = data;
|
|||
|
tc0140syt.status |= TC0140SYT_PORT01_FULL;
|
|||
|
tc0140syt.nmi_req = 1;
|
|||
|
break;
|
|||
|
case 0x02: // mode #2
|
|||
|
tc0140syt.slavedata[tc0140syt.mainmode++] = data;
|
|||
|
break;
|
|||
|
case 0x03: // mode #3
|
|||
|
tc0140syt.slavedata[tc0140syt.mainmode++] = data;
|
|||
|
tc0140syt.status |= TC0140SYT_PORT23_FULL;
|
|||
|
tc0140syt.nmi_req = 1;
|
|||
|
break;
|
|||
|
case 0x04: // port status
|
|||
|
/* this does a hi-lo transition to reset the sound cpu */
|
|||
|
if (data != 0)
|
|||
|
{
|
|||
|
Cpuint.cpunum_set_input_line(1, (int)LineState.INPUT_LINE_RESET, LineState.ASSERT_LINE);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Cpuint.cpunum_set_input_line(1, (int)LineState.INPUT_LINE_RESET, LineState.CLEAR_LINE);
|
|||
|
Cpuexec.cpu_spin(); /* otherwise no sound in driftout */
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
public static byte taitosound_comm_r(int offset)
|
|||
|
{
|
|||
|
byte result;
|
|||
|
switch (tc0140syt.mainmode)
|
|||
|
{
|
|||
|
case 0x00: // mode #0
|
|||
|
result = tc0140syt.masterdata[tc0140syt.mainmode++];
|
|||
|
break;
|
|||
|
case 0x01: // mode #1
|
|||
|
tc0140syt.status &= (byte)(~TC0140SYT_PORT01_FULL_MASTER);
|
|||
|
result = tc0140syt.masterdata[tc0140syt.mainmode++];
|
|||
|
break;
|
|||
|
case 0x02: // mode #2
|
|||
|
result = tc0140syt.masterdata[tc0140syt.mainmode++];
|
|||
|
break;
|
|||
|
case 0x03: // mode #3
|
|||
|
tc0140syt.status &= (byte)(~TC0140SYT_PORT23_FULL_MASTER);
|
|||
|
result = tc0140syt.masterdata[tc0140syt.mainmode++];
|
|||
|
break;
|
|||
|
case 0x04: // port status
|
|||
|
result = tc0140syt.status;
|
|||
|
break;
|
|||
|
default:
|
|||
|
result = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
public static void taitosound_slave_port_w(byte data)
|
|||
|
{
|
|||
|
data &= 0x0f;
|
|||
|
tc0140syt.submode = data;
|
|||
|
}
|
|||
|
public static void taitosound_slave_comm_w(byte data)
|
|||
|
{
|
|||
|
data &= 0x0f;
|
|||
|
switch (tc0140syt.submode)
|
|||
|
{
|
|||
|
case 0x00: // mode #0
|
|||
|
tc0140syt.masterdata[tc0140syt.submode++] = data;
|
|||
|
break;
|
|||
|
case 0x01: // mode #1
|
|||
|
tc0140syt.masterdata[tc0140syt.submode++] = data;
|
|||
|
tc0140syt.status |= TC0140SYT_PORT01_FULL_MASTER;
|
|||
|
Cpuexec.cpu_spin(); /* writing should take longer than emulated, so spin */
|
|||
|
break;
|
|||
|
case 0x02: // mode #2
|
|||
|
tc0140syt.masterdata[tc0140syt.submode++] = data;
|
|||
|
break;
|
|||
|
case 0x03: // mode #3
|
|||
|
tc0140syt.masterdata[tc0140syt.submode++] = data;
|
|||
|
tc0140syt.status |= TC0140SYT_PORT23_FULL_MASTER;
|
|||
|
Cpuexec.cpu_spin(); /* writing should take longer than emulated, so spin */
|
|||
|
break;
|
|||
|
case 0x04: // port status
|
|||
|
break;
|
|||
|
case 0x05: // nmi disable
|
|||
|
tc0140syt.nmi_enabled = 0;
|
|||
|
break;
|
|||
|
case 0x06: // nmi enable
|
|||
|
tc0140syt.nmi_enabled = 1;
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
Interrupt_Controller();
|
|||
|
}
|
|||
|
public static byte taitosound_slave_comm_r()
|
|||
|
{
|
|||
|
byte res = 0;
|
|||
|
switch (tc0140syt.submode)
|
|||
|
{
|
|||
|
case 0x00: // mode #0
|
|||
|
res = tc0140syt.slavedata[tc0140syt.submode++];
|
|||
|
break;
|
|||
|
case 0x01: // mode #1
|
|||
|
tc0140syt.status &= unchecked((byte)(~0x01));
|
|||
|
res = tc0140syt.slavedata[tc0140syt.submode++];
|
|||
|
break;
|
|||
|
case 0x02: // mode #2
|
|||
|
res = tc0140syt.slavedata[tc0140syt.submode++];
|
|||
|
break;
|
|||
|
case 0x03: // mode #3
|
|||
|
tc0140syt.status &= unchecked((byte)(~0x02));
|
|||
|
res = tc0140syt.slavedata[tc0140syt.submode++];
|
|||
|
break;
|
|||
|
case 0x04: // port status
|
|||
|
res = tc0140syt.status;
|
|||
|
break;
|
|||
|
default:
|
|||
|
res = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
Interrupt_Controller();
|
|||
|
return res;
|
|||
|
}
|
|||
|
public static void taitosound_port16_msb_w(ushort data)
|
|||
|
{
|
|||
|
//if (ACCESSING_BITS_8_15)
|
|||
|
taitosound_port_w(0, (byte)(data >> 8));
|
|||
|
}
|
|||
|
public static void taitosound_port16_msb_w1(byte data)
|
|||
|
{
|
|||
|
//if (ACCESSING_BITS_8_15)
|
|||
|
taitosound_port_w(0, data);
|
|||
|
}
|
|||
|
public static void taitosound_comm16_msb_w(ushort data)
|
|||
|
{
|
|||
|
//if (ACCESSING_BITS_8_15)
|
|||
|
taitosound_comm_w(0, (byte)(data >> 8));
|
|||
|
}
|
|||
|
public static void taitosound_comm16_msb_w1(byte data)
|
|||
|
{
|
|||
|
//if (ACCESSING_BITS_8_15)
|
|||
|
taitosound_comm_w(0, data);
|
|||
|
}
|
|||
|
public static ushort taitosound_comm16_msb_r()
|
|||
|
{
|
|||
|
return (ushort)(taitosound_comm_r(0) << 8);
|
|||
|
}
|
|||
|
public static void SaveStateBinary(BinaryWriter writer)
|
|||
|
{
|
|||
|
writer.Write(tc0140syt.slavedata, 0, 4);
|
|||
|
writer.Write(tc0140syt.masterdata, 0, 4);
|
|||
|
writer.Write(tc0140syt.mainmode);
|
|||
|
writer.Write(tc0140syt.submode);
|
|||
|
writer.Write(tc0140syt.status);
|
|||
|
writer.Write(tc0140syt.nmi_enabled);
|
|||
|
writer.Write(tc0140syt.nmi_req);
|
|||
|
}
|
|||
|
public static void LoadStateBinary(BinaryReader reader)
|
|||
|
{
|
|||
|
tc0140syt.slavedata = reader.ReadBytes(4);
|
|||
|
tc0140syt.masterdata = reader.ReadBytes(4);
|
|||
|
tc0140syt.mainmode = reader.ReadByte();
|
|||
|
tc0140syt.submode = reader.ReadByte();
|
|||
|
tc0140syt.status = reader.ReadByte();
|
|||
|
tc0140syt.nmi_enabled = reader.ReadByte();
|
|||
|
tc0140syt.nmi_req = reader.ReadByte();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|