AxibugEmuOnline/AxibugEmuOnline.Client/Assets/Plugins/Mame.Core/sound/QSound.cs

239 lines
9.0 KiB
C#
Raw Normal View History

using System;
using System.IO;
namespace MAME.Core
{
public struct QSOUND_CHANNEL
{
public int bank; /* bank (x16) */
public int address; /* start address */
public int pitch; /* pitch */
public int reg3; /* unknown (always 0x8000) */
public int loop; /* loop address */
public int end; /* end address */
public int vol; /* master volume */
public int pan; /* Pan value */
public int reg9; /* unknown */
/* Work variables */
public int key; /* Key on / key off */
public int lvol; /* left volume */
public int rvol; /* right volume */
public int lastdt; /* last sample value */
public int offset; /* current offset counter */
};
public struct qsound_info
{
/* Private variables */
public QSOUND_CHANNEL[] channel;
public int data; /* register latch data */
public int sample_rom_length;
public int[] pan_table; /* Pan volume table */
public float frq_ratio; /* Frequency ratio */
};
public unsafe class QSound
{
public static sbyte[] qsoundrom;
public static qsound_info QChip;
public static void qsound_start()
{
int i;
QChip.sample_rom_length = qsoundrom.Length;
QChip.channel = new QSOUND_CHANNEL[16];
//QChip.frq_ratio = 16.0;
QChip.pan_table = new int[33];
for (i = 0; i < 33; i++)
{
QChip.pan_table[i] = (int)((256 / Math.Sqrt(32)) * Math.Sqrt(i));
}
}
public static void qsound_data_h_w(byte data)
{
QChip.data = (QChip.data & 0xff) | (data << 8);
}
public static void qsound_data_l_w(byte data)
{
QChip.data = (QChip.data & 0xff00) | data;
}
public static void qsound_cmd_w(byte data)
{
qsound_set_command(data, QChip.data);
}
public static byte qsound_status_r()
{
/* Port ready bit (0x80 if ready) */
return 0x80;
}
private static void qsound_set_command(int data, int value)
{
int ch = 0, reg = 0;
if (data < 0x80)
{
ch = data >> 3;
reg = data & 0x07;
}
else
{
if (data < 0x90)
{
ch = data - 0x80;
reg = 8;
}
else
{
if (data >= 0xba && data < 0xca)
{
ch = data - 0xba;
reg = 9;
}
else
{
/* Unknown registers */
ch = 99;
reg = 99;
}
}
}
switch (reg)
{
case 0: /* Bank */
ch = (ch + 1) & 0x0f; /* strange ... */
QChip.channel[ch].bank = (value & 0x7f) << 16;
break;
case 1: /* start */
QChip.channel[ch].address = value;
break;
case 2: /* pitch */
QChip.channel[ch].pitch = value * 16;
if (value == 0)
{
/* Key off */
QChip.channel[ch].key = 0;
}
break;
case 3: /* unknown */
QChip.channel[ch].reg3 = value;
break;
case 4: /* loop offset */
QChip.channel[ch].loop = value;
break;
case 5: /* end */
QChip.channel[ch].end = value;
break;
case 6: /* master volume */
if (value == 0)
{
/* Key off */
QChip.channel[ch].key = 0;
}
else if (QChip.channel[ch].key == 0)
{
/* Key on */
QChip.channel[ch].key = 1;
QChip.channel[ch].offset = 0;
QChip.channel[ch].lastdt = 0;
}
QChip.channel[ch].vol = value;
break;
case 7: /* unused */
break;
case 8:
{
int pandata = (value - 0x10) & 0x3f;
if (pandata > 32)
{
pandata = 32;
}
QChip.channel[ch].rvol = QChip.pan_table[pandata];
QChip.channel[ch].lvol = QChip.pan_table[32 - pandata];
QChip.channel[ch].pan = value;
}
break;
case 9:
QChip.channel[ch].reg9 = value;
break;
}
}
public static void qsound_update(int offset, int length)
{
int i, j;
int rvol, lvol, count;
for (i = 0; i < length; i++)
{
Sound.qsoundstream.streamoutput_Ptrs[0][offset + i] = 0;
Sound.qsoundstream.streamoutput_Ptrs[1][offset + i] = 0;
}
for (i = 0; i < 16; i++)
{
if (QChip.channel[i].key != 0)
{
rvol = (QChip.channel[i].rvol * QChip.channel[i].vol) >> 8;
lvol = (QChip.channel[i].lvol * QChip.channel[i].vol) >> 8;
for (j = 0; j < length; j++)
{
count = (QChip.channel[i].offset) >> 16;
QChip.channel[i].offset &= 0xffff;
if (count != 0)
{
QChip.channel[i].address += count;
if (QChip.channel[i].address >= QChip.channel[i].end)
{
if (QChip.channel[i].loop == 0)
{
/* Reached the end of a non-looped sample */
QChip.channel[i].key = 0;
break;
}
/* Reached the end, restart the loop */
QChip.channel[i].address = (QChip.channel[i].end - QChip.channel[i].loop) & 0xffff;
}
QChip.channel[i].lastdt = qsoundrom[(QChip.channel[i].bank + QChip.channel[i].address) % (QChip.sample_rom_length)];
}
Sound.qsoundstream.streamoutput_Ptrs[0][offset + j] += ((QChip.channel[i].lastdt * lvol) >> 6);
Sound.qsoundstream.streamoutput_Ptrs[1][offset + j] += ((QChip.channel[i].lastdt * rvol) >> 6);
QChip.channel[i].offset += QChip.channel[i].pitch;
}
}
}
}
public static void SaveStateBinary(BinaryWriter writer)
{
int i;
for (i = 0; i < 16; i++)
{
writer.Write(QChip.channel[i].bank);
writer.Write(QChip.channel[i].address);
writer.Write(QChip.channel[i].pitch);
writer.Write(QChip.channel[i].loop);
writer.Write(QChip.channel[i].end);
writer.Write(QChip.channel[i].vol);
writer.Write(QChip.channel[i].pan);
writer.Write(QChip.channel[i].key);
writer.Write(QChip.channel[i].lvol);
writer.Write(QChip.channel[i].rvol);
writer.Write(QChip.channel[i].lastdt);
writer.Write(QChip.channel[i].offset);
}
writer.Write(QChip.data);
}
public static void LoadStateBinary(BinaryReader reader)
{
int i;
for (i = 0; i < 16; i++)
{
QChip.channel[i].bank = reader.ReadInt32();
QChip.channel[i].address = reader.ReadInt32();
QChip.channel[i].pitch = reader.ReadInt32();
QChip.channel[i].loop = reader.ReadInt32();
QChip.channel[i].end = reader.ReadInt32();
QChip.channel[i].vol = reader.ReadInt32();
QChip.channel[i].pan = reader.ReadInt32();
QChip.channel[i].key = reader.ReadInt32();
QChip.channel[i].lvol = reader.ReadInt32();
QChip.channel[i].rvol = reader.ReadInt32();
QChip.channel[i].lastdt = reader.ReadInt32();
QChip.channel[i].offset = reader.ReadInt32();
}
QChip.data = reader.ReadInt32();
}
}
}