1 #pragma once
2 
3 #include "Types.h"
4 #include "BasicUnion.h"
5 #include "Convertible.h"
6 #include "zip/ZipArchiveWriter.h"
7 #include "zip/ZipArchiveReader.h"
8 
9 class CRegisterStateFile;
10 
11 namespace Iop
12 {
13 	class CSpuBase
14 	{
15 	public:
16 		struct ADSR_LEVEL : public convertible<uint16>
17 		{
18 			unsigned int sustainLevel : 4;
19 			unsigned int decayRate : 4;
20 			unsigned int attackRate : 7;
21 			unsigned int attackMode : 1;
22 		};
23 		static_assert(sizeof(ADSR_LEVEL) >= sizeof(uint16), "Size of ADSR_LEVEL struct must be at least 2 bytes.");
24 
25 		struct ADSR_RATE : public convertible<uint16>
26 		{
27 			unsigned int releaseRate : 5;
28 			unsigned int releaseMode : 1;
29 			unsigned int sustainRate : 7;
30 			unsigned int reserved0 : 1;
31 			unsigned int sustainDirection : 1;
32 			unsigned int sustainMode : 1;
33 		};
34 		static_assert(sizeof(ADSR_RATE) >= sizeof(uint16), "Size of ADSR_RATE struct must be at least 2 bytes.");
35 
36 		struct CHANNEL_VOLUME : public convertible<uint16>
37 		{
38 			union {
39 				struct
40 				{
41 					unsigned int unused0 : 15;
42 					unsigned int mode : 1;
43 				} mode;
44 				struct
45 				{
46 					unsigned int volume : 14;
47 					unsigned int phase : 1;
48 					unsigned int mode : 1;
49 				} volume;
50 				struct
51 				{
52 					unsigned int volume : 7;
53 					unsigned int unused0 : 5;
54 					unsigned int phase : 1;
55 					unsigned int decrease : 1;
56 					unsigned int slope : 1;
57 					unsigned int mode : 1;
58 				} sweep;
59 			};
60 		};
61 		static_assert(sizeof(CHANNEL_VOLUME) >= sizeof(uint16), "Size of CHANNEL_VOLUME struct must be at least 2 bytes.");
62 
63 		enum
64 		{
65 			MAX_CHANNEL = 24
66 		};
67 
68 		enum
69 		{
70 			REVERB_PARAM_COUNT = 32
71 		};
72 
73 		enum CONTROL
74 		{
75 			CONTROL_REVERB = 0x80,
76 			CONTROL_IRQ = 0x40,
77 
78 			CONTROL_DMA = 0x30,
79 			CONTROL_DMA_STOP = 0x00,
80 			CONTROL_DMA_IO = 0x10,
81 			CONTROL_DMA_WRITE = 0x20,
82 			CONTROL_DMA_READ = 0x30,
83 		};
84 
85 		enum TRANSFER_MODE
86 		{
87 			TRANSFER_MODE_VOICE = 0,
88 			TRANSFER_MODE_BLOCK_CORE0IN = 1,
89 			TRANSFER_MODE_BLOCK_CORE1IN = 2,
90 			TRANSFER_MODE_BLOCK_READ = 4
91 		};
92 
93 		enum
94 		{
95 			FB_SRC_A = 0,
96 			FB_SRC_B,
97 			IIR_ALPHA,
98 			ACC_COEF_A,
99 			ACC_COEF_B,
100 			ACC_COEF_C,
101 			ACC_COEF_D,
102 			IIR_COEF,
103 			FB_ALPHA,
104 			FB_X,
105 			IIR_DEST_A0,
106 			IIR_DEST_A1,
107 			ACC_SRC_A0,
108 			ACC_SRC_A1,
109 			ACC_SRC_B0,
110 			ACC_SRC_B1,
111 			IIR_SRC_A0,
112 			IIR_SRC_A1,
113 			IIR_DEST_B0,
114 			IIR_DEST_B1,
115 			ACC_SRC_C0,
116 			ACC_SRC_C1,
117 			ACC_SRC_D0,
118 			ACC_SRC_D1,
119 			IIR_SRC_B1,
120 			IIR_SRC_B0,
121 			MIX_DEST_A0,
122 			MIX_DEST_A1,
123 			MIX_DEST_B0,
124 			MIX_DEST_B1,
125 			IN_COEF_L,
126 			IN_COEF_R,
127 			REVERB_REG_COUNT,
128 		};
129 
130 		enum CHANNEL_STATUS
131 		{
132 			STOPPED = 0,
133 			KEY_ON = 1,
134 			ATTACK,
135 			DECAY,
136 			SUSTAIN,
137 			RELEASE,
138 		};
139 
140 		struct CHANNEL
141 		{
142 			CHANNEL_VOLUME volumeLeft;
143 			CHANNEL_VOLUME volumeRight;
144 			int32 volumeLeftAbs;
145 			int32 volumeRightAbs;
146 			uint16 pitch;
147 			uint32 address;
148 			ADSR_LEVEL adsrLevel;
149 			ADSR_RATE adsrRate;
150 			uint32 adsrVolume;
151 			uint32 repeat;
152 			uint16 status;
153 			uint32 current;
154 		};
155 
156 		CSpuBase(uint8*, uint32, unsigned int);
157 		virtual ~CSpuBase() = default;
158 
159 		void Reset();
160 
161 		void LoadState(Framework::CZipArchiveReader&);
162 		void SaveState(Framework::CZipArchiveWriter&);
163 
164 		bool IsEnabled() const;
165 
166 		void SetVolumeAdjust(float);
167 		void SetReverbEnabled(bool);
168 
169 		void SetBaseSamplingRate(uint32);
170 
171 		bool GetIrqPending() const;
172 		void ClearIrqPending();
173 
174 		uint32 GetIrqAddress() const;
175 		void SetIrqAddress(uint32);
176 
177 		uint16 GetTransferMode() const;
178 		void SetTransferMode(uint16);
179 
180 		uint32 GetTransferAddress() const;
181 		void SetTransferAddress(uint32);
182 
183 		uint16 GetControl() const;
184 		void SetControl(uint16);
185 
186 		uint32 GetReverbParam(unsigned int) const;
187 		void SetReverbParam(unsigned int, uint32);
188 
189 		uint32 GetReverbWorkAddressStart() const;
190 		void SetReverbWorkAddressStart(uint32);
191 
192 		uint32 GetReverbWorkAddressEnd() const;
193 		void SetReverbWorkAddressEnd(uint32);
194 
195 		void SetReverbCurrentAddress(uint32);
196 
197 		UNION32_16 GetChannelOn() const;
198 		void SetChannelOn(uint16, uint16);
199 		void SetChannelOnLo(uint16);
200 		void SetChannelOnHi(uint16);
201 
202 		UNION32_16 GetChannelReverb() const;
203 		void SetChannelReverbLo(uint16);
204 		void SetChannelReverbHi(uint16);
205 
206 		CHANNEL& GetChannel(unsigned int);
207 
208 		void SendKeyOn(uint32);
209 		void SendKeyOff(uint32);
210 
211 		UNION32_16 GetEndFlags() const;
212 		void ClearEndFlags();
213 
214 		void WriteWord(uint16);
215 
216 		uint32 ReceiveDma(uint8*, uint32, uint32);
217 
218 		void Render(int16*, unsigned int, unsigned int);
219 
220 		static bool g_reverbParamIsAddress[REVERB_PARAM_COUNT];
221 
222 	private:
223 		enum
224 		{
225 			CORE0_OUTPUT_LEFT = 0x800,
226 			CORE0_OUTPUT_RIGHT = 0xA00,
227 			CORE0_OUTPUT_SIZE = 0x200,
228 			SOUND_INPUT_DATA_CORE0_BASE = 0x2000,
229 			SOUND_INPUT_DATA_CORE1_BASE = 0x2400,
230 			SOUND_INPUT_DATA_SIZE = 0x400,
231 			SOUND_INPUT_DATA_SAMPLES = (SOUND_INPUT_DATA_SIZE / 4),
232 		};
233 
234 		class CSampleReader
235 		{
236 		public:
237 			CSampleReader();
238 			virtual ~CSampleReader() = default;
239 
240 			void Reset();
241 			void SetMemory(uint8*, uint32);
242 
243 			void LoadState(const CRegisterStateFile&, const std::string&);
244 			void SaveState(CRegisterStateFile*, const std::string&) const;
245 
246 			void SetParamsRead(uint32, uint32);
247 			void SetParamsNoRead(uint32, uint32);
248 			void SetPitch(uint32, uint16);
249 			void GetSamples(int16*, unsigned int, unsigned int);
250 			uint32 GetRepeat() const;
251 			void SetRepeat(uint32);
252 			uint32 GetCurrent() const;
253 			void SetIrqAddress(uint32);
254 			bool IsDone() const;
255 			void ClearIsDone();
256 			bool GetEndFlag() const;
257 			void ClearEndFlag();
258 			bool GetIrqPending() const;
259 			void ClearIrqPending();
260 
261 			bool DidChangeRepeat() const;
262 			void ClearDidChangeRepeat();
263 
264 		private:
265 			enum
266 			{
267 				BUFFER_SAMPLES = 28,
268 			};
269 
270 			void SetParams(uint32, uint32);
271 			void UnpackSamples(int16*);
272 			void AdvanceBuffer();
273 			int16 GetSample(unsigned int);
274 
275 			uint8* m_ram = nullptr;
276 			uint32 m_ramSize = 0;
277 
278 			uint32 m_srcSampleIdx;
279 			unsigned int m_srcSamplingRate;
280 			uint32 m_nextSampleAddr = 0;
281 			uint32 m_repeatAddr = 0;
282 			uint32 m_irqAddr = 0;
283 			int16 m_buffer[BUFFER_SAMPLES * 2];
284 			uint16 m_pitch;
285 			int32 m_s1;
286 			int32 m_s2;
287 			bool m_done;
288 			bool m_nextValid;
289 			bool m_endFlag;
290 			bool m_irqPending = false;
291 			bool m_didChangeRepeat;
292 
293 			static_assert((sizeof(decltype(m_buffer)) % 16) == 0, "sizeof(m_buffer) must be a multiple of 16 (needed for saved state).");
294 		};
295 
296 		class CBlockSampleReader
297 		{
298 		public:
299 			void Reset();
300 			bool CanReadSamples() const;
301 
302 			void FillBlock(const uint8*);
303 			void GetSamples(int16&, int16&, unsigned int);
304 
305 		private:
306 			enum
307 			{
308 				SRC_SAMPLING_RATE = 48000,
309 			};
310 
311 			uint32 m_srcSampleIdx = 0;
312 			uint8 m_blockBuffer[SOUND_INPUT_DATA_SIZE];
313 		};
314 
315 		enum
316 		{
317 			MAX_ADSR_VOLUME = 0x7FFFFFFF,
318 		};
319 
320 		void UpdateAdsr(CHANNEL&);
321 		uint32 GetAdsrDelta(unsigned int) const;
322 		float GetReverbSample(uint32) const;
323 		void SetReverbSample(uint32, float);
324 		uint32 GetReverbOffset(unsigned int) const;
325 		float GetReverbCoef(unsigned int) const;
326 
327 		static void MixSamples(int32, int32, int16*);
328 		int32 ComputeChannelVolume(const CHANNEL_VOLUME&, int32);
329 
330 		static const uint32 g_linearIncreaseSweepDeltas[0x80];
331 		static const uint32 g_linearDecreaseSweepDeltas[0x80];
332 
333 		uint8* m_ram;
334 		uint32 m_ramSize;
335 		unsigned int m_spuNumber;
336 		uint32 m_baseSamplingRate;
337 
338 		uint32 m_irqAddr = 0;
339 		bool m_irqPending = false;
340 		uint16 m_transferMode;
341 		uint32 m_transferAddr;
342 		uint32 m_core0OutputOffset;
343 		UNION32_16 m_channelOn;
344 		UNION32_16 m_channelReverb;
345 		uint32 m_reverbWorkAddrStart;
346 		uint32 m_reverbWorkAddrEnd;
347 		uint32 m_reverbCurrAddr;
348 		uint16 m_ctrl;
349 		int m_reverbTicks;
350 		uint32 m_reverb[REVERB_REG_COUNT];
351 		CHANNEL m_channel[MAX_CHANNEL];
352 		CSampleReader m_reader[MAX_CHANNEL];
353 		uint32 m_adsrLogTable[160];
354 		bool m_reverbEnabled;
355 		float m_volumeAdjust;
356 
357 		CBlockSampleReader m_blockReader;
358 		uint32 m_soundInputDataAddr = 0;
359 		uint32 m_blockWritePtr = 0;
360 
361 		static_assert((sizeof(decltype(m_reverb)) % 16) == 0, "sizeof(m_reverb) must be a multiple of 16 (needed for saved state).");
362 	};
363 }
364