aboutsummaryrefslogtreecommitdiff
path: root/lib/snesapu/SNES/SNESAPU/APU.h
blob: 18a0a1922c17276128d66456b36dff0661e87fb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/***************************************************************************************************
* Program:    Super Nintendo Entertainment System(tm) Audio Processing Unit Emulator               *
* Platform:   Intel 80386 & MMX                                                                    *
* Programmer: Anti Resonance                                                                       *
*                                                                                                  *
* "SNES" and "Super Nintendo Entertainment System" are trademarks of Nintendo Co., Limited and its *
* subsidiary companies.                                                                            *
*                                                                                                  *
* This library is free software; you can redistribute it and/or modify it under the terms of the   *
* GNU Lesser General Public License as published by the Free Software Foundation; either version   *
* 2.1 of the License, or (at your option) any later version.                                       *
*                                                                                                  *
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;        *
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        *
* See the GNU Lesser General Public License for more details.                                      *
*                                                                                                  *
* You should have received a copy of the GNU Lesser General Public License along with this         *
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,        *
* Boston, MA  02111-1307  USA                                                                      *
*                                                                                                  *
* ------------------------------------------------------------------------------------------------ *
* Revision History:                                                                                *
*                                                                                                  *
*  2005.10.28 SNESAPU 3.0
*  + Added NULL pointer support to SaveAPU and RestoreAPU                                          *
*  + Moved variables into the .bss                                                                 *
*  + The build options are now returned by InitAPU instead of being stored in a global variable    *
*  - Calculate the emulated sample rate at the top of EmuAPU so SetAPUSmpClk will be thread safe   *
*                                                                                                  *
*  2003.11.04 SNESAPU 2.0                                                                          *
*  + Updated EmuAPU to use SetEmuDSP when DSPINTEG is enabled                                      *
*  + Move fade out code into DSP.Asm                                                               *
*  + Removed amp setting from ResetAPU                                                             *
*                                                                                                  *
*  2003.07.12 SNESAPU 1.0a                                                                         *
*  - Fixed the call to SetDSPVol in SetFade that wasn't restoring the stack                        *
*                                                                                                  *
*  2003.06.20                                                                                      *
*  + Added LoadSPCFile                                                                             *
*  + Added ability to pass -1 to ResetAPU to keep current amp level                                *
*                                                                                                  *
*  2003.02.10                                                                                      *
*  + Rewrote in assembly                                                                           *
*  + Removed GetAPUData and memory allocation (they were specific to SNESAPU.DLL)                  *
*  - Sometimes EmuAPU would generate an extra sample                                               *
*                                                                                                  *
*  2002.06.20                                                                                      *
*  - Call SetFade after seeking                                                                    *
*                                                                                                  *
*  2001.04.12                                                                                      *
*  + Updated SeekAPU to incorporate new features in SPC700 and DSP emus                            *
*                                                                                                  *
*  2000.12.30 SNESAmp v2.0                                                                         *
*  + Added SetAPULength, SeekAPU, SaveAPU, RestoreAPU, HaltAPU                                     *
*  + General optimizations                                                                         *
*  - Simplified interface a bit                                                                    *
*                                                                                                  *
*  2000.04.04 SNESAmp v1.0                                                                         *
*                                                                                                  *
*  2000.03.17 SNESAmp v0.9                                                                         *
*                                                        Copyright (C)2003-06 Alpha-II Productions *
***************************************************************************************************/

namespace A2
{
namespace SNES
{

	//**********************************************************************************************
	// Compile Options

	//The build options correspond to the equates at the top of APU.Inc

	enum APUOpts
	{
		//SPC700 clock speed divisor (bits 7-0)
		SA_CLKDIV	= 0x00000FF,				//Mask for retieving the clock divisor

		//APU build options (bits 15-8) --------
		SA_DEBUG	= 0x0000100,				//Debugging ability enabled
		SA_DSPINTEG	= 0x0000200,				//DSP emulation is integrated with the SPC700

		//SPC700 build options (bits 23-16) ----
		SA_HALFC	= 0x0010000,				//Half-carry flag emulation enabled
		SA_IPLW		= 0x0080000,				//IPL ROM region writeable
		SA_CNTBK	= 0x0020000,				//Break SPC700/Update DSP if a counter is increased
		SA_DSPBK	= 0x0100000,				//Break SPC700/Update DSP if 0F3h is read from
		SA_SPEED	= 0x0040000,				//Hacks are enabled to skip cycles when a counter is
												// read or the processor is sleeping
		SA_PROFILE	= 0x0200000,				//Profiling counters enabled

		//DSP build options (bits 31-24) -------
		SA_MAINPPM	= 0x1000000,				//Peak program metering on main output (for AAR)
		SA_VOICEPPM	= 0x2000000,				//Peak program metering on voices (for visualization)
		SA_STEREO	= 0x4000000					//Stereo controls enabled (seperation and EFBCT)
	};


	//**********************************************************************************************
	// Structures

	//Profiling counters -----------------------
	struct Profile
	{
		struct Counter
		{
			u64		acc;						//Accumulated time spent executing
			u64		base;						//Temp value (holds the TSC upon entrance)
		};

		u32			exec[256];					//Number of times instruction has been executed

		struct Branch							//For branch instructions executed, the number of
		{										// times the branch was taken:
			u32		bxx[8];						//BPL, BMI, BVC, BVS, BCC, BCS, BNE, BEQ
			u32		bbc[8];						//BBC.bit
			u32		bbs[8];						//BBS.bit
			u32		cbne[2];					//CBNE dp, CBNE dp+X
			u32		dbnz[2];					//DBNZ Y, DBNZ dp
		} branch;

		struct Func								//Number of times a function register was accessed
		{
			u32		read[16];
			u32		write[16];
			u32		write16[16];				//16-bit write via MOVW, INCW, or DECW
		} func;

		struct DSP
		{
			u32		read[128];					//DSP register was read from
			u32		write[256];					//DSP register was written to

			struct Update						//Used when DSP integration is enabled
			{
				u32	reg[128];					//Register write that caused an update
				u32	num;						//Number of times DSP got updated during SPC700 emu.
				u32	read;						//Number of those times because of a register read
				u32	gen;						//Number of times the update generated output
				u32	_r;
			} update;
		} dsp;

		struct TSC								//Time-stamp counters
		{
			Counter	host;						//Place holder for user to store total execution time
			Counter	apu;						//Time spent in EmuAPU()
			Counter	spc700;						//Time spent in EmuSPC()
			Counter	dsp;						//Time spent in EmuDSP()
		} tsc;
	};


#if !defined(SNESAPU_DLL) || defined(DONT_IMPORT_SNESAPU)

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Private Declarations

	extern "C" Profile	profile;				//Profiling counters


	////////////////////////////////////////////////////////////////////////////////////////////////
	// External Functions

extern "C" {

	//**********************************************************************************************
	// Initialize Audio Processing Unit
	//
	// Initializes internal tables, mixer settings, memory, and registers.
	// This only needs to be called once.
	//
	// see InitSPC() and InitDSP()
	//
	// Out:
	//    APU build options (see the SA_??? above, APU.Inc, and SNESAPU.h GetAPUData())

	u32 InitAPU();


	//**********************************************************************************************
	// Reset Audio Processor
	//
	// Clears all memory and sets registers to their default values
	//
	// Thread safe:
	//    No
	//
	// see ResetSPC() and ResetDSP()

	void ResetAPU();


	//**********************************************************************************************
	// Load SPC File
	//
	// Restores the APU state from an .SPC file.  You do not need to call ResetAPU() before loading
	// a file.
	//
	// Thread safe:
	//    No
	//
	// In:
	//    pFile -> 66048 byte SPC file

	void LoadSPCFile(const void* pFile);


	//**********************************************************************************************
	// Save Audio Processor State
	//
	// Creates a saved state of the audio processor
	//
	// see SaveSPC() and SaveDSP()
	//
	// Thread safe:
	//    No
	//
	// In:
	//    pSPC -> SPCState structure (can be NULL)
	//    pDSP -> DSPState structure (can be NULL)

	void SaveAPU(SPCState* pSPC, DSPState* pDSP);


	//**********************************************************************************************
	// Restore Audio Processor State
	//
	// Restores the audio processor from a saved state
	//
	// see RestoreSPC() and RestoreDSP()
	//
	// Thread safe:
	//    No
	//
	// In:
	//    spc -> SPCState structure (can be NULL)
	//    dsp -> DSPState structure (can be NULL)

	void RestoreAPU(const SPCState& spc, const DSPState& dsp);


	//**********************************************************************************************
	// Set Audio Processor Options
	//
	// Configures the sound processor emulator.  Range checking is performed on all parameters.
	//
	// Notes:  -1 can be passed for any parameter you want to remain unchanged
	//         see SetDSPOpt() in DSP.h for a more detailed explantion of the options
	//
	// Thread safe:
	//    No, except when only changing the interpolation type
	//
	// In:
	//    mix   = Mixing routine (default MIX_INT)
	//    chn   = Number of channels (1 or 2, default 2)
	//    bits  = Sample size (8, 16, 24, 32, or -32 [IEEE 754], default 16)
	//    rate  = Sample rate (8000-192000, default 32000)
	//    inter = Interpolation type (default INT_GAUSS)
	//    opts  = See enum DSPOpts

	void SetAPUOpt(Mixing mix, u32 chn, u32 bits, u32 rate, DSPInter inter = INT_INVALID,
				   Set<DSPOpts> opts = ~Set<DSPOpts>());


	//**********************************************************************************************
	// Set Audio Processor Sample Clock
	//
	// Calculates the ratio of emulated clock cycles to sample output.  Used to speed up or slow
	// down a song without affecting the pitch.  Range checking is performed.
	//
	// This function is safe to call while the APU is emulated in another thread
	//
	// Thread safe:
	//    Yes
	//
	// In:
	//    speed = Multiplier [16.16] (1/16x to 16x)

	void SetAPUSmpClk(u32 speed);


	//**********************************************************************************************
	// Emulate Audio Processing Unit
	//
	// Emulates the APU for a specified amount of time.  DSP output is placed in a buffer to be
	// handled by the main program.
	//
	// Calling EmuAPU() instead of EmuSPC() and EmuDSP() will ensure the two processors are kept in
	// sync with each other.
	//
	// If the cycle count is 0, the SPC700 will be emulated until the DSP has filled the output
	// buffer with the specified number of samples.
	//
	// If the sample count is 0, the DSP will be produce output for the same amount of time as the
	// SPC700 is emulated.
	//
	// If the cycle count and sample count aren't equal in terms of time, then one processor will be
	// halted at the end of its count while the other processor is continued.
	//
	// In:
	//    pBuf   -> Buffer to store output samples (can be NULL)
	//    cycles  = Number of clock cycles to emulate SPC700 for (APU_CLK = 1 second)
	//    samples = Number of samples for the DSP to generate
	//
	// Out:
	//    -> End of buffer

	void* EmuAPU(void* pBuf, u32 cycles, u32 samples);


	//**********************************************************************************************
	// Seek to Position
	//
	// Seeks forward in the song from the current position
	//
	// In:
	//    time = 1/64000ths of a second to seek forward (must be >= 0)
	//    fast = Use faster seeking method (may break some songs)

	void SeekAPU(u32 time, bool fast);


	//**********************************************************************************************
	// Shutdown Audio Processing Unit
	//
	// Currently does nothing

	void ShutAPU();

}	// extern "C"

#endif	//!SNESAPU_DLL

}	// namespace SNES
}	// namespace A2