Mercurial > hg > xmms-sid
comparison src/xs_sidplay1.cpp @ 834:a7ee5dc23e78
Rename .cc -> .cpp.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 08 Nov 2012 20:47:05 +0200 |
parents | src/xs_sidplay1.cc@b158abe91a75 |
children | 5b3e2116408f |
comparison
equal
deleted
inserted
replaced
833:c0e892fa914a | 834:a7ee5dc23e78 |
---|---|
1 /* | |
2 XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) | |
3 | |
4 libSIDPlay v1 support | |
5 | |
6 Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> | |
7 (C) Copyright 1999-2007 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 along | |
20 with this program; if not, write to the Free Software Foundation, Inc., | |
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
22 */ | |
23 #include "xmms-sid.h" | |
24 | |
25 #ifdef HAVE_SIDPLAY1 | |
26 | |
27 #include "xs_sidplay1.h" | |
28 #include "xs_slsup.h" | |
29 #include "xs_config.h" | |
30 | |
31 #include <sidplay/player.h> | |
32 #include <sidplay/myendian.h> | |
33 #include <sidplay/fformat.h> | |
34 | |
35 | |
36 /* Maximum audio frequency supported by libSIDPlay v1 */ | |
37 #define SIDPLAY1_MAX_FREQ (48000) | |
38 | |
39 | |
40 typedef struct { | |
41 emuEngine *emu; | |
42 emuConfig currConfig; | |
43 sidTune *tune; | |
44 guint8 *buf; | |
45 size_t bufSize; | |
46 } XSSIDPlay1; | |
47 | |
48 | |
49 /* We need to 'export' all this pseudo-C++ crap */ | |
50 extern "C" { | |
51 | |
52 | |
53 /* Return song information | |
54 */ | |
55 #define TFUNCTION xs_sidplay1_getinfo | |
56 #define TFUNCTION2 xs_sidplay1_updateinfo | |
57 #define TTUNEINFO sidTuneInfo | |
58 #define TTUNE sidTune | |
59 #define TENGINE XSSIDPlay1 | |
60 #include "xs_sidplay.h" | |
61 | |
62 | |
63 /* Check if we can play the given file | |
64 */ | |
65 gboolean xs_sidplay1_probe(XSFile *f) | |
66 { | |
67 gchar tmpBuf[4]; | |
68 | |
69 if (!f) return FALSE; | |
70 | |
71 if (xs_fread(tmpBuf, sizeof(gchar), 4, f) != 4) | |
72 return FALSE; | |
73 | |
74 if (!strncmp(tmpBuf, "PSID", 4)) | |
75 return TRUE; | |
76 else | |
77 return FALSE; | |
78 } | |
79 | |
80 | |
81 /* Initialize SIDPlay1 | |
82 */ | |
83 gboolean xs_sidplay1_init(XSEngineState * state) | |
84 { | |
85 gint tmpFreq; | |
86 XSSIDPlay1 *engine; | |
87 assert(state); | |
88 | |
89 /* Allocate internal structures */ | |
90 engine = (XSSIDPlay1 *) g_malloc0(sizeof(XSSIDPlay1)); | |
91 if (!engine) return FALSE; | |
92 | |
93 /* Initialize engine */ | |
94 engine->emu = new emuEngine(); | |
95 if (!engine->emu) { | |
96 xs_error("[SIDPlay1] Could not initialize emulation engine.\n"); | |
97 g_free(engine); | |
98 return FALSE; | |
99 } | |
100 | |
101 /* Verify endianess */ | |
102 if (!engine->emu->verifyEndianess()) { | |
103 xs_error("[SIDPlay1] Endianess verification failed.\n"); | |
104 delete engine->emu; | |
105 g_free(engine); | |
106 return FALSE; | |
107 } | |
108 | |
109 state->internal = engine; | |
110 | |
111 /* Get current configuration */ | |
112 engine->emu->getConfig(engine->currConfig); | |
113 | |
114 /* Configure channel parameters */ | |
115 switch (state->audioChannels) { | |
116 | |
117 case XS_CHN_AUTOPAN: | |
118 engine->currConfig.channels = SIDEMU_STEREO; | |
119 engine->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING; | |
120 engine->currConfig.volumeControl = SIDEMU_FULLPANNING; | |
121 break; | |
122 | |
123 case XS_CHN_STEREO: | |
124 engine->currConfig.channels = SIDEMU_STEREO; | |
125 engine->currConfig.autoPanning = SIDEMU_NONE; | |
126 engine->currConfig.volumeControl = SIDEMU_NONE; | |
127 break; | |
128 | |
129 case XS_CHN_MONO: | |
130 default: | |
131 engine->currConfig.channels = SIDEMU_MONO; | |
132 engine->currConfig.autoPanning = SIDEMU_NONE; | |
133 engine->currConfig.volumeControl = SIDEMU_NONE; | |
134 state->audioChannels = XS_CHN_MONO; | |
135 break; | |
136 } | |
137 | |
138 | |
139 /* Memory mode settings */ | |
140 switch (xs_cfg.memoryMode) { | |
141 case XS_MPU_TRANSPARENT_ROM: | |
142 engine->currConfig.memoryMode = MPU_TRANSPARENT_ROM; | |
143 break; | |
144 | |
145 case XS_MPU_PLAYSID_ENVIRONMENT: | |
146 engine->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT; | |
147 break; | |
148 | |
149 case XS_MPU_BANK_SWITCHING: | |
150 default: | |
151 engine->currConfig.memoryMode = MPU_BANK_SWITCHING; | |
152 xs_cfg.memoryMode = XS_MPU_BANK_SWITCHING; | |
153 break; | |
154 } | |
155 | |
156 | |
157 /* Audio parameters sanity checking and setup */ | |
158 engine->currConfig.bitsPerSample = state->audioBitsPerSample; | |
159 tmpFreq = state->audioFrequency; | |
160 | |
161 if (tmpFreq > SIDPLAY1_MAX_FREQ) | |
162 tmpFreq = SIDPLAY1_MAX_FREQ; | |
163 | |
164 engine->currConfig.frequency = tmpFreq; | |
165 | |
166 switch (state->audioBitsPerSample) { | |
167 case XS_RES_8BIT: | |
168 switch (state->audioFormat) { | |
169 case FMT_S8: | |
170 state->audioFormat = FMT_S8; | |
171 engine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM; | |
172 break; | |
173 | |
174 case FMT_U8: | |
175 default: | |
176 state->audioFormat = FMT_U8; | |
177 engine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM; | |
178 break; | |
179 } | |
180 break; | |
181 | |
182 case XS_RES_16BIT: | |
183 default: | |
184 switch (state->audioFormat) { | |
185 case FMT_U16_NE: | |
186 case FMT_U16_LE: | |
187 case FMT_U16_BE: | |
188 state->audioFormat = FMT_U16_NE; | |
189 engine->currConfig.sampleFormat = SIDEMU_UNSIGNED_PCM; | |
190 break; | |
191 | |
192 case FMT_S16_NE: | |
193 case FMT_S16_LE: | |
194 case FMT_S16_BE: | |
195 default: | |
196 state->audioFormat = FMT_S16_NE; | |
197 engine->currConfig.sampleFormat = SIDEMU_SIGNED_PCM; | |
198 break; | |
199 } | |
200 break; | |
201 } | |
202 | |
203 /* Clockspeed settings */ | |
204 switch (xs_cfg.clockSpeed) { | |
205 case XS_CLOCK_NTSC: | |
206 engine->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC; | |
207 break; | |
208 | |
209 case XS_CLOCK_PAL: | |
210 default: | |
211 engine->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL; | |
212 xs_cfg.clockSpeed = XS_CLOCK_PAL; | |
213 break; | |
214 } | |
215 | |
216 engine->currConfig.forceSongSpeed = xs_cfg.forceSpeed; | |
217 | |
218 | |
219 /* Configure rest of the emulation */ | |
220 /* if (xs_cfg.forceModel) */ | |
221 engine->currConfig.mos8580 = xs_cfg.mos8580; | |
222 engine->currConfig.emulateFilter = xs_cfg.emulateFilters; | |
223 engine->currConfig.filterFs = xs_cfg.sid1Filter.fs; | |
224 engine->currConfig.filterFm = xs_cfg.sid1Filter.fm; | |
225 engine->currConfig.filterFt = xs_cfg.sid1Filter.ft; | |
226 | |
227 | |
228 /* Now set the emulator configuration */ | |
229 if (!engine->emu->setConfig(engine->currConfig)) { | |
230 xs_error("[SIDPlay1] Emulator engine configuration failed!\n"); | |
231 return FALSE; | |
232 } | |
233 | |
234 /* Create sidtune object */ | |
235 engine->tune = new sidTune(0); | |
236 if (!engine->tune) { | |
237 xs_error("[SIDPlay1] Could not initialize SIDTune object.\n"); | |
238 return FALSE; | |
239 } | |
240 | |
241 return TRUE; | |
242 } | |
243 | |
244 | |
245 /* Close SIDPlay1 engine | |
246 */ | |
247 void xs_sidplay1_close(XSEngineState * state) | |
248 { | |
249 XSSIDPlay1 *engine; | |
250 assert(state); | |
251 | |
252 engine = (XSSIDPlay1 *) state->internal; | |
253 | |
254 /* Free internals */ | |
255 if (engine->emu) { | |
256 delete engine->emu; | |
257 engine->emu = NULL; | |
258 } | |
259 | |
260 if (engine->tune) { | |
261 delete engine->tune; | |
262 engine->tune = NULL; | |
263 } | |
264 | |
265 xs_sidplay1_delete(state); | |
266 | |
267 g_free(engine); | |
268 state->internal = NULL; | |
269 } | |
270 | |
271 | |
272 /* Initialize current song and sub-tune | |
273 */ | |
274 gboolean xs_sidplay1_initsong(XSEngineState * state) | |
275 { | |
276 XSSIDPlay1 *engine; | |
277 assert(state); | |
278 | |
279 engine = (XSSIDPlay1 *) state->internal; | |
280 if (!engine) return FALSE; | |
281 | |
282 if (!engine->tune) { | |
283 xs_error("[SIDPlay1] SID-tune struct pointer was NULL. This should not happen, report to XMMS-SID author.\n"); | |
284 return FALSE; | |
285 } | |
286 | |
287 if (!engine->tune->getStatus()) { | |
288 xs_error("[SIDPlay1] SID-tune status check failed. This should not happen, report to XMMS-SID author.\n"); | |
289 return FALSE; | |
290 } | |
291 | |
292 return sidEmuInitializeSong(*engine->emu, *engine->tune, state->currSong); | |
293 } | |
294 | |
295 | |
296 /* Emulate and render audio data to given buffer | |
297 */ | |
298 guint xs_sidplay1_fillbuffer(XSEngineState * state, gchar * audioBuffer, guint audioBufSize) | |
299 { | |
300 XSSIDPlay1 *engine; | |
301 assert(state); | |
302 | |
303 engine = (XSSIDPlay1 *) state->internal; | |
304 if (!engine) return 0; | |
305 | |
306 sidEmuFillBuffer(*engine->emu, *engine->tune, audioBuffer, audioBufSize); | |
307 | |
308 return audioBufSize; | |
309 } | |
310 | |
311 | |
312 /* Load a given SID-tune file | |
313 */ | |
314 gboolean xs_sidplay1_load(XSEngineState * state, gchar * filename) | |
315 { | |
316 XSSIDPlay1 *engine; | |
317 assert(state); | |
318 | |
319 engine = (XSSIDPlay1 *) state->internal; | |
320 if (!engine) return FALSE; | |
321 | |
322 /* Try to get the tune */ | |
323 if (!filename) return FALSE; | |
324 | |
325 if (xs_fload_buffer(filename, &(engine->buf), &(engine->bufSize)) != 0) | |
326 return FALSE; | |
327 | |
328 if (!engine->tune->load(engine->buf, engine->bufSize)) | |
329 return FALSE; | |
330 | |
331 return TRUE; | |
332 } | |
333 | |
334 | |
335 /* Delete INTERNAL information | |
336 */ | |
337 void xs_sidplay1_delete(XSEngineState * state) | |
338 { | |
339 XSSIDPlay1 *engine; | |
340 assert(state); | |
341 | |
342 engine = (XSSIDPlay1 *) state->internal; | |
343 if (!engine) return; | |
344 | |
345 g_free(engine->buf); | |
346 engine->buf = NULL; | |
347 engine->bufSize = 0; | |
348 } | |
349 | |
350 | |
351 } /* extern "C" */ | |
352 #endif /* HAVE_SIDPLAY1 */ |