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 */