Mercurial > audlegacy-plugins
comparison src/sid/xs_sidplay2.cc @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/sid/xs_sidplay2.cc@13389e613d67 |
children | c488d191b528 |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
1 /* | |
2 XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) | |
3 | |
4 libSIDPlay v2 support | |
5 | |
6 Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> | |
7 (C) Copyright 1999-2005 Tecnic Software productions (TNSP) | |
8 | |
9 This program is free software; you can redistribute it and/or modify | |
10 it under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; either version 2 of the License, or | |
12 (at your option) any later version. | |
13 | |
14 This program is distributed in the hope that it will be useful, | |
15 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 GNU General Public License for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with this program; if not, write to the Free Software | |
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
22 */ | |
23 #include "xmms-sid.h" | |
24 | |
25 #ifdef HAVE_SIDPLAY2 | |
26 | |
27 #include "xs_sidplay2.h" | |
28 #include <stdio.h> | |
29 #include "xs_config.h" | |
30 #include "xs_support.h" | |
31 #include "xs_length.h" | |
32 #include "xs_title.h" | |
33 | |
34 #include <sidplay/sidplay2.h> | |
35 #ifdef HAVE_RESID_BUILDER | |
36 #include <sidplay/builders/resid.h> | |
37 #endif | |
38 #ifdef HAVE_HARDSID_BUILDER | |
39 #include <sidplay/builders/hardsid.h> | |
40 #endif | |
41 | |
42 | |
43 typedef struct | |
44 { | |
45 sidplay2 *currEng; | |
46 sidbuilder *currBuilder; | |
47 sid2_config_t currConfig; | |
48 SidTune *currTune; | |
49 } t_xs_sidplay2; | |
50 | |
51 | |
52 /* We need to 'export' all this pseudo-C++ crap */ | |
53 extern "C" | |
54 { | |
55 | |
56 | |
57 /* Check if we can play the given file | |
58 */ | |
59 gboolean xs_sidplay2_isourfile(gchar * pcFilename) | |
60 { | |
61 SidTune *testTune = new SidTune(pcFilename); | |
62 | |
63 if (!testTune) return FALSE; | |
64 | |
65 if (!testTune->getStatus()) { | |
66 delete testTune; | |
67 return FALSE; | |
68 } | |
69 | |
70 delete testTune; | |
71 return TRUE; | |
72 } | |
73 | |
74 | |
75 | |
76 /* Initialize SIDPlay2 | |
77 */ | |
78 gboolean xs_sidplay2_init(t_xs_status * myStatus) | |
79 { | |
80 gint tmpFreq; | |
81 t_xs_sidplay2 *myEngine; | |
82 assert(myStatus); | |
83 | |
84 /* Allocate internal structures */ | |
85 myEngine = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2)); | |
86 myStatus->sidEngine = myEngine; | |
87 if (!myEngine) return FALSE; | |
88 | |
89 /* Initialize the engine */ | |
90 myEngine->currEng = new sidplay2; | |
91 if (!myEngine->currEng) { | |
92 XSERR("Could not initialize libSIDPlay2 emulation engine\n"); | |
93 return FALSE; | |
94 } | |
95 | |
96 /* Get current configuration */ | |
97 myEngine->currConfig = myEngine->currEng->config(); | |
98 | |
99 /* Configure channels and stuff */ | |
100 switch (myStatus->audioChannels) { | |
101 | |
102 case XS_CHN_AUTOPAN: | |
103 myEngine->currConfig.playback = sid2_stereo; | |
104 break; | |
105 | |
106 case XS_CHN_STEREO: | |
107 myEngine->currConfig.playback = sid2_stereo; | |
108 break; | |
109 | |
110 case XS_CHN_MONO: | |
111 default: | |
112 myEngine->currConfig.playback = sid2_mono; | |
113 myStatus->audioChannels = XS_CHN_MONO; | |
114 break; | |
115 } | |
116 | |
117 | |
118 /* Memory mode settings */ | |
119 switch (xs_cfg.memoryMode) { | |
120 case XS_MPU_BANK_SWITCHING: | |
121 myEngine->currConfig.environment = sid2_envBS; | |
122 break; | |
123 | |
124 case XS_MPU_TRANSPARENT_ROM: | |
125 myEngine->currConfig.environment = sid2_envTP; | |
126 break; | |
127 | |
128 case XS_MPU_PLAYSID_ENVIRONMENT: | |
129 myEngine->currConfig.environment = sid2_envPS; | |
130 break; | |
131 | |
132 case XS_MPU_REAL: | |
133 default: | |
134 myEngine->currConfig.environment = sid2_envR; | |
135 xs_cfg.memoryMode = XS_MPU_REAL; | |
136 break; | |
137 } | |
138 | |
139 | |
140 /* Audio parameters sanity checking and setup */ | |
141 myEngine->currConfig.precision = myStatus->audioBitsPerSample; | |
142 tmpFreq = myStatus->audioFrequency; | |
143 | |
144 if (myStatus->oversampleEnable) | |
145 tmpFreq = (tmpFreq * myStatus->oversampleFactor); | |
146 | |
147 myEngine->currConfig.frequency = tmpFreq; | |
148 | |
149 switch (myStatus->audioBitsPerSample) { | |
150 case XS_RES_8BIT: | |
151 myStatus->audioFormat = FMT_U8; | |
152 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | |
153 break; | |
154 | |
155 case XS_RES_16BIT: | |
156 default: | |
157 switch (myStatus->audioFormat) { | |
158 case FMT_U16_LE: | |
159 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | |
160 break; | |
161 | |
162 case FMT_U16_BE: | |
163 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; | |
164 break; | |
165 | |
166 case FMT_U16_NE: | |
167 #ifdef WORDS_BIGENDIAN | |
168 myEngine->currConfig.sampleFormat = SID2_BIG_UNSIGNED; | |
169 #else | |
170 myEngine->currConfig.sampleFormat = SID2_LITTLE_UNSIGNED; | |
171 #endif | |
172 break; | |
173 | |
174 case FMT_S16_LE: | |
175 myEngine->currConfig.sampleFormat = SID2_LITTLE_SIGNED; | |
176 break; | |
177 | |
178 case FMT_S16_BE: | |
179 myEngine->currConfig.sampleFormat = SID2_BIG_SIGNED; | |
180 break; | |
181 | |
182 default: | |
183 myStatus->audioFormat = FMT_S16_NE; | |
184 #ifdef WORDS_BIGENDIAN | |
185 myEngine->currConfig.sampleFormat = SID2_BIG_SIGNED; | |
186 #else | |
187 myEngine->currConfig.sampleFormat = SID2_LITTLE_SIGNED; | |
188 #endif | |
189 break; | |
190 | |
191 } | |
192 break; | |
193 } | |
194 | |
195 /* Initialize builder object */ | |
196 XSDEBUG("init builder #%i, maxsids=%i\n", xs_cfg.sid2Builder, (myEngine->currEng->info()).maxsids); | |
197 #ifdef HAVE_RESID_BUILDER | |
198 if (xs_cfg.sid2Builder == XS_BLD_RESID) { | |
199 ReSIDBuilder *rs = new ReSIDBuilder("ReSID builder"); | |
200 myEngine->currBuilder = (sidbuilder *) rs; | |
201 if (rs) { | |
202 /* Builder object created, initialize it */ | |
203 rs->create((myEngine->currEng->info()).maxsids); | |
204 if (!*rs) { | |
205 XSERR("rs->create() failed. SIDPlay2 suxx again.\n"); | |
206 return FALSE; | |
207 } | |
208 | |
209 rs->filter(xs_cfg.emulateFilters); | |
210 if (!*rs) { | |
211 XSERR("rs->filter(%d) failed.\n", xs_cfg.emulateFilters); | |
212 return FALSE; | |
213 } | |
214 | |
215 rs->sampling(tmpFreq); | |
216 if (!*rs) { | |
217 XSERR("rs->sampling(%d) failed.\n", tmpFreq); | |
218 return FALSE; | |
219 } | |
220 | |
221 rs->filter((sid_filter_t *) NULL); | |
222 if (!*rs) { | |
223 XSERR("rs->filter(NULL) failed.\n"); | |
224 return FALSE; | |
225 } | |
226 } | |
227 } | |
228 #endif | |
229 #ifdef HAVE_HARDSID_BUILDER | |
230 if (xs_cfg.sid2Builder == XS_BLD_HARDSID) { | |
231 HardSIDBuilder *hs = new HardSIDBuilder("HardSID builder"); | |
232 myEngine->currBuilder = (sidbuilder *) hs; | |
233 if (hs) { | |
234 /* Builder object created, initialize it */ | |
235 hs->create((myEngine->currEng->info()).maxsids); | |
236 if (!*hs) { | |
237 XSERR("hs->create() failed. SIDPlay2 suxx again.\n"); | |
238 return FALSE; | |
239 } | |
240 | |
241 hs->filter(xs_cfg.emulateFilters); | |
242 if (!*hs) { | |
243 XSERR("hs->filter(%d) failed.\n", xs_cfg.emulateFilters); | |
244 return FALSE; | |
245 } | |
246 } | |
247 } | |
248 #endif | |
249 | |
250 if (!myEngine->currBuilder) { | |
251 XSERR("Could not initialize SIDBuilder object.\n"); | |
252 return FALSE; | |
253 } | |
254 | |
255 XSDEBUG("%s\n", myEngine->currBuilder->credits()); | |
256 | |
257 | |
258 /* Clockspeed settings */ | |
259 switch (xs_cfg.clockSpeed) { | |
260 case XS_CLOCK_NTSC: | |
261 myEngine->currConfig.clockDefault = SID2_CLOCK_NTSC; | |
262 break; | |
263 | |
264 case XS_CLOCK_PAL: | |
265 default: | |
266 myEngine->currConfig.clockDefault = SID2_CLOCK_PAL; | |
267 xs_cfg.clockSpeed = XS_CLOCK_PAL; | |
268 break; | |
269 } | |
270 | |
271 | |
272 /* Configure rest of the emulation */ | |
273 myEngine->currConfig.sidEmulation = myEngine->currBuilder; | |
274 | |
275 if (xs_cfg.forceSpeed) { | |
276 myEngine->currConfig.clockForced = true; | |
277 myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault; | |
278 } else { | |
279 myEngine->currConfig.clockForced = false; | |
280 myEngine->currConfig.clockSpeed = SID2_CLOCK_CORRECT; | |
281 } | |
282 | |
283 if (xs_cfg.sid2OptLevel) | |
284 myEngine->currConfig.optimisation = 1; | |
285 else | |
286 myEngine->currConfig.optimisation = 0; | |
287 | |
288 if (xs_cfg.mos8580) | |
289 myEngine->currConfig.sidDefault = SID2_MOS8580; | |
290 else | |
291 myEngine->currConfig.sidDefault = SID2_MOS6581; | |
292 | |
293 if (xs_cfg.forceModel) | |
294 myEngine->currConfig.sidModel = myEngine->currConfig.sidDefault; | |
295 else | |
296 myEngine->currConfig.sidModel = SID2_MODEL_CORRECT; | |
297 | |
298 myEngine->currConfig.sidSamples = TRUE; // FIXME FIX ME, make configurable! | |
299 | |
300 | |
301 /* Now set the emulator configuration */ | |
302 if (myEngine->currEng->config(myEngine->currConfig) < 0) { | |
303 XSERR("Emulator engine configuration failed!\n"); | |
304 return FALSE; | |
305 } | |
306 | |
307 /* Create the sidtune */ | |
308 myEngine->currTune = new SidTune(0); | |
309 if (!myEngine->currTune) { | |
310 XSERR("Could not initialize SIDTune object.\n"); | |
311 return FALSE; | |
312 } | |
313 | |
314 return TRUE; | |
315 } | |
316 | |
317 | |
318 /* Close SIDPlay2 engine | |
319 */ | |
320 void xs_sidplay2_close(t_xs_status * myStatus) | |
321 { | |
322 t_xs_sidplay2 *myEngine; | |
323 assert(myStatus); | |
324 | |
325 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
326 | |
327 /* Free internals */ | |
328 if (myEngine->currBuilder) { | |
329 delete myEngine->currBuilder; | |
330 myEngine->currBuilder = NULL; | |
331 } | |
332 | |
333 if (myEngine->currEng) { | |
334 delete myEngine->currEng; | |
335 myEngine->currEng = NULL; | |
336 } | |
337 | |
338 if (myEngine->currTune) { | |
339 delete myEngine->currTune; | |
340 myEngine->currTune = NULL; | |
341 } | |
342 | |
343 xs_sidplay2_deletesid(myStatus); | |
344 | |
345 g_free(myEngine); | |
346 myStatus->sidEngine = NULL; | |
347 } | |
348 | |
349 | |
350 /* Initialize current song and sub-tune | |
351 */ | |
352 gboolean xs_sidplay2_initsong(t_xs_status * myStatus) | |
353 { | |
354 t_xs_sidplay2 *myEngine; | |
355 assert(myStatus); | |
356 | |
357 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
358 if (!myEngine) return FALSE; | |
359 | |
360 if (!myEngine->currTune->selectSong(myStatus->currSong)) { | |
361 XSERR("currTune->selectSong() failed\n"); | |
362 return FALSE; | |
363 } | |
364 | |
365 if (myEngine->currEng->load(myEngine->currTune) < 0) { | |
366 XSERR("currEng->load() failed\n"); | |
367 return FALSE; | |
368 } | |
369 | |
370 return TRUE; | |
371 } | |
372 | |
373 | |
374 /* Emulate and render audio data to given buffer | |
375 */ | |
376 guint xs_sidplay2_fillbuffer(t_xs_status * myStatus, gchar * audioBuffer, guint audioBufSize) | |
377 { | |
378 t_xs_sidplay2 *myEngine; | |
379 assert(myStatus); | |
380 | |
381 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
382 if (!myEngine) return 0; | |
383 | |
384 return myEngine->currEng->play(audioBuffer, audioBufSize); | |
385 } | |
386 | |
387 | |
388 /* Load a given SID-tune file | |
389 */ | |
390 gboolean xs_sidplay2_loadsid(t_xs_status * myStatus, gchar * pcFilename) | |
391 { | |
392 t_xs_sidplay2 *myEngine; | |
393 assert(myStatus); | |
394 | |
395 myEngine = (t_xs_sidplay2 *) myStatus->sidEngine; | |
396 if (!myEngine) return FALSE; | |
397 | |
398 /* Try to get the tune */ | |
399 if (!pcFilename) return FALSE; | |
400 | |
401 if (!myEngine->currTune->load(pcFilename)) | |
402 return FALSE; | |
403 | |
404 return TRUE; | |
405 } | |
406 | |
407 | |
408 /* Delete INTERNAL information | |
409 */ | |
410 void xs_sidplay2_deletesid(t_xs_status * myStatus) | |
411 { | |
412 assert(myStatus); | |
413 | |
414 /* With the current scheme of handling sidtune-loading, we don't do anything here. */ | |
415 } | |
416 | |
417 | |
418 /* Return song information | |
419 */ | |
420 #define TFUNCTION xs_sidplay2_getsidinfo | |
421 #define TTUNEINFO SidTuneInfo | |
422 #define TTUNE SidTune | |
423 #include "xs_sidplay.h" | |
424 | |
425 } /* extern "C" */ | |
426 #endif /* HAVE_SIDPLAY2 */ |