Mercurial > spc_convert
comparison snes_spc.txt @ 0:e38dacceb958
initial import
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 21 Oct 2011 05:53:11 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e38dacceb958 |
---|---|
1 snes_spc 0.9.0: SNES SPC-700 APU Emulator | |
2 ----------------------------------------- | |
3 Author : Shay Green <gblargg@gmail.com> | |
4 Website: http://www.slack.net/~ant/ | |
5 Forum : http://groups.google.com/group/blargg-sound-libs | |
6 License: GNU Lesser General Public License (LGPL) | |
7 | |
8 | |
9 Contents | |
10 -------- | |
11 * C and C++ Interfaces | |
12 * Overview | |
13 * Full SPC Emulation | |
14 * DSP Emulation | |
15 * SPC Music Playback | |
16 * State Copying | |
17 * Library Compilation | |
18 * Error handling | |
19 * Solving Problems | |
20 * Accurate S-DSP Limitations | |
21 * Fast S-DSP Limitations | |
22 * S-SMP Limitations | |
23 * To Do | |
24 * Thanks | |
25 | |
26 | |
27 C and C++ Interfaces | |
28 -------------------- | |
29 The library includes a C interface in spc.h and dsp.h, which can be used | |
30 from C and C++. This C interface is referred to in the following | |
31 documentation. If you're building this as a shared library (rather than | |
32 linking statically), you should use the C interface since it will change | |
33 less in future versions. | |
34 | |
35 The native C++ interface is in the header files SNES_SPC.h, SPC_DSP.h, | |
36 and SPC_Filter.h, and the two interfaces can be freely mixed in C++ | |
37 code. Conversion between the two interfaces generally follows a pattern: | |
38 | |
39 C interface C++ interface | |
40 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
41 SNES_SPC* spc; SNES_SPC* spc; | |
42 | |
43 spc = spc_new(); spc = new SNES_SPC; | |
44 | |
45 spc_play( spc, count, buf ); spc->play( count, buf ); | |
46 | |
47 spc_sample_rate SNES_SPC::sample_rate | |
48 | |
49 spc_delete( spc ); delete spc; | |
50 | |
51 | |
52 Overview | |
53 -------- | |
54 There are three main roles for this library: | |
55 * Full SPC emulation in a SNES emulator | |
56 * DSP emulation in a SNES emulator (where you emulate the SMP CPU) | |
57 * SPC playback in an SPC music file player | |
58 | |
59 Each of these uses are described separately below. | |
60 | |
61 | |
62 Full SPC Emulation | |
63 ------------------ | |
64 See spc.h for full function reference (SNES_SPC.h if using C++). | |
65 | |
66 * Create SPC emulator with spc_new() and check for NULL. | |
67 | |
68 * Call spc_init_rom() with a pointer to the 64-byte IPL ROM dump (not | |
69 included with library). | |
70 | |
71 * When your emulated SNES is powered on, call spc_reset(). When the | |
72 reset switch is pressed, call spc_soft_reset(). | |
73 | |
74 * Call spc_set_output() with your output buffer, then do emulation. | |
75 | |
76 * When the SNES CPU accesses APU ports, call spc_read_port() and | |
77 spc_write_port(). | |
78 | |
79 * When your emulator's timebase is going back to 0, call | |
80 spc_end_frame(), usually at the end of a video frame or scanline. | |
81 | |
82 * Periodically play samples from your buffer. Use spc_sample_count() to | |
83 find out how many samples have been written, then spc_set_output() after | |
84 you've made more space in your buffer. | |
85 | |
86 * Save/load full emulator state with spc_copy_state(). | |
87 | |
88 * You can save as an SPC music file with spc_save_spc(). | |
89 | |
90 * When done, use spc_delete() to free memory. | |
91 | |
92 | |
93 DSP Emulation | |
94 ------------- | |
95 See dsp.h for full function reference (SPC_DSP.h if using C++). | |
96 | |
97 * Create DSP emulator with spc_dsp_new() and check for NULL. | |
98 | |
99 * Let the DSP know where your 64K RAM is with spc_dsp_init(). | |
100 | |
101 * When your emulated SNES is powered on, call spc_dsp_reset(). When the | |
102 reset switch is pressed, call spc_dsp_soft_reset(). | |
103 | |
104 * Call spc_dsp_set_output() with your output buffer, then do emulation. | |
105 | |
106 * Use spc_dsp_run() to run DSP for specified number of clocks (1024000 | |
107 per second). Every 32 clocks a pair of samples is added to your output | |
108 buffer. | |
109 | |
110 * Use spc_dsp_read() and spc_dsp_write() to handle DSP reads/writes from | |
111 the S-SMP. Before calling these always catch the DSP up to present time | |
112 with spc_dsp_run(). | |
113 | |
114 * Periodically play samples from your buffer. Use spc_dsp_sample_count() | |
115 to find out how many samples have been written, then | |
116 spc_dsp_set_output() after you've made more space in your buffer. | |
117 | |
118 * Use spc_dsp_copy_state() to save/load full DSP state. | |
119 | |
120 * When done, use spc_delete() to free memory. | |
121 | |
122 | |
123 SPC Music Playback | |
124 ------------------ | |
125 See spc.h for full function reference (SNES_SPC.h if using C++). | |
126 | |
127 * Create SPC emulator with spc_new() and check for NULL. | |
128 | |
129 * Load SPC with spc_load_spc() and check for error. | |
130 | |
131 * Optionally cear echo buffer with spc_clear_echo(). Many SPCs have | |
132 garbage in echo buffer, which causes noise at the beginning. | |
133 | |
134 * Generate samples as needed with spc_play(). | |
135 | |
136 * When done, use spc_delete() to free memory. | |
137 | |
138 * For a more complete game music playback library, use Game_Music_Emu | |
139 | |
140 | |
141 State Copying | |
142 ------------- | |
143 The SPC and DSP modules include state save/load functions. They take a | |
144 pointer to a pointer to a buffer to store state, and a copy function. | |
145 This copy function can either copy data to the buffer or from it, | |
146 allowing state save and restore with the same library function. The | |
147 internal save state format allows for future expansion without making | |
148 previous save states unusable. | |
149 | |
150 The SPC save state format puts the most important parts first to make it | |
151 easier to manually examine. It's organized as follows: | |
152 | |
153 Offset Size Data | |
154 - - - - - - - - - - - - - - - - - - | |
155 0 $10000 SPC RAM | |
156 $10000 $10 SMP $F0-$FF registers | |
157 $10010 4 SMP $F4-$F8 output registers | |
158 $10014 2 PC | |
159 $10016 1 A | |
160 $10017 1 X | |
161 $10018 1 Y | |
162 $10019 1 PSW | |
163 $1001A 1 SP | |
164 $1001B 5 internal | |
165 $10020 $80 DSP registers | |
166 $100A0 ... internal | |
167 | |
168 | |
169 Library Compilation | |
170 ------------------- | |
171 While this library is in C++, it has been written to easily link in a C | |
172 program *without* needing the standard C++ library. It doesn't use | |
173 exception handling or run-time type information (RTTI), so you can | |
174 disable these in your C++ compiler to increase efficiency. | |
175 | |
176 If you're building a shared library (DLL), I recommend only exporting | |
177 the C interfaces in spc.h and dsp.h, as the C++ interfaces expose | |
178 implementation details that will break link compatibility across | |
179 versions. | |
180 | |
181 If you're using C and compiling with GCC, I recommend the following | |
182 command-line options when compiling the library source, otherwise GCC | |
183 will insert calls to the standard C++ library and require that it be | |
184 linked in: | |
185 | |
186 -fno-rtti -fno-exceptions | |
187 | |
188 For maximum optimization, see the NDEBUG and BLARGG_NONPORTABLE options | |
189 in blargg_config. If using GCC, you can enable these by adding the | |
190 following command-line options when you invoke gcc. If you encounter | |
191 problems, try without -DBLARGG_NONPORTABLE; if that works, contact me so | |
192 I can figure out why BLARGG_NONPORTABLE was causing it to fail. | |
193 | |
194 -O3 -DNDEBUG -DBLARGG_NONPORTABLE -fno-rtti -fno-exceptions | |
195 | |
196 | |
197 | |
198 Error handling | |
199 -------------- | |
200 Functions which can fail have a return type of spc_err_t (blargg_err_t | |
201 in the C++ interfaces), which is a pointer to an error string (const | |
202 char*). If a function is successful it returns NULL. Errors that you can | |
203 easily avoid are checked with debug assertions; spc_err_t return values | |
204 are only used for genuine run-time errors that can't be easily predicted | |
205 in advance (out of memory, I/O errors, incompatible file data). Your | |
206 code should check all error values. | |
207 | |
208 To improve usability for C programmers, C++ programmers unfamiliar with | |
209 exceptions, and compatibility with older C++ compilers, the library does | |
210 *not* throw any C++ exceptions and uses malloc() instead of the standard | |
211 operator new. This means that you *must* check for NULL when creating a | |
212 library object with the new operator. | |
213 | |
214 | |
215 Solving Problems | |
216 ---------------- | |
217 If you're having problems, try the following: | |
218 | |
219 * If you're getting garbled sound, try this simple siren generator in | |
220 place of your call to play(). This will quickly tell whether the problem | |
221 is in the library or in your code. | |
222 | |
223 static void play_siren( long count, short* out ) | |
224 { | |
225 static double a, a2; | |
226 while ( count-- ) | |
227 *out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) ); | |
228 } | |
229 | |
230 * Enable debugging support in your environment. This enables assertions | |
231 and other run-time checks. | |
232 | |
233 * Turn the compiler's optimizer is off. Sometimes an optimizer generates | |
234 bad code. | |
235 | |
236 * If multiple threads are being used, ensure that only one at a time is | |
237 accessing a given set of objects from the library. This library is not | |
238 in general thread-safe, though independent objects can be used in | |
239 separate threads. | |
240 | |
241 * If all else fails, see if the demos work. | |
242 | |
243 | |
244 Accurate S-DSP Limitations | |
245 -------------------------- | |
246 * Power-up and soft reset behavior might have slight inaccuracies. | |
247 | |
248 * Muting (FLG bit 6) behavior when toggling bit very rapidly is not | |
249 emulated properly. | |
250 | |
251 * No other known inaccuracies. Has passed 100+ strenuous tests. | |
252 | |
253 | |
254 Fast S-DSP Limitations | |
255 ---------------------- | |
256 * Uses faster sample calculations except in cases where exact value is | |
257 actually important (BRR decoding, and gaussian interpolation combined | |
258 with pitch modulation). | |
259 | |
260 * Stops decoding BRR data when a voice's envelope has released to | |
261 silence. | |
262 | |
263 * Emulates 32 clocks at a time, so DSP register and memory accesses are | |
264 all done in a bunch rather than spread out. Even though, some clever | |
265 code makes register accesses separated by 40 or so clocks occur with | |
266 cycle-accurate timing. | |
267 | |
268 | |
269 S-SMP Limitations | |
270 ----------------- | |
271 * Opcode fetches and indirect pointers are always read directly from | |
272 memory, even for the $F0-$FF region, and the DSP is not caught up for | |
273 these fetches. | |
274 | |
275 * Attempts to perversely execute data in registers or an area being | |
276 modified by echo will not be emulated properly. | |
277 | |
278 * Has not been thoroughly tested. | |
279 | |
280 * Test register ($F0) is not implemented. | |
281 | |
282 * Echo buffer can overwrite IPL ROM area, and does not correctly update | |
283 extra RAM there. | |
284 | |
285 | |
286 To Do | |
287 ----- | |
288 * I'd like feedback on the interface and any ways to improve it. In | |
289 particular, the differing features between the accurate and fast DSP | |
290 emulators might make it harder to cleanly switch between them without | |
291 modifying source code. | |
292 | |
293 * Finish thorough tests on SMP memory access times. | |
294 | |
295 * Finish thorough tests on SMP instruction behavior (flags, registers). | |
296 | |
297 * Finish thorough tests on SMP timers. | |
298 | |
299 * Finish power-up and reset behavior testing. | |
300 | |
301 * Come up with best starting conditions to play an SPC and implement in | |
302 hardware SNES SPC player for verification. | |
303 | |
304 | |
305 Thanks | |
306 ------ | |
307 Thanks to Anti-Resonance's SPC2ROM and help getting SPCs playing on my | |
308 SNES in the first place, then Brad Martin's openspc and Chris Moeller's | |
309 openspc++ C++ adaptation, giving me a good SPC emulator to start with | |
310 several years ago. Thanks to Richard Bannister, Mahendra Tallur, Shazz, | |
311 nenolod, theHobbit, Johan Samuelsson, nes6502, and Micket for helping | |
312 test my Game_Music_Emu library. Thanks to hcs for help in converting to | |
313 C for the Rockbox port. Thanks to byuu (bsnes author) and pagefault and | |
314 Nach (zsnes team) for testing and using my new rewritten DSP in their | |
315 emulators. Thanks to anomie for his good SNES documentation and | |
316 discussions with me to keep it up to date with my latest findings. | |
317 -- | |
318 Shay Green <gblargg@gmail.com> |