using System.IO;

namespace MyNes.Core
{
    internal class VRC6Sawtooth
    {
    	private byte AccumRate;

    	private int accumClock;

    	private byte accumulationRegister;

    	private int frequency;

    	private int freqTimer;

    	private int cycles;

    	private bool enabled;

    	internal int output;

    	internal bool Outputable;

    	internal void HardReset()
    	{
    	}

    	private void UpdateFrequency()
    	{
    		freqTimer = (frequency + 1) * 2;
    	}

    	internal void Write0(ref byte data)
    	{
    		AccumRate = (byte)(data & 0x3Fu);
    	}

    	internal void Write1(ref byte data)
    	{
    		frequency = (frequency & 0xF00) | data;
    		UpdateFrequency();
    	}

    	internal void Write2(ref byte data)
    	{
    		frequency = (frequency & 0xFF) | ((data & 0xF) << 8);
    		enabled = (data & 0x80) == 128;
    		UpdateFrequency();
    	}

    	internal void ClockSingle()
    	{
    		if (--cycles > 0)
    		{
    			return;
    		}
    		cycles = freqTimer;
    		if (enabled)
    		{
    			accumClock++;
    			switch (++accumClock)
    			{
    			case 2:
    			case 4:
    			case 6:
    			case 8:
    			case 10:
    			case 12:
    				accumulationRegister += AccumRate;
    				break;
    			case 14:
    				accumulationRegister = 0;
    				accumClock = 0;
    				break;
    			}
    			if (Outputable)
    			{
    				output = (accumulationRegister >> 3) & 0x1F;
    			}
    			else
    			{
    				output = 0;
    			}
    		}
    		else
    		{
    			output = 0;
    		}
    	}

    	internal void SaveState(ref BinaryWriter stream)
    	{
    		stream.Write(AccumRate);
    		stream.Write(accumClock);
    		stream.Write(accumulationRegister);
    		stream.Write(frequency);
    		stream.Write(freqTimer);
    		stream.Write(cycles);
    		stream.Write(enabled);
    	}

    	internal void LoadState(ref BinaryReader stream)
    	{
    		AccumRate = stream.ReadByte();
    		accumClock = stream.ReadInt32();
    		accumulationRegister = stream.ReadByte();
    		frequency = stream.ReadInt32();
    		freqTimer = stream.ReadInt32();
    		cycles = stream.ReadInt32();
    		enabled = stream.ReadBoolean();
    	}
    }
}