Mercurial > hg > dmlib
comparison tools/xm2jss.c @ 2285:25398f2eba64
Merge.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 18 Jun 2019 14:23:02 +0300 |
parents | 6c3c3355007d |
children | dcf1016f3d27 |
comparison
equal
deleted
inserted
replaced
2284:519c8726b235 | 2285:25398f2eba64 |
---|---|
1 /* | 1 /* |
2 * xm2jss - Convert XM module to JSSMOD | 2 * xm2jss - Convert XM module to JSSMOD |
3 * Programmed and designed by Matti 'ccr' Hamalainen | 3 * Programmed and designed by Matti 'ccr' Hamalainen |
4 * (C) Copyright 2006-2017 Tecnic Software productions (TNSP) | 4 * (C) Copyright 2006-2019 Tecnic Software productions (TNSP) |
5 * | 5 * |
6 * Please read file 'COPYING' for information on license and distribution. | 6 * Please read file 'COPYING' for information on license and distribution. |
7 */ | 7 */ |
8 #include "dmtool.h" | 8 #include "dmtool.h" |
9 #include <stdio.h> | 9 #include <stdio.h> |
145 | 145 |
146 return TRUE; | 146 return TRUE; |
147 } | 147 } |
148 | 148 |
149 | 149 |
150 static inline const JSSNote * jssGetNotePtr(const JSSPattern *pattern, const int channel, const int row) | |
151 { | |
152 if (!pattern->used[channel]) | |
153 return NULL; | |
154 else | |
155 return pattern->data + (pattern->nchannels * row) + channel; | |
156 } | |
157 | |
158 | |
150 /* These functions and the macro mess are meant to make the | 159 /* These functions and the macro mess are meant to make the |
151 * conversion routines themselves clearer and simpler. | 160 * conversion routines themselves clearer and simpler. |
152 */ | 161 */ |
153 BOOL jsPutByte(Uint8 *patBuf, size_t patBufSize, size_t *npatBuf, Uint8 val) | 162 BOOL jsPutByte(Uint8 *patBuf, size_t patBufSize, size_t *npatBuf, Uint8 val) |
154 { | 163 { |
187 } while (0) | 196 } while (0) |
188 | 197 |
189 | 198 |
190 /* Convert a note | 199 /* Convert a note |
191 */ | 200 */ |
192 static int jssConvertNote( | 201 static int jssDoConvertNote( |
193 Uint8 *patBuf, const size_t patBufSize, | 202 Uint8 *patBuf, const size_t patBufSize, |
194 size_t *patSize, const JSSNote *pnote) | 203 size_t *patSize, const JSSNote *pnote) |
195 { | 204 { |
196 Uint8 tmp; | 205 Uint8 tmp; |
197 if (pnote->note == jsetNotSet) | 206 if (pnote->note == jsetNotSet) |
218 } | 227 } |
219 | 228 |
220 | 229 |
221 /* Compress a note | 230 /* Compress a note |
222 */ | 231 */ |
223 static int jssCompressNote( | 232 static int jssDoCompressNote( |
224 Uint8 *patBuf, const size_t patBufSize, | 233 Uint8 *patBuf, const size_t patBufSize, |
225 size_t *patSize, const JSSNote *pnote) | 234 size_t *patSize, const JSSNote *pnote) |
226 { | 235 { |
227 Uint8 qflags = 0; | 236 Uint8 qflags = 0; |
228 int qcomp = 0; | 237 int qcomp = 0; |
254 | 263 |
255 JSCOMPPUT(JM_COMP_INSTRUMENT, pnote->instrument, "Instrument"); | 264 JSCOMPPUT(JM_COMP_INSTRUMENT, pnote->instrument, "Instrument"); |
256 JSCOMPPUT(JM_COMP_VOLUME, pnote->volume, "Volume"); | 265 JSCOMPPUT(JM_COMP_VOLUME, pnote->volume, "Volume"); |
257 JSCOMPPUT(JM_COMP_EFFECT, pnote->effect, "Effect"); | 266 JSCOMPPUT(JM_COMP_EFFECT, pnote->effect, "Effect"); |
258 JSCOMPPUT(JM_COMP_PARAM, pnote->param, "Param"); | 267 JSCOMPPUT(JM_COMP_PARAM, pnote->param, "Param"); |
268 | |
269 return DMERR_OK; | |
259 } | 270 } |
260 else | 271 else |
261 { | 272 { |
262 // Was 4 bytes or more, just dump it all in .. | 273 // Was 4 bytes or more, just dump it all in .. |
263 return jssConvertNote(patBuf, patBufSize, patSize, pnote); | 274 return jssDoConvertNote(patBuf, patBufSize, patSize, pnote); |
264 } | 275 } |
265 | 276 } |
277 | |
278 | |
279 static int jssCompressNote( | |
280 Uint8 *patBuf, const size_t patBufSize, | |
281 size_t *patSize, const JSSPattern *pattern, | |
282 const int channel, const int row) | |
283 { | |
284 const JSSNote *pnote = jssGetNotePtr(pattern, channel, row); | |
285 if (pnote != NULL) | |
286 { | |
287 int res = jssDoCompressNote(patBuf, patBufSize, patSize, pnote); | |
288 if (res != DMERR_OK) | |
289 { | |
290 JSSERROR(res, res, "Note compression failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
291 patBuf, patBufSize, *patSize, row, channel); | |
292 return res; | |
293 } | |
294 } | |
266 return DMERR_OK; | 295 return DMERR_OK; |
267 } | 296 } |
268 | 297 |
269 | 298 |
270 /* Compress pattern | 299 /* Compress pattern |
276 *patSize = 0; | 305 *patSize = 0; |
277 | 306 |
278 for (int row = 0; row < pattern->nrows; row++) | 307 for (int row = 0; row < pattern->nrows; row++) |
279 for (int channel = 0; channel < pattern->nchannels; channel++) | 308 for (int channel = 0; channel < pattern->nchannels; channel++) |
280 { | 309 { |
281 const JSSNote *pnote = &pattern->data[(pattern->nchannels * row) + channel]; | 310 int res = jssCompressNote(patBuf, patBufSize, patSize, pattern, channel, row); |
282 const int res = jssCompressNote(patBuf, patBufSize, patSize, pnote); | |
283 if (res != DMERR_OK) | 311 if (res != DMERR_OK) |
284 { | |
285 JSSERROR(res, res, "Note compression failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
286 patBuf, patBufSize, *patSize, row, channel); | |
287 return res; | 312 return res; |
288 } | |
289 } | 313 } |
290 | 314 |
291 return DMERR_OK; | 315 return DMERR_OK; |
292 } | 316 } |
293 | 317 |
299 *patSize = 0; | 323 *patSize = 0; |
300 | 324 |
301 for (int channel = 0; channel < pattern->nchannels; channel++) | 325 for (int channel = 0; channel < pattern->nchannels; channel++) |
302 for (int row = 0; row < pattern->nrows; row++) | 326 for (int row = 0; row < pattern->nrows; row++) |
303 { | 327 { |
304 const JSSNote *pnote = &pattern->data[(pattern->nchannels * row) + channel]; | 328 int res = jssCompressNote(patBuf, patBufSize, patSize, pattern, channel, row); |
305 const int res = jssCompressNote(patBuf, patBufSize, patSize, pnote); | |
306 if (res != DMERR_OK) | 329 if (res != DMERR_OK) |
307 { | 330 return res; |
308 JSSERROR(res, res, "Note compression failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | 331 } |
332 | |
333 return DMERR_OK; | |
334 } | |
335 | |
336 | |
337 /* Convert a pattern | |
338 */ | |
339 static int jssConvertNote( | |
340 Uint8 *patBuf, const size_t patBufSize, | |
341 size_t *patSize, const JSSPattern *pattern, | |
342 const int channel, const int row) | |
343 { | |
344 const JSSNote *pnote = jssGetNotePtr(pattern, channel, row); | |
345 if (pnote != NULL) | |
346 { | |
347 int res = jssDoConvertNote(patBuf, patBufSize, patSize, pnote); | |
348 if (res != DMERR_OK) | |
349 { | |
350 JSSERROR(res, res, "Note conversion failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
309 patBuf, patBufSize, *patSize, row, channel); | 351 patBuf, patBufSize, *patSize, row, channel); |
310 return res; | 352 return res; |
311 } | 353 } |
312 } | 354 } |
313 | |
314 return DMERR_OK; | 355 return DMERR_OK; |
315 } | 356 } |
316 | 357 |
317 | 358 |
318 /* Convert a pattern | |
319 */ | |
320 static int jssConvertPatternRawHoriz( | 359 static int jssConvertPatternRawHoriz( |
321 Uint8 *patBuf, const size_t patBufSize, | 360 Uint8 *patBuf, const size_t patBufSize, |
322 size_t *patSize, const JSSPattern *pattern) | 361 size_t *patSize, const JSSPattern *pattern) |
323 { | 362 { |
324 *patSize = 0; | 363 *patSize = 0; |
325 | 364 |
326 for (int row = 0; row < pattern->nrows; row++) | 365 for (int row = 0; row < pattern->nrows; row++) |
327 for (int channel = 0; channel < pattern->nchannels; channel++) | 366 for (int channel = 0; channel < pattern->nchannels; channel++) |
328 { | 367 { |
329 const JSSNote *pnote = &pattern->data[(pattern->nchannels * row) + channel]; | 368 int res = jssConvertNote(patBuf, patBufSize, patSize, pattern, channel, row); |
330 const int res = jssConvertNote(patBuf, patBufSize, patSize, pnote); | |
331 if (res != DMERR_OK) | 369 if (res != DMERR_OK) |
332 { | |
333 JSSERROR(res, res, "Note conversion failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
334 patBuf, patBufSize, *patSize, row, channel); | |
335 return res; | 370 return res; |
336 } | |
337 } | 371 } |
338 | 372 |
339 return DMERR_OK; | 373 return DMERR_OK; |
340 } | 374 } |
341 | 375 |
347 *patSize = 0; | 381 *patSize = 0; |
348 | 382 |
349 for (int channel = 0; channel < pattern->nchannels; channel++) | 383 for (int channel = 0; channel < pattern->nchannels; channel++) |
350 for (int row = 0; row < pattern->nrows; row++) | 384 for (int row = 0; row < pattern->nrows; row++) |
351 { | 385 { |
352 const JSSNote *pnote = &pattern->data[(pattern->nchannels * row) + channel]; | 386 int res = jssConvertNote(patBuf, patBufSize, patSize, pattern, channel, row); |
353 const int res = jssConvertNote(patBuf, patBufSize, patSize, pnote); | |
354 if (res != DMERR_OK) | 387 if (res != DMERR_OK) |
355 { | |
356 JSSERROR(res, res, "Note conversion failed [patBuf=%p, patBufSize=%d, patSize=%d, row=%d, chn=%d]\n", | |
357 patBuf, patBufSize, *patSize, row, channel); | |
358 return res; | 388 return res; |
359 } | |
360 } | 389 } |
361 | 390 |
362 return DMERR_OK; | 391 return DMERR_OK; |
363 } | 392 } |
364 | 393 |
365 | 394 |
366 #define JSFOREACHNOTE1 \ | 395 #define JSFOREACHNOTE1 \ |
367 for (channel = 0; channel < pattern->nchannels; channel++) \ | 396 for (channel = 0; channel < pattern->nchannels; channel++) \ |
368 for (row = 0; row < pattern->nrows; row++) { \ | 397 for (row = 0; row < pattern->nrows; row++) { \ |
369 const JSSNote *pnote = &pattern->data[(pattern->nchannels * row) + channel]; | 398 const JSSNote *pnote = jssGetNotePtr(pattern, channel, row); \ |
370 | 399 if (pnote != NULL) { |
371 #define JSFOREACHNOTE2 } | 400 |
401 #define JSFOREACHNOTE2 } } | |
402 | |
372 | 403 |
373 static int jssConvertPatternRawElem( | 404 static int jssConvertPatternRawElem( |
374 Uint8 *patBuf, const size_t patBufSize, | 405 Uint8 *patBuf, const size_t patBufSize, |
375 size_t *patSize, const JSSPattern *pattern) | 406 size_t *patSize, const JSSPattern *pattern) |
376 { | 407 { |
544 "Error allocating memory for pattern compression buffer.\n"); | 575 "Error allocating memory for pattern compression buffer.\n"); |
545 } | 576 } |
546 | 577 |
547 // Convert and write patterns | 578 // Convert and write patterns |
548 for (totalSize = index = 0; index < module->npatterns; index++) | 579 for (totalSize = index = 0; index < module->npatterns; index++) |
549 if (module->patterns[index] != NULL) | |
550 { | 580 { |
551 JSSPattern *pattern = module->patterns[index]; | 581 JSSPattern *pattern = module->patterns[index]; |
552 size_t dataSize = 0; | 582 size_t dataSize = 0; |
553 int ret; | 583 int ret; |
584 | |
585 if (pattern == NULL) | |
586 { | |
587 dmMsg(1, | |
588 "Pattern #%d is NULL.\n", index); | |
589 pattern = module->patterns[module->npatterns]; | |
590 } | |
554 | 591 |
555 if (pattern->nrows > jsetMaxRows) | 592 if (pattern->nrows > jsetMaxRows) |
556 { | 593 { |
557 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, | 594 JSSERROR(DMERR_INVALID_DATA, DMERR_INVALID_DATA, |
558 "Pattern #%d has %d rows > %d max.\n", | 595 "Pattern #%d has %d rows > %d max.\n", |
591 dmMsg(3, " - Pattern %d size %d bytes\n", index, dataSize); | 628 dmMsg(3, " - Pattern %d size %d bytes\n", index, dataSize); |
592 totalSize += dataSize + sizeof(JSSMODPattern); | 629 totalSize += dataSize + sizeof(JSSMODPattern); |
593 | 630 |
594 if (!dm_fwrite_le32(outFile, dataSize) || | 631 if (!dm_fwrite_le32(outFile, dataSize) || |
595 !dm_fwrite_le16(outFile, pattern->nrows) || | 632 !dm_fwrite_le16(outFile, pattern->nrows) || |
596 !dm_fwrite_str(outFile, patBuf, dataSize)) | 633 !dm_fwrite_le16(outFile, pattern->nmap)) |
597 { | 634 { |
598 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | 635 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, |
599 "Error writing JSSMOD pattern #%d.\n", | 636 "Error writing JSSMOD pattern header #%d.\n", |
600 index); | 637 index); |
601 } | 638 } |
602 } | 639 |
603 else | 640 if (pattern->nmap != pattern->nchannels) |
604 { | 641 { |
605 JSSERROR(DMERR_NULLPTR, DMERR_NULLPTR, | 642 if (!dm_fwrite_str(outFile, pattern->map, |
606 "Pattern #%d was NULL.\n", index); | 643 sizeof(pattern->map[0]) * pattern->nmap)) |
644 { | |
645 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
646 "Error writing JSSMOD channel map for pattern #%d.\n", | |
647 index); | |
648 } | |
649 } | |
650 | |
651 if (!dm_fwrite_str(outFile, patBuf, dataSize)) | |
652 { | |
653 JSSERROR(DMERR_FWRITE, DMERR_FWRITE, | |
654 "Error writing JSSMOD pattern data #%d.\n", | |
655 index); | |
656 } | |
607 } | 657 } |
608 | 658 |
609 dmFree(patBuf); | 659 dmFree(patBuf); |
610 dmMsg(1," * %d patterns, %d bytes.\n", | 660 dmMsg(1," * %d patterns, %d bytes.\n", |
611 module->npatterns, totalSize); | 661 module->npatterns, totalSize); |
618 | 668 |
619 if (einst == NULL) | 669 if (einst == NULL) |
620 { | 670 { |
621 einst = &tmpEInst; | 671 einst = &tmpEInst; |
622 memset(&tmpEInst, 0, sizeof(tmpEInst)); | 672 memset(&tmpEInst, 0, sizeof(tmpEInst)); |
623 JSSWARNING(DMERR_NULLPTR, DMERR_NULLPTR, | 673 dmMsg(1, |
624 "Extended instrument #%d NULL!\n", | 674 "Extended instrument #%d is NULL!\n", |
625 index); | 675 index); |
626 } | 676 } |
627 | 677 |
628 // Misc data | 678 // Misc data |
629 BOOL ok = | 679 BOOL ok = |
742 | 792 |
743 | 793 |
744 /* Scan given pattern for used instruments and channels. | 794 /* Scan given pattern for used instruments and channels. |
745 * Also checks if the pattern is empty. | 795 * Also checks if the pattern is empty. |
746 */ | 796 */ |
747 void scanPattern(const JSSModule *module, const JSSPattern *pattern, | 797 BOOL jssScanPattern(const JSSModule *module, const JSSPattern *pattern, |
748 const int npattern, BOOL *usedExtInstruments, BOOL *usedChannels, BOOL *empty) | 798 const int npattern, BOOL *usedExtInstruments, BOOL *usedChannels) |
749 { | 799 { |
750 JSSNote *n = pattern->data; | 800 JSSNote *n = pattern->data; |
751 *empty = FALSE; | 801 BOOL empty = TRUE; |
752 | 802 |
753 // Check all notes in this pattern | 803 // Check all notes in this pattern |
754 for (int row = 0; row < pattern->nrows; row++) | 804 for (int row = 0; row < pattern->nrows; row++) |
755 for (int channel = 0; channel < pattern->nchannels; channel++, n++) | 805 for (int channel = 0; channel < pattern->nchannels; channel++, n++) |
756 { | 806 { |
757 // Is the instrument set? | 807 // Is the instrument set? |
758 if (n->instrument != jsetNotSet) | 808 if (usedExtInstruments != NULL && |
809 n->instrument != jsetNotSet) | |
759 { | 810 { |
760 // Is it valid? | 811 // Is it valid? |
761 if (n->instrument >= 0 && n->instrument < module->nextInstruments) | 812 if (n->instrument >= 0 && n->instrument < module->nextInstruments) |
762 usedExtInstruments[n->instrument] = TRUE; | 813 usedExtInstruments[n->instrument] = TRUE; |
763 else | 814 else |
772 n->instrument != jsetNotSet || | 823 n->instrument != jsetNotSet || |
773 n->volume != jsetNotSet || | 824 n->volume != jsetNotSet || |
774 n->effect != jsetNotSet || | 825 n->effect != jsetNotSet || |
775 n->param != jsetNotSet) | 826 n->param != jsetNotSet) |
776 { | 827 { |
777 usedChannels[channel] = TRUE; | 828 if (usedChannels != NULL) |
778 *empty = FALSE; | 829 usedChannels[channel] = TRUE; |
779 } | 830 |
780 } | 831 empty = FALSE; |
832 } | |
833 } | |
834 | |
835 return empty; | |
781 } | 836 } |
782 | 837 |
783 | 838 |
784 /* Check if two given patterns are dupes | 839 /* Check if two given patterns are dupes |
785 */ | 840 */ |
786 BOOL comparePattern(const JSSPattern *pat1, const JSSPattern *pat2) | 841 BOOL jssComparePattern(const JSSPattern *pat1, const JSSPattern *pat2) |
787 { | 842 { |
788 return | 843 return |
789 pat1->nrows == pat2->nrows && | 844 pat1->nrows == pat2->nrows && |
790 pat1->nchannels == pat2->nchannels && | 845 pat1->nchannels == pat2->nchannels && |
791 memcmp(pat1->data, pat2->data, sizeof(JSSNote) * pat1->nrows * pat1->nchannels) == 0; | 846 memcmp(pat1->data, pat2->data, sizeof(JSSNote) * pat1->nrows * pat1->nchannels) == 0; |
792 } | 847 } |
793 | 848 |
794 | 849 |
795 /* Optimize a given module | 850 /* Optimize a given module |
796 */ | 851 */ |
797 JSSModule *optimizeModule(JSSModule *m) | 852 JSSModule *jssOptimizeModule(JSSModule *m) |
798 { | 853 { |
799 BOOL usedPatterns[jsetMaxPatterns + 1], | 854 BOOL usedPatterns[jsetMaxPatterns + 1], |
800 usedInstruments[jsetMaxInstruments + 1], | 855 usedInstruments[jsetMaxInstruments + 1], |
801 usedExtInstruments[jsetMaxInstruments + 1], | 856 usedExtInstruments[jsetMaxInstruments + 1]; |
802 usedChannels[jsetMaxChannels]; | |
803 int mapExtInstruments[jsetMaxInstruments + 1], | 857 int mapExtInstruments[jsetMaxInstruments + 1], |
804 mapInstruments[jsetMaxInstruments + 1], | 858 mapInstruments[jsetMaxInstruments + 1], |
805 mapPatterns[jsetMaxPatterns + 1], | 859 mapPatterns[jsetMaxPatterns + 1], |
806 dupPatterns[jsetMaxPatterns + 1]; | 860 dupPatterns[jsetMaxPatterns + 1]; |
807 | 861 |
825 r->norders = m->norders; | 879 r->norders = m->norders; |
826 | 880 |
827 for (int i = 0; i < jsetNChannels; i++) | 881 for (int i = 0; i < jsetNChannels; i++) |
828 { | 882 { |
829 r->defPanning[i] = m->defPanning[i]; | 883 r->defPanning[i] = m->defPanning[i]; |
830 usedChannels[i] = FALSE; | |
831 } | 884 } |
832 | 885 |
833 // Initialize values | 886 // Initialize values |
834 for (int i = 0; i <= jsetMaxInstruments; i++) | 887 for (int i = 0; i <= jsetMaxInstruments; i++) |
835 { | 888 { |
857 if (npat >= 0 && npat < m->npatterns) | 910 if (npat >= 0 && npat < m->npatterns) |
858 { | 911 { |
859 JSSPattern *pattern = m->patterns[npat]; | 912 JSSPattern *pattern = m->patterns[npat]; |
860 if (pattern != NULL) | 913 if (pattern != NULL) |
861 { | 914 { |
862 BOOL empty; | 915 // Scan for used instruments etc |
863 | 916 BOOL empty = jssScanPattern(m, pattern, npat, usedExtInstruments, NULL); |
864 // Mark this pattern as used | |
865 usedPatterns[npat] = TRUE; | |
866 | |
867 // Scan for used instruments and channels | |
868 scanPattern(m, pattern, npat, usedExtInstruments, usedChannels, &empty); | |
869 | 917 |
870 // Empty patterns with known number of rows are "removed" | 918 // Empty patterns with known number of rows are "removed" |
871 if (empty && pattern->nrows == jsetDefaultRows) | 919 if (empty && pattern->nrows == jsetDefaultRows) |
872 { | 920 { |
873 m->orderList[norder] = jsetNotSet; | 921 m->orderList[norder] = jsetNotSet; |
874 usedPatterns[npat] = FALSE; | 922 usedPatterns[npat] = FALSE; |
875 } | 923 } |
924 else | |
925 usedPatterns[npat] = TRUE; | |
876 } | 926 } |
877 else | 927 else |
878 { | 928 { |
879 dmErrorMsg("Pattern 0x%x is used on order 0x%x, but has no data!\n", | 929 dmErrorMsg("Pattern 0x%x is used on order 0x%x, but has no data!\n", |
880 npat, norder); | 930 npat, norder); |
949 | 999 |
950 // Check for duplicate patterns of "pat1" and mark them as such | 1000 // Check for duplicate patterns of "pat1" and mark them as such |
951 for (int pat2 = 0; pat2 < m->npatterns; pat2++) | 1001 for (int pat2 = 0; pat2 < m->npatterns; pat2++) |
952 if (pat1 != pat2 && m->patterns[pat2] != NULL && | 1002 if (pat1 != pat2 && m->patterns[pat2] != NULL && |
953 dupPatterns[pat2] == jsetNotSet && | 1003 dupPatterns[pat2] == jsetNotSet && |
954 comparePattern(m->patterns[pat1], m->patterns[pat2])) | 1004 jssComparePattern(m->patterns[pat1], m->patterns[pat2])) |
955 { | 1005 { |
956 dmPrint(1, " * %d and %d are dupes.\n", pat1, pat2); | 1006 dmPrint(1, " * %d and %d are dupes.\n", pat1, pat2); |
957 dupPatterns[pat2] = pat1; | 1007 dupPatterns[pat2] = pat1; |
958 ndupes++; | 1008 ndupes++; |
959 } | 1009 } |
1075 dmPrint(2, "\n"); | 1125 dmPrint(2, "\n"); |
1076 dmMsg(1, "%d extended instruments (%d unused).\n", | 1126 dmMsg(1, "%d extended instruments (%d unused).\n", |
1077 r->nextInstruments, nunused); | 1127 r->nextInstruments, nunused); |
1078 | 1128 |
1079 // | 1129 // |
1080 // Check for actually used channels | |
1081 // XXX TODO: Actually remove the unused channels. | |
1082 // | |
1083 nunused = 0; | |
1084 for (int i = 0; i < r->nchannels; i++) | |
1085 { | |
1086 if(!usedChannels[i]) | |
1087 nunused++; | |
1088 } | |
1089 dmMsg(1, "%d channels (%d unused).\n", | |
1090 r->nchannels - nunused, nunused); | |
1091 | |
1092 // | |
1093 // Remap pattern data with remapped instrument data | 1130 // Remap pattern data with remapped instrument data |
1094 // | 1131 // |
1095 for (int i = 0; i < r->npatterns; i++) | 1132 for (int i = 0; i < r->npatterns; i++) |
1096 { | 1133 { |
1097 JSSPattern *p = r->patterns[i]; | 1134 JSSPattern *p = r->patterns[i]; |
1148 r->orderList[i] = map; | 1185 r->orderList[i] = map; |
1149 } | 1186 } |
1150 if (nunused) | 1187 if (nunused) |
1151 dmPrint(2, "\n"); | 1188 dmPrint(2, "\n"); |
1152 | 1189 |
1190 // | |
1191 // Do final pass on patterns to remove unused channels | |
1192 // | |
1193 for (int i = 0; i < r->npatterns; i++) | |
1194 { | |
1195 JSSPattern *p = r->patterns[i]; | |
1196 | |
1197 jssScanPattern(r, p, i, NULL, p->used); | |
1198 | |
1199 p->nmap = 0; | |
1200 for (int i = 0; i < r->nchannels; i++) | |
1201 { | |
1202 if (p->used[i]) | |
1203 p->map[p->nmap++] = i; | |
1204 } | |
1205 | |
1206 if (p->nmap != p->nchannels) | |
1207 { | |
1208 dmMsg(2, "Pattern %d: %d/%d used channels (%d unused).\n", | |
1209 i, p->nchannels - p->nmap, p->nchannels, p->nmap); | |
1210 } | |
1211 } | |
1212 | |
1153 return r; | 1213 return r; |
1154 } | 1214 } |
1155 | 1215 |
1156 | 1216 |
1157 int main(int argc, char *argv[]) | 1217 int main(int argc, char *argv[]) |
1159 DMResource *inFile = NULL; | 1219 DMResource *inFile = NULL; |
1160 FILE *outFile = NULL; | 1220 FILE *outFile = NULL; |
1161 JSSModule *sm, *dm; | 1221 JSSModule *sm, *dm; |
1162 int result; | 1222 int result; |
1163 | 1223 |
1164 dmInitProg("xm2jss", "XM to JSSMOD converter", "0.7", NULL, NULL); | 1224 dmInitProg("xm2jss", "XM to JSSMOD converter", "0.8", NULL, NULL); |
1165 dmVerbosity = 0; | 1225 dmVerbosity = 0; |
1166 | 1226 |
1167 // Parse arguments | 1227 // Parse arguments |
1168 if (!dmArgsProcess(argc, argv, optList, optListN, | 1228 if (!dmArgsProcess(argc, argv, optList, optListN, |
1169 argHandleOpt, argHandleFile, OPTH_BAILOUT)) | 1229 argHandleOpt, argHandleFile, OPTH_BAILOUT)) |
1250 | 1310 |
1251 // Run the optimization procedure | 1311 // Run the optimization procedure |
1252 if (optOptimize) | 1312 if (optOptimize) |
1253 { | 1313 { |
1254 dmMsg(1, "Optimizing module data...\n"); | 1314 dmMsg(1, "Optimizing module data...\n"); |
1255 dm = optimizeModule(sm); | 1315 dm = jssOptimizeModule(sm); |
1256 } else | 1316 } else |
1257 dm = sm; | 1317 dm = sm; |
1258 | 1318 |
1259 // Write output file | 1319 // Write output file |
1260 if ((outFile = fopen(optOutFilename, "wb")) == NULL) | 1320 if ((outFile = fopen(optOutFilename, "wb")) == NULL) |