Mercurial > hg > dmlib
annotate tools/xm2jss.c @ 797:f066e9dccf29
Oops, fix some inverted booleans.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 18 Oct 2013 19:51:38 +0300 |
parents | 97ecc0a9c21f |
children | 422f85db78fd |
rev | line source |
---|---|
0 | 1 /* |
2 * xm2jss - Convert XM module to JSSMOD | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2006-2009 Tecnic Software productions (TNSP) | |
5 * | |
6 * Please read file 'COPYING' for information on license and distribution. | |
7 */ | |
8 #include <stdio.h> | |
9 #include <errno.h> | |
10 #include "jss.h" | |
11 #include "jssmod.h" | |
184
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
12 #include "jssplr.h" |
0 | 13 #include "dmlib.h" |
14 #include "dmargs.h" | |
15 #include "dmres.h" | |
285
245b15cd1919
Don't link libSDL uselessly to utilities that do not actually use it.
Matti Hamalainen <ccr@tnsp.org>
parents:
202
diff
changeset
|
16 #include "dmmutex.h" |
245b15cd1919
Don't link libSDL uselessly to utilities that do not actually use it.
Matti Hamalainen <ccr@tnsp.org>
parents:
202
diff
changeset
|
17 |
0 | 18 |
184
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
19 #define jmpNMODEffectTable (36) |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
20 static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
21 |
0 | 22 |
300 | 23 char *optInFilename = NULL, *optOutFilename = NULL; |
0 | 24 BOOL optIgnoreErrors = FALSE, |
25 optStripExtInstr = FALSE, | |
26 optStripInstr = FALSE, | |
27 optStripSamples = FALSE, | |
28 optOptimize = FALSE; | |
29 | |
30 int optPatternMode = PATMODE_COMP_HORIZ, | |
31 optSampMode16 = jsampDelta, | |
32 optSampMode8 = jsampFlipSign | jsampDelta; | |
33 | |
34 #define SAMPMODE_MASK (jsampFlipSign | jsampSwapEndianess | jsampSplit | jsampDelta) | |
35 | |
36 | |
37 static const char* patModeTable[PATMODE_LAST] = | |
38 { | |
39 "Raw horizontal", | |
40 "Compressed horizontal (similar to XM modules)", | |
41 "Raw vertical", | |
42 "Compressed vertical", | |
43 "Raw vertical for each element", | |
44 }; | |
45 | |
46 | |
47 DMOptArg optList[] = { | |
48 { 0, '?', "help", "Show this help", OPT_NONE }, | |
337 | 49 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, |
50 { 2, 'i', "ignore", "Ignore errors", OPT_NONE }, | |
51 { 3, 'p', "patterns", "Pattern storage mode", OPT_ARGREQ }, | |
52 { 4, 'E', "strip-ext-instr","Strip ext. instruments (implies -I -S)", OPT_NONE }, | |
53 { 5, 'I', "strip-instr", "Strip instruments (implies -S)", OPT_NONE }, | |
54 { 6, 'S', "strip-samples", "Strip instr. sampledata", OPT_NONE }, | |
0 | 55 { 7, '8', "smode8", "8-bit sample conversion flags", OPT_ARGREQ }, |
56 { 8, '1', "smode16", "16-bit sample conversion flags", OPT_ARGREQ }, | |
337 | 57 { 9, 'O', "optimize", "Optimize module", OPT_NONE }, |
0 | 58 }; |
59 | |
60 const int optListN = sizeof(optList) / sizeof(optList[0]); | |
61 | |
62 | |
63 void argShowHelp() | |
64 { | |
65 int i; | |
66 | |
337 | 67 dmPrintBanner(stdout, dmProgName, "[options] <input.xm> <output.jmod>"); |
0 | 68 dmArgsPrintHelp(stdout, optList, optListN); |
69 | |
70 printf("\n" | |
71 "Pattern storage modes:\n"); | |
72 | |
73 for (i = 1; i < PATMODE_LAST; i++) | |
74 printf(" %d = %s\n", i, patModeTable[i-1]); | |
75 | |
76 printf( | |
77 "\n" | |
78 "Sample data conversion flags (summative):\n" | |
79 " 1 = Delta encoding (DEF 8 & 16)\n" | |
80 " 2 = Flip signedness (DEF 8)\n" | |
81 " 4 = Swap endianess (affects 16-bit only)\n" | |
82 " 8 = Split and de-interleave hi/lo bytes (affects 16-bit only)\n" | |
83 "\n" | |
84 ); | |
85 } | |
86 | |
87 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) | |
88 { | |
89 (void) optArg; | |
90 | |
91 switch (optN) | |
92 { | |
93 case 0: | |
94 argShowHelp(); | |
95 exit(0); | |
96 break; | |
97 | |
98 case 1: | |
337 | 99 dmVerbosity++; |
100 break; | |
101 | |
102 case 2: | |
0 | 103 optIgnoreErrors = TRUE; |
104 break; | |
105 | |
337 | 106 case 3: |
0 | 107 optPatternMode = atoi(optArg); |
108 if (optPatternMode <= 0 || optPatternMode >= PATMODE_LAST) | |
109 { | |
110 dmError("Unknown pattern conversion mode %d\n", optPatternMode); | |
111 return FALSE; | |
112 } | |
113 break; | |
114 | |
337 | 115 case 4: optStripExtInstr = TRUE; break; |
116 case 5: optStripInstr = TRUE; break; | |
117 case 6: optStripSamples = TRUE; break; | |
118 | |
0 | 119 case 7: optSampMode8 = atoi(optArg) & SAMPMODE_MASK; break; |
120 case 8: optSampMode16 = atoi(optArg) & SAMPMODE_MASK; break; | |
121 | |
337 | 122 case 9: optOptimize = TRUE; break; |
0 | 123 |
124 default: | |
125 dmError("Unknown argument '%s'.\n", currArg); | |
126 return FALSE; | |
127 } | |
128 | |
129 return TRUE; | |
130 } | |
131 | |
132 | |
133 BOOL argHandleFile(char *currArg) | |
134 { | |
135 // Was not option argument | |
300 | 136 if (!optInFilename) |
137 optInFilename = currArg; | |
337 | 138 else |
300 | 139 if (!optOutFilename) |
140 optOutFilename = currArg; | |
0 | 141 else |
142 { | |
300 | 143 dmError("Too many filename arguments specified, '%s'.\n", currArg); |
0 | 144 return FALSE; |
145 } | |
146 | |
147 return TRUE; | |
148 } | |
149 | |
150 | |
151 /* These functions and the macro mess are meant to make the | |
152 * conversion routines themselves clearer and simpler. | |
153 */ | |
154 BOOL jsPutByte(Uint8 *patBuf, size_t patBufSize, size_t *npatBuf, Uint8 val) | |
155 { | |
156 if (*npatBuf >= patBufSize) | |
157 return FALSE; | |
158 else | |
159 { | |
160 patBuf[*npatBuf] = val; | |
161 (*npatBuf)++; | |
162 return TRUE; | |
163 } | |
164 } | |
165 | |
166 #define JSPUTBYTE(x) do { if (!jsPutByte(patBuf, patBufSize, patSize, x)) return DMERR_BOUNDS; } while (0) | |
167 | |
168 #define JSCOMP(x,z) do { if ((x) != jsetNotSet) { qflags |= (z); qcomp++; } } while (0) | |
169 | |
170 #define JSCOMPPUT(xf,xv,qv) do { \ | |
171 if (qflags & (xf)) { \ | |
172 if ((xv) < 0 || (xv) > 255) \ | |
173 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, \ | |
174 "%s value out of bounds %d.\n", qv, (xv)); \ | |
175 JSPUTBYTE(xv); \ | |
176 } \ | |
177 } while (0) | |
178 | |
179 #define JSCONVPUT(xv,qv) do { \ | |
180 if ((xv) != jsetNotSet) { \ | |
181 if ((xv) < 0 || (xv) > 254) \ | |
182 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, \ | |
183 "%s value out of bounds %d.\n", qv, (xv)); \ | |
184 JSPUTBYTE((xv) + 1); \ | |
185 } else { \ | |
186 JSPUTBYTE(0); \ | |
187 } \ | |
188 } while (0) | |
189 | |
190 | |
191 /* Convert a note | |
192 */ | |
193 static int jssConvertNote(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSNote *note) | |
194 { | |
195 Uint8 tmp; | |
196 if (note->note == jsetNotSet) | |
197 tmp = 0; | |
198 else if (note->note == jsetNoteOff) | |
199 tmp = 127; | |
200 else | |
201 tmp = note->note + 1; | |
202 | |
203 if (tmp > 0x7f) | |
204 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, "Note value out of bounds %d > 0x7f.\n", tmp); | |
205 | |
206 JSPUTBYTE(tmp & 0x7f); | |
207 | |
208 JSCONVPUT(note->instrument, "Instrument"); | |
209 JSCONVPUT(note->volume, "Volume"); | |
210 JSCONVPUT(note->effect, "Effect"); | |
211 | |
212 tmp = (note->param != jsetNotSet) ? note->param : 0; | |
213 JSPUTBYTE(tmp); | |
214 | |
215 return DMERR_OK; | |
216 } | |
217 | |
218 | |
219 /* Compress a note | |
220 */ | |
221 static int jssCompressNote(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSNote *note) | |
222 { | |
223 Uint8 qflags = 0; | |
224 int qcomp = 0; | |
225 | |
226 JSCOMP(note->note, COMP_NOTE); | |
227 JSCOMP(note->instrument, COMP_INSTRUMENT); | |
228 JSCOMP(note->volume, COMP_VOLUME); | |
229 JSCOMP(note->effect, COMP_EFFECT); | |
230 if (note->param != jsetNotSet && note->param != 0) | |
231 { | |
232 qflags |= COMP_PARAM; | |
233 qcomp++; | |
234 } | |
235 | |
236 if (qcomp < 4) | |
237 { | |
238 JSPUTBYTE(qflags | 0x80); | |
239 | |
240 if (note->note != jsetNotSet) | |
241 { | |
242 Uint8 tmp = (note->note != jsetNoteOff) ? note->note : 127; | |
243 if (tmp > 0x7f) | |
244 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, "Note value out of bounds %d > 0x7f.\n", tmp); | |
245 JSPUTBYTE(tmp); | |
246 } | |
247 | |
248 JSCOMPPUT(COMP_INSTRUMENT, note->instrument, "Instrument"); | |
249 JSCOMPPUT(COMP_VOLUME, note->volume, "Volume"); | |
250 JSCOMPPUT(COMP_EFFECT, note->effect, "Effect"); | |
251 JSCOMPPUT(COMP_PARAM, note->param, "Param"); | |
252 } else | |
253 return jssConvertNote(patBuf, patBufSize, patSize, note); | |
254 | |
255 return DMERR_OK; | |
256 } | |
257 | |
258 | |
259 /* Compress pattern | |
260 */ | |
261 static int jssConvertPatternCompHoriz(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSPattern *pattern) | |
262 { | |
263 int row, channel; | |
264 *patSize = 0; | |
265 | |
266 for (row = 0; row < pattern->nrows; row++) | |
267 for (channel = 0; channel < pattern->nchannels; channel++) | |
268 { | |
269 const JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | |
270 const int res = jssCompressNote(patBuf, patBufSize, patSize, note); | |
271 if (res != DMERR_OK) | |
272 { | |
273 JSSERROR(res, res, "Note compression failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
274 patBuf, patBufSize, *patSize, row, channel); | |
275 return res; | |
276 } | |
277 } | |
278 | |
279 return DMERR_OK; | |
280 } | |
281 | |
282 | |
283 static int jssConvertPatternCompVert(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSPattern *pattern) | |
284 { | |
285 int row, channel; | |
286 *patSize = 0; | |
287 | |
288 for (channel = 0; channel < pattern->nchannels; channel++) | |
289 for (row = 0; row < pattern->nrows; row++) | |
290 { | |
291 const JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | |
292 const int res = jssCompressNote(patBuf, patBufSize, patSize, note); | |
293 if (res != DMERR_OK) | |
294 { | |
295 JSSERROR(res, res, "Note compression failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
296 patBuf, patBufSize, *patSize, row, channel); | |
297 return res; | |
298 } | |
299 } | |
300 | |
301 return DMERR_OK; | |
302 } | |
303 | |
304 | |
305 /* Convert a pattern | |
306 */ | |
307 static int jssConvertPatternRawHoriz(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSPattern *pattern) | |
308 { | |
309 int row, channel; | |
310 *patSize = 0; | |
311 | |
312 for (row = 0; row < pattern->nrows; row++) | |
313 for (channel = 0; channel < pattern->nchannels; channel++) | |
314 { | |
315 const JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | |
316 const int res = jssConvertNote(patBuf, patBufSize, patSize, note); | |
317 if (res != DMERR_OK) | |
318 { | |
319 JSSERROR(res, res, "Note conversion failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
320 patBuf, patBufSize, *patSize, row, channel); | |
321 return res; | |
322 } | |
323 } | |
324 | |
325 return DMERR_OK; | |
326 } | |
327 | |
328 | |
329 static int jssConvertPatternRawVert(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSPattern *pattern) | |
330 { | |
331 int row, channel; | |
332 *patSize = 0; | |
333 | |
334 for (channel = 0; channel < pattern->nchannels; channel++) | |
335 for (row = 0; row < pattern->nrows; row++) | |
336 { | |
337 const JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | |
338 const int res = jssConvertNote(patBuf, patBufSize, patSize, note); | |
339 if (res != DMERR_OK) | |
340 { | |
341 JSSERROR(res, res, "Note conversion failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
342 patBuf, patBufSize, *patSize, row, channel); | |
343 return res; | |
344 } | |
345 } | |
346 | |
347 return DMERR_OK; | |
348 } | |
349 | |
350 | |
351 #define JSFOREACHNOTE1 \ | |
352 for (channel = 0; channel < pattern->nchannels; channel++) \ | |
353 for (row = 0; row < pattern->nrows; row++) { \ | |
354 const JSSNote *note = &pattern->data[(pattern->nchannels * row) + channel]; | |
355 | |
356 #define JSFOREACHNOTE2 } | |
357 | |
358 static int jssConvertPatternRawElem(Uint8 *patBuf, const size_t patBufSize, size_t *patSize, const JSSPattern *pattern) | |
359 { | |
360 Uint8 tmp; | |
361 int row, channel; | |
362 *patSize = 0; | |
363 | |
364 JSFOREACHNOTE1; | |
365 if (note->note == jsetNotSet) | |
366 tmp = 0; | |
367 else if (note->note == jsetNoteOff) | |
368 tmp = 127; | |
369 else | |
370 tmp = note->note + 1; | |
371 if (tmp > 0x7f) | |
372 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, "Note value out of bounds %d > 0x7f.\n", tmp); | |
373 JSPUTBYTE(tmp); | |
374 JSFOREACHNOTE2; | |
375 | |
376 JSFOREACHNOTE1; | |
377 JSCONVPUT(note->instrument, "Instrument"); | |
378 JSFOREACHNOTE2; | |
379 | |
380 JSFOREACHNOTE1; | |
381 JSCONVPUT(note->volume, "Volume"); | |
382 JSFOREACHNOTE2; | |
383 | |
384 JSFOREACHNOTE1; | |
385 JSCONVPUT(note->effect, "Effect"); | |
386 JSFOREACHNOTE2; | |
387 | |
388 JSFOREACHNOTE1; | |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
389 tmp = (note->param != jsetNotSet) ? note->param : 0; |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
390 JSPUTBYTE(tmp); |
0 | 391 JSFOREACHNOTE2; |
392 | |
393 return DMERR_OK; | |
394 } | |
395 | |
396 #undef JSFOREACHNOTE1 | |
397 #undef JSFOREACHNOTE2 | |
398 | |
399 | |
400 static void jssCopyEnvelope(JSSMODEnvelope *je, JSSEnvelope *e) | |
401 { | |
402 int i; | |
403 | |
404 je->flags = e->flags; | |
405 je->npoints = e->npoints; | |
406 je->sustain = e->sustain; | |
407 je->loopS = e->loopS; | |
408 je->loopE = e->loopE; | |
409 | |
410 for (i = 0; i < e->npoints; i++) | |
411 { | |
412 je->points[i].frame = e->points[i].frame; | |
413 je->points[i].value = e->points[i].value; | |
414 } | |
415 } | |
416 | |
417 | |
418 /* Save a JSSMOD file | |
419 */ | |
420 int jssSaveJSSMOD(FILE *outFile, JSSModule *m, int patMode, int flags8, int flags16) | |
421 { | |
422 JSSMODHeader jssH; | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
423 int i, pattern, order, instr, totalSize; |
0 | 424 const size_t patBufSize = 64*1024; // 64kB pattern buffer |
425 Uint8 *patBuf; | |
426 | |
427 // Check the module | |
428 if (m == NULL) | |
429 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, "Module pointer was NULL\n"); | |
430 | |
431 if ((m->nchannels < 1) || (m->npatterns < 1) || (m->norders < 1)) | |
432 JSSERROR(DMERR_BOUNDS, DMERR_BOUNDS, | |
433 "Module had invalid values (nchannels=%i, npatterns=%i, norders=%i)\n", | |
434 m->nchannels, m->npatterns, m->norders); | |
435 | |
436 // Create the JSSMOD header | |
437 jssH.idMagic[0] = 'J'; | |
438 jssH.idMagic[1] = 'M'; | |
439 jssH.idVersion = JSSMOD_VERSION; | |
440 jssH.norders = m->norders; | |
441 jssH.npatterns = m->npatterns; | |
442 jssH.nchannels = m->nchannels; | |
443 jssH.nextInstruments = m->nextInstruments; | |
444 jssH.ninstruments = m->ninstruments; | |
445 jssH.defFlags = m->defFlags; | |
446 jssH.intVersion = m->intVersion; | |
447 jssH.defRestartPos = m->defRestartPos; | |
448 jssH.defSpeed = m->defSpeed; | |
449 jssH.defTempo = m->defTempo; | |
450 jssH.patMode = patMode; | |
451 | |
452 // Write header | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
453 totalSize = sizeof(jssH); |
0 | 454 if (fwrite(&jssH, sizeof(jssH), 1, outFile) != 1) |
455 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, "Could not write JSSMOD header!\n"); | |
456 | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
457 dmMsg(1," * JSSMOD-header 0x%04x, %d bytes.\n", JSSMOD_VERSION, totalSize); |
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
458 |
0 | 459 // Write orders list |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
460 for (totalSize = order = 0; order < m->norders; order++) |
0 | 461 { |
462 Uint16 tmp = m->orderList[order]; | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
463 totalSize += sizeof(tmp); |
0 | 464 if (fwrite(&tmp, sizeof(tmp), 1, outFile) != 1) |
465 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, "Could not write JSSMOD orders list.\n"); | |
466 } | |
467 | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
468 dmMsg(1," * %d item orders list, %d bytes.\n", |
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
469 m->norders, totalSize); |
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
470 |
0 | 471 // Allocate pattern compression buffer |
472 if ((patBuf = dmMalloc(patBufSize)) == NULL) | |
473 JSSERROR(DMERR_MALLOC, DMERR_MALLOC, | |
474 "Error allocating memory for pattern compression buffer.\n"); | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
475 |
0 | 476 |
477 // Write patterns | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
478 for (totalSize = pattern = 0; pattern < m->npatterns; pattern++) |
0 | 479 { |
480 JSSMODPattern patHead; | |
481 size_t finalSize = 0; | |
482 | |
483 switch (patMode) | |
484 { | |
485 case PATMODE_RAW_HORIZ: | |
486 i = jssConvertPatternRawHoriz(patBuf, patBufSize, &finalSize, m->patterns[pattern]); | |
487 break; | |
488 case PATMODE_COMP_HORIZ: | |
489 i = jssConvertPatternCompHoriz(patBuf, patBufSize, &finalSize, m->patterns[pattern]); | |
490 break; | |
491 case PATMODE_RAW_VERT: | |
492 i = jssConvertPatternRawVert(patBuf, patBufSize, &finalSize, m->patterns[pattern]); | |
493 break; | |
494 case PATMODE_COMP_VERT: | |
495 i = jssConvertPatternCompVert(patBuf, patBufSize, &finalSize, m->patterns[pattern]); | |
496 break; | |
497 case PATMODE_RAW_ELEM: | |
498 i = jssConvertPatternRawElem(patBuf, patBufSize, &finalSize, m->patterns[pattern]); | |
499 break; | |
500 default: | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
501 i = DMERR_INVALID_DATA; |
0 | 502 dmFree(patBuf); |
503 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | |
504 "Unsupported pattern conversion mode %d.\n", patMode); | |
505 break; | |
506 } | |
507 | |
508 if (i != DMERR_OK) | |
509 { | |
510 dmFree(patBuf); | |
511 JSSERROR(i, i, "Error converting pattern data #%i\n", pattern); | |
512 } | |
513 else | |
514 { | |
515 dmMsg(3, " - Pattern %d size %d bytes\n", pattern, finalSize); | |
516 patHead.nrows = m->patterns[pattern]->nrows; | |
517 patHead.size = finalSize; | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
518 totalSize += finalSize + sizeof(patHead); |
0 | 519 |
520 if (fwrite(&patHead, sizeof(patHead), 1, outFile) != 1) | |
521 { | |
522 dmFree(patBuf); | |
523 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
524 "Error writing pattern #%d header\n", pattern); | |
525 } | |
526 | |
527 if (fwrite(patBuf, sizeof(Uint8), finalSize, outFile) != finalSize) | |
528 { | |
529 dmFree(patBuf); | |
530 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
531 "Error writing pattern #%d data\n", pattern); | |
532 } | |
533 } | |
534 } | |
535 dmFree(patBuf); | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
536 dmMsg(1," * %d patterns, %d bytes.\n", m->npatterns, totalSize); |
0 | 537 |
538 // Write extended instruments | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
539 for (totalSize = instr = 0; instr < m->nextInstruments; instr++) |
0 | 540 { |
541 JSSMODExtInstrument jssE; | |
542 JSSExtInstrument *einst = m->extInstruments[instr]; | |
543 | |
544 memset(&jssE, 0, sizeof(jssE)); | |
545 | |
546 if (einst) | |
547 { | |
548 // Create header | |
549 jssE.nsamples = einst->nsamples; | |
550 for (i = 0; i < jsetNNotes; i++) | |
551 { | |
552 int snum = einst->sNumForNotes[i]; | |
553 jssE.sNumForNotes[i] = (snum != jsetNotSet) ? snum : 0; | |
554 } | |
555 | |
556 jssCopyEnvelope(&jssE.volumeEnv, &(einst->volumeEnv)); | |
557 jssCopyEnvelope(&jssE.panningEnv, &(einst->panningEnv)); | |
558 jssE.vibratoType = einst->vibratoType; | |
559 jssE.vibratoSweep = einst->vibratoSweep; | |
560 jssE.vibratoDepth = einst->vibratoDepth; | |
561 jssE.fadeOut = einst->fadeOut; | |
562 } else | |
563 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, "Extended instrument #%i NULL!\n", instr); | |
564 | |
565 // Write to file | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
566 totalSize += sizeof(jssE); |
0 | 567 if (fwrite(&jssE, sizeof(jssE), 1, outFile) != 1) |
568 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
569 "Could not write JSSMOD extended instrument #%i to file!\n", instr); | |
570 } | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
571 dmMsg(1," * %d Extended Instruments, %d bytes.\n", m->nextInstruments, totalSize); |
0 | 572 |
573 | |
574 // Write sample instrument headers | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
575 for (totalSize = instr = 0; instr < m->ninstruments; instr++) |
0 | 576 { |
577 JSSMODInstrument jssI; | |
578 JSSInstrument *pInst = m->instruments[instr]; | |
579 | |
580 memset(&jssI, 0, sizeof(jssI)); | |
581 | |
582 // Create header | |
583 if (pInst) | |
584 { | |
585 jssI.size = pInst->size; | |
586 jssI.loopS = pInst->loopS; | |
587 jssI.loopE = pInst->loopE; | |
588 jssI.volume = pInst->volume; | |
589 jssI.flags = pInst->flags; | |
590 jssI.C4BaseSpeed = pInst->C4BaseSpeed; | |
591 jssI.ERelNote = pInst->ERelNote; | |
592 jssI.EFineTune = pInst->EFineTune; | |
593 jssI.EPanning = pInst->EPanning; | |
594 jssI.hasData = (pInst->data != NULL) ? TRUE : FALSE; | |
595 jssI.convFlags = (pInst->flags & jsf16bit) ? flags16 : flags8; | |
596 } | |
597 else | |
598 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, "Instrument #%i NULL!\n", instr); | |
599 | |
600 // Write to file | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
601 totalSize += sizeof(jssI); |
0 | 602 if (fwrite(&jssI, sizeof(jssI), 1, outFile) != 1) |
603 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
604 "Could not write JSSMOD instrument #%i to file!\n", instr); | |
605 } | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
606 dmMsg(1," * %d Instrument headers, %d bytes.\n", m->ninstruments, totalSize); |
0 | 607 |
608 // Write sample data | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
609 for (totalSize = instr = 0; instr < m->ninstruments; instr++) |
0 | 610 if (m->instruments[instr]) |
611 { | |
612 JSSInstrument *inst = m->instruments[instr]; | |
613 if (inst->data != NULL) | |
614 { | |
615 size_t res; | |
616 if (inst->flags & jsf16bit) | |
617 { | |
618 jssEncodeSample16(inst->data, inst->size, flags16); | |
619 res = fwrite(inst->data, sizeof(Uint16), inst->size, outFile); | |
620 } | |
621 else | |
622 { | |
623 jssEncodeSample8(inst->data, inst->size, flags8); | |
624 res = fwrite(inst->data, sizeof(Uint8), inst->size, outFile); | |
625 } | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
626 |
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
627 totalSize += inst->size; |
86 | 628 if (res != (size_t) inst->size) |
0 | 629 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
630 "Could not write JSSMOD sample #%i to file!\n", instr); | |
631 } | |
632 } | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
633 dmMsg(1," * %d samples, %d bytes.\n", m->ninstruments, totalSize); |
0 | 634 |
635 return DMERR_OK; | |
636 } | |
637 | |
638 | |
639 /* Optimize a given module | |
640 */ | |
641 JSSModule *optimizeModule(JSSModule *m) | |
642 { | |
643 BOOL usedPatterns[jsetMaxPatterns + 1], | |
644 usedInstruments[jsetMaxInstruments + 1], | |
645 usedExtInstruments[jsetMaxInstruments + 1]; | |
646 int mapExtInstruments[jsetMaxInstruments + 1], | |
647 mapInstruments[jsetMaxInstruments + 1], | |
648 mapPatterns[jsetMaxPatterns + 1]; | |
649 JSSModule *r = NULL; | |
650 int i, n8, n16; | |
651 | |
652 // Allocate a new module | |
653 if ((r = jssAllocateModule()) == NULL) | |
654 return NULL; | |
655 | |
656 // Allocate tables | |
657 | |
658 // Copy things | |
659 r->moduleType = m->moduleType; | |
660 r->moduleName = dm_strdup(m->moduleName); | |
661 r->trackerName = dm_strdup(m->trackerName); | |
662 r->defSpeed = m->defSpeed; | |
663 r->defTempo = m->defTempo; | |
664 r->defFlags = m->defFlags; | |
665 r->defRestartPos = m->defRestartPos; | |
666 r->intVersion = m->intVersion; | |
667 r->nchannels = m->nchannels; | |
668 r->norders = m->norders; | |
669 for (i = 0; i < jsetNChannels; i++) | |
670 r->defPanning[i] = m->defPanning[i]; | |
671 | |
672 // Initialize values | |
673 for (i = 0; i <= jsetMaxInstruments; i++) | |
674 { | |
675 usedExtInstruments[i] = FALSE; | |
676 usedInstruments[i] = FALSE; | |
677 mapExtInstruments[i] = jsetNotSet; | |
678 mapInstruments[i] = jsetNotSet; | |
679 } | |
680 | |
681 for (i = 0; i <= jsetMaxPatterns; i++) | |
682 { | |
683 usedPatterns[i] = FALSE; | |
684 mapPatterns[i] = jsetNotSet; | |
685 } | |
686 | |
687 // Find out all used patterns and ext.instruments | |
688 for (i = 0; i < m->norders; i++) | |
689 { | |
690 int pattern = m->orderList[i]; | |
691 if (pattern >= 0 && pattern < m->npatterns) | |
692 { | |
693 JSSPattern *p = m->patterns[pattern]; | |
694 if (p != NULL) | |
695 { | |
696 int row, channel; | |
697 JSSNote *n = p->data; | |
698 | |
699 // Mark pattern as used | |
700 usedPatterns[pattern] = TRUE; | |
701 | |
702 // Check all notes | |
703 for (row = 0; row < p->nrows; row++) | |
704 for (channel = 0; channel < p->nchannels; channel++, n++) | |
705 { | |
706 if (n->instrument != jsetNotSet) | |
707 { | |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
708 if (optStripExtInstr || (n->instrument >= 0 && n->instrument < m->nextInstruments)) |
0 | 709 usedExtInstruments[n->instrument] = TRUE; |
710 else | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
711 dmMsg(2, "Pattern 0x%x, row=0x%x, chn=%d has invalid instrument 0x%x\n", |
0 | 712 pattern, row, channel, n->instrument); |
713 } | |
714 } | |
715 } | |
716 else | |
717 { | |
718 dmError("Pattern 0x%x is used on order 0x%x, but has no data!\n", | |
719 pattern, i); | |
720 } | |
721 } | |
722 else | |
723 if (pattern != jsetMaxPatterns) | |
724 { | |
725 dmError("Order 0x%x has invalid pattern number 0x%x!\n", | |
726 i, pattern); | |
727 } | |
728 } | |
729 | |
730 // Find out used instruments | |
731 for (i = 0; i <= jsetMaxInstruments; i++) | |
732 if (usedExtInstruments[i] && m->extInstruments[i] != NULL) | |
733 { | |
734 int note; | |
735 JSSExtInstrument *e = m->extInstruments[i]; | |
736 | |
737 for (note = 0; note < jsetNNotes; note++) | |
738 if (e->sNumForNotes[note] != jsetNotSet) | |
739 { | |
740 int q = e->sNumForNotes[note]; | |
741 if (q >= 0 && q < m->ninstruments) | |
742 { | |
743 usedInstruments[q] = TRUE; | |
744 } | |
745 else | |
746 { | |
747 dmError("Ext.instrument #%d sNumForNotes[%d] value out range (%d < %d).\n", | |
748 i, m->ninstruments, q); | |
749 } | |
750 } | |
751 } | |
752 | |
753 // Create pattern mappings | |
754 r->npatterns = 0; | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
755 dmMsg(1, "Unused patterns: "); |
0 | 756 |
757 for (i = 0; i <= jsetMaxPatterns; i++) | |
758 if (m->patterns[i] != NULL) | |
759 { | |
760 if (!usedPatterns[i]) | |
761 { | |
762 dmPrint(2, "0x%x, ", i); | |
763 } | |
764 else | |
765 { | |
766 if (i >= m->npatterns) | |
767 dmError("Pattern 0x%x >= 0x%x, but used!\n", i, m->npatterns); | |
768 | |
769 mapPatterns[i] = r->npatterns; | |
770 r->patterns[r->npatterns] = m->patterns[i]; | |
771 (r->npatterns)++; | |
772 } | |
773 } | |
774 dmPrint(2, "\n"); | |
775 | |
776 dmMsg(1, "%d used patterns, %d unused.\n", | |
777 r->npatterns, m->npatterns - r->npatterns); | |
778 | |
779 | |
780 // Re-map instruments | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
781 dmMsg(1, "Unused instruments: "); |
0 | 782 for (n8 = n16 = i = 0; i <= jsetMaxInstruments; i++) |
783 if (m->instruments[i] != NULL) | |
784 { | |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
785 if (!usedInstruments[i] && !optStripInstr) |
0 | 786 { |
787 dmPrint(2, "0x%x, ", i); | |
788 } | |
789 else | |
790 { | |
791 JSSInstrument *ip = m->instruments[i]; | |
792 if (i >= m->ninstruments) | |
793 dmError("Instrument 0x%x >= 0x%x, but used!\n", i, m->ninstruments); | |
794 | |
795 mapInstruments[i] = r->ninstruments; | |
796 r->instruments[r->ninstruments] = ip; | |
797 (r->ninstruments)++; | |
798 | |
799 if (ip->flags & jsf16bit) | |
800 n16++; | |
801 else | |
802 n8++; | |
803 } | |
804 } | |
805 dmPrint(2, "\n"); | |
806 dmMsg(1, "Total of (%d) 16-bit, (%d) 8-bit samples, (%d) instruments.\n", | |
807 n16, n8, r->ninstruments); | |
808 | |
809 // Re-map ext.instruments | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
810 dmMsg(1, "Unused ext.instruments: "); |
0 | 811 for (i = 0; i < jsetMaxInstruments; i++) |
812 if (usedExtInstruments[i]) | |
813 { | |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
814 if (i >= m->nextInstruments && !optStripExtInstr) |
0 | 815 { |
816 dmError("Ext.instrument 0x%x >= 0x%x, but used!\n", | |
817 i, m->nextInstruments); | |
818 } | |
819 else | |
820 if (m->extInstruments[i] != NULL) | |
821 { | |
822 JSSExtInstrument *e = m->extInstruments[i]; | |
823 int note; | |
824 | |
825 mapExtInstruments[i] = r->nextInstruments; | |
826 r->extInstruments[r->nextInstruments] = e; | |
827 (r->nextInstruments)++; | |
828 | |
829 // Re-map sNumForNotes | |
830 for (note = 0; note < jsetNNotes; note++) | |
831 { | |
832 int q = e->sNumForNotes[note]; | |
833 if (q != jsetNotSet) | |
834 { | |
835 int map; | |
836 if (q >= 0 && q <= jsetMaxInstruments) | |
837 { | |
838 map = mapInstruments[q]; | |
839 } | |
840 else | |
841 { | |
842 map = jsetNotSet; | |
843 dmError("e=%d, note=%d, q=%d/%d\n", i, note, q, r->ninstruments); | |
844 } | |
845 e->sNumForNotes[note] = map; | |
846 } | |
847 } | |
848 } | |
849 else | |
850 { | |
851 dmPrint(2, "[0x%x==NULL], ", i); | |
852 mapExtInstruments[i] = jsetNotSet; | |
853 } | |
854 } | |
855 else | |
856 { | |
857 if (i < m->nextInstruments && m->extInstruments[i] != NULL) | |
858 { | |
859 dmPrint(2, "0x%x, ", i); | |
860 } | |
861 } | |
862 dmPrint(2, "\n"); | |
863 dmMsg(1, "%d extended instruments.\n", r->nextInstruments); | |
864 | |
865 | |
866 // Remap pattern instrument data | |
867 for (i = 0; i < r->npatterns; i++) | |
868 { | |
869 int row, channel; | |
870 JSSPattern *p = r->patterns[i]; | |
871 JSSNote *n = p->data; | |
872 | |
873 for (row = 0; row < p->nrows; row++) | |
874 for (channel = 0; channel < p->nchannels; channel++, n++) | |
875 { | |
184
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
876 char effect; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
877 |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
878 if (!optStripExtInstr) |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
879 { |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
880 if (n->instrument >= 0 && n->instrument <= jsetMaxInstruments) |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
881 n->instrument = mapExtInstruments[n->instrument]; |
202
85614db5f577
Warn about invalid instruments.
Matti Hamalainen <ccr@tnsp.org>
parents:
184
diff
changeset
|
882 |
338
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
883 if (n->instrument != jsetNotSet && r->extInstruments[n->instrument] == NULL) |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
884 dmError("Non-existing instrument used #%d.\n", n->instrument); |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
885 } |
cd57ba1130eb
Fixes and improvements in the JMOD saving and loading.
Matti Hamalainen <ccr@tnsp.org>
parents:
337
diff
changeset
|
886 |
184
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
887 JMPGETEFFECT(effect, n->effect); |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
888 |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
889 switch (effect) |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
890 { |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
891 case 'C': // Cxx = Set volume |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
892 if (n->volume == jsetNotSet) |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
893 { |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
894 n->volume = n->param; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
895 n->effect = jsetNotSet; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
896 n->param = jsetNotSet; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
897 } |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
898 break; |
50f55def91e5
Add a minor optimization in the conversion.
Matti Hamalainen <ccr@tnsp.org>
parents:
86
diff
changeset
|
899 } |
0 | 900 } |
901 } | |
902 | |
903 // Remap orders list | |
904 for (i = 0; i < m->norders; i++) | |
905 { | |
906 r->orderList[i] = mapPatterns[m->orderList[i]]; | |
907 } | |
908 | |
909 return r; | |
910 } | |
911 | |
912 | |
913 int main(int argc, char *argv[]) | |
914 { | |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
915 DMResource *inFile = NULL; |
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
916 FILE *outFile = NULL; |
0 | 917 JSSModule *sm, *dm; |
918 int result; | |
919 | |
920 dmInitProg("xm2jss", "XM to JSSMOD converter", "0.6", NULL, NULL); | |
921 dmVerbosity = 0; | |
922 | |
923 // Parse arguments | |
924 if (!dmArgsProcess(argc, argv, optList, optListN, | |
925 argHandleOpt, argHandleFile, TRUE)) | |
926 exit(1); | |
927 | |
300 | 928 // Check arguments |
929 if (optInFilename == NULL || optOutFilename == NULL) | |
930 { | |
931 dmError("Input or output file not specified. Try --help.\n"); | |
932 return 1; | |
933 } | |
0 | 934 |
935 // Read the source file | |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
936 if ((result = dmf_create_stdio(optInFilename, "rb", &inFile)) != DMERR_OK) |
0 | 937 { |
84
35db15881923
Oops, another fix for dmf_create_stdio() changes.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
938 dmError("Error opening input file '%s', %d: %s\n", |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
939 optInFilename, result, dmErrorStr(result)); |
0 | 940 return 1; |
941 } | |
942 | |
943 // Initialize miniJSS | |
944 jssInit(); | |
945 | |
946 // Read file | |
947 dmMsg(1, "Reading XM-format file ...\n"); | |
797
f066e9dccf29
Oops, fix some inverted booleans.
Matti Hamalainen <ccr@tnsp.org>
parents:
796
diff
changeset
|
948 result = jssLoadXM(inFile, &sm, FALSE); |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
949 dmf_close(inFile); |
0 | 950 if (result != 0) |
951 { | |
952 dmError("Error while loading XM file (%i), ", result); | |
953 if (optIgnoreErrors) | |
954 fprintf(stderr, "ignoring. This may cause problems.\n"); | |
955 else | |
956 { | |
957 fprintf(stderr, "giving up. Use --ignore if you want to try to convert anyway.\n"); | |
958 return 2; | |
959 } | |
960 } | |
961 | |
962 // Check stripping settings | |
963 if (optStripExtInstr) optStripInstr = TRUE; | |
964 if (optStripInstr) optStripSamples = TRUE; | |
965 | |
966 // Remove samples | |
967 if (optStripSamples) | |
968 { | |
969 int i; | |
970 | |
971 dmMsg(1, "Stripping samples...\n"); | |
972 for (i = 0; i < sm->ninstruments; i++) | |
973 { | |
974 dmFree(sm->instruments[i]->data); | |
975 sm->instruments[i]->data = NULL; | |
976 } | |
977 } | |
978 | |
979 // Remove instruments | |
980 if (optStripInstr) | |
981 { | |
982 int i; | |
983 | |
984 dmMsg(1, "Stripping instruments...\n"); | |
985 for (i = 0; i < sm->ninstruments; i++) | |
986 { | |
987 dmFree(sm->instruments[i]); | |
988 sm->instruments[i] = NULL; | |
989 } | |
990 sm->ninstruments = 0; | |
991 } | |
992 | |
993 // Remove ext.instruments | |
994 if (optStripExtInstr) | |
995 { | |
996 int i; | |
997 | |
998 dmMsg(1, "Stripping ext.instruments...\n"); | |
999 for (i = 0; i < sm->nextInstruments; i++) | |
1000 { | |
1001 dmFree(sm->extInstruments[i]); | |
1002 sm->extInstruments[i] = NULL; | |
1003 } | |
1004 sm->nextInstruments = 0; | |
1005 } | |
1006 // Run the optimization procedure | |
1007 if (optOptimize) | |
1008 { | |
1009 dmMsg(1, "Optimizing module data...\n"); | |
1010 dm = optimizeModule(sm); | |
1011 } else | |
1012 dm = sm; | |
1013 | |
1014 // Write output file | |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
1015 if ((outFile = fopen(optOutFilename, "wb")) == NULL) |
0 | 1016 { |
300 | 1017 dmError("Error creating output file '%s', %d: %s\n", |
1018 optOutFilename, errno, strerror(errno)); | |
0 | 1019 return 1; |
1020 } | |
1021 | |
9
c42ee907de9c
Various improvements in xm2jss output.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
1022 dmMsg(1, "Writing JSSMOD-format file [patMode=0x%04x, samp8=0x%02x, samp16=0x%02x]\n", |
0 | 1023 optPatternMode, optSampMode8, optSampMode16); |
1024 | |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
1025 result = jssSaveJSSMOD(outFile, dm, optPatternMode, optSampMode8, optSampMode16); |
0 | 1026 |
730
3d813c81f33c
More work on resources API.
Matti Hamalainen <ccr@tnsp.org>
parents:
652
diff
changeset
|
1027 fclose(outFile); |
0 | 1028 |
1029 if (result != 0) | |
1030 { | |
300 | 1031 dmError("Error while saving JSSMOD file, %d: %s\n", |
1032 result, dmErrorStr(result)); | |
1033 dmError("WARNING: The resulting file may be broken!\n"); | |
0 | 1034 } |
300 | 1035 else |
1036 { | |
1037 dmMsg(1, "Conversion complete.\n"); | |
1038 } | |
0 | 1039 return 0; |
1040 } |