#ifndef _IOP_SPU_H_
#define _IOP_SPU_H_

#include "Iop_SpuBase.h"

namespace Iop
{
	class CSpu
	{
	public:
		CSpu(CSpuBase&);
		virtual ~CSpu();

		void Reset();

		uint16 ReadRegister(uint32);
		void WriteRegister(uint32, uint16);

		enum
		{
			SPU_BEGIN = 0x1F801C00,
			SPU_END = 0x1F801DFF
		};

		enum
		{
			CH0_BASE = 0x1F801C00,
			CH1_BASE = 0x1F801C10,
			CH2_BASE = 0x1F801C20,
			CH3_BASE = 0x1F801C30,
			CH4_BASE = 0x1F801C40,
			CH5_BASE = 0x1F801C50,
			CH6_BASE = 0x1F801C60,
			CH7_BASE = 0x1F801C70,
			CH8_BASE = 0x1F801C80,
			CH9_BASE = 0x1F801C90,
			CH10_BASE = 0x1F801CA0,
			CH11_BASE = 0x1F801CB0,
			CH12_BASE = 0x1F801CC0,
			CH13_BASE = 0x1F801CD0,
			CH14_BASE = 0x1F801CE0,
			CH15_BASE = 0x1F801CF0,
			CH16_BASE = 0x1F801D00,
			CH17_BASE = 0x1F801D10,
			CH18_BASE = 0x1F801D20,
			CH19_BASE = 0x1F801D30,
			CH20_BASE = 0x1F801D40,
			CH21_BASE = 0x1F801D50,
			CH22_BASE = 0x1F801D60,
			CH23_BASE = 0x1F801D70,
		};

		enum
		{
			CH_VOL_LEFT = 0x00,
			CH_VOL_RIGHT = 0x02,
			CH_PITCH = 0x04,
			CH_ADDRESS = 0x06,
			CH_ADSR_LEVEL = 0x08,
			CH_ADSR_RATE = 0x0A,
			CH_ADSR_VOLUME = 0x0C,
			CH_REPEAT = 0x0E
		};

		enum
		{
			SPU_GENERAL_BASE = 0x1F801D80,
		};

		enum
		{
			MAIN_VOL_LEFT = 0x1F801D80,
			MAIN_VOL_RIGHT = 0x1F801D82,
			REVERB_LEFT = 0x1F801D84,
			REVERB_RIGHT = 0x1F801D86,
			VOICE_ON_0 = 0x1F801D88,
			VOICE_ON_1 = 0x1F801D8A,
			VOICE_OFF_0 = 0x1F801D8C,
			VOICE_OFF_1 = 0x1F801D8E,
			FM_0 = 0x1F801D90,
			FM_1 = 0x1F801D92,
			NOISE_0 = 0x1F801D94,
			NOISE_1 = 0x1F801D96,
			REVERB_0 = 0x1F801D98,
			REVERB_1 = 0x1F801D9A,
			CHANNEL_ON_0 = 0x1F801D9C,
			CHANNEL_ON_1 = 0x1F801D9E,
			REVERB_WORK = 0x1F801DA2,
			IRQ_ADDR = 0x1F801DA4,
			BUFFER_ADDR = 0x1F801DA6,
			SPU_DATA = 0x1F801DA8,
			SPU_CTRL0 = 0x1F801DAA,
			SPU_STATUS0 = 0x1F801DAC,
			SPU_STATUS1 = 0x1F801DAE,
			CD_VOL_LEFT = 0x1F801DB0,
			CD_VOL_RIGHT = 0x1F801DB2,
			EXT_VOL_LEFT = 0x1F801DB4,
			EXT_VOL_RIGHT = 0x1F801DB6,
			REVERB_START = 0x1F801DC0,
			REVERB_END = 0x1F801E00,
		};

	private:
		void DisassembleRead(uint32);
		void DisassembleWrite(uint32, uint16);

		CSpuBase& m_base;

		uint16 m_status0;
		uint16 m_status1;
	};
}

#endif
