AxibugEmuOnline/AxibugEmuOnline.Client/Assets/MyNes.Core/Namcot106Chnl.cs
2024-07-03 18:22:22 +08:00

158 lines
3.3 KiB
C#

using System.IO;
namespace MyNes.Core
{
internal class Namcot106Chnl
{
private Namcot106 namcot;
private int freqTimer;
private int frequency;
public int output;
public int output_av;
public int clocks;
private int cycles;
private int InstrumentLength;
private byte InstrumentAddress;
private int startPoint;
private int endPoint;
private int readPoint;
public int volume;
private bool freez;
public bool Enabled { get; set; }
public Namcot106Chnl(Namcot106 namcot)
{
this.namcot = namcot;
}
public void HardReset()
{
}
private void UpdateFrequency()
{
if (frequency > 0)
{
freqTimer = 983040 * (namcot.enabledChannels + 1) / frequency;
freez = false;
}
else
{
freez = true;
output_av = 0;
}
}
private void UpdatePlaybackParameters()
{
startPoint = InstrumentAddress;
endPoint = InstrumentAddress + 4 * (8 - InstrumentLength);
readPoint = InstrumentAddress;
}
public void WriteA(ref byte data)
{
frequency = (frequency & 0xFFFF00) | data;
UpdateFrequency();
}
public void WriteB(ref byte data)
{
frequency = (frequency & 0xFF00FF) | (data << 8);
UpdateFrequency();
}
public void WriteC(ref byte data)
{
frequency = (frequency & 0xFFFF) | ((data & 3) << 12);
InstrumentLength = (data >> 2) & 7;
UpdateFrequency();
UpdatePlaybackParameters();
}
public void WriteD(ref byte data)
{
InstrumentAddress = data;
UpdatePlaybackParameters();
}
public void WriteE(ref byte data)
{
volume = data & 0xF;
}
public void ClockSingle()
{
if (freez || --cycles > 0)
{
return;
}
cycles = freqTimer;
if (readPoint >= startPoint && readPoint <= endPoint)
{
if (Enabled && !freez)
{
if ((readPoint & 1) == 0)
{
output_av += (namcot.EXRAM[readPoint] & 0xF) * volume;
}
else
{
output_av += ((namcot.EXRAM[readPoint] >> 4) & 0xF) * volume;
}
}
readPoint++;
}
else
{
readPoint = startPoint;
}
clocks++;
}
public void SaveState(BinaryWriter stream)
{
stream.Write(freqTimer);
stream.Write(frequency);
stream.Write(output);
stream.Write(cycles);
stream.Write(InstrumentLength);
stream.Write(InstrumentAddress);
stream.Write(startPoint);
stream.Write(endPoint);
stream.Write(readPoint);
stream.Write(volume);
stream.Write(freez);
}
public void LoadState(BinaryReader stream)
{
freqTimer = stream.ReadInt32();
frequency = stream.ReadInt32();
output = stream.ReadByte();
cycles = stream.ReadInt32();
InstrumentLength = stream.ReadInt32();
InstrumentAddress = stream.ReadByte();
startPoint = stream.ReadInt32();
endPoint = stream.ReadInt32();
readPoint = stream.ReadInt32();
volume = stream.ReadInt32();
freez = stream.ReadBoolean();
}
}
}