Mercurial > hg > dmlib
comparison tools/xm2jss.c @ 2586:9807ae37ad69
Require stdbool.h, we require C11 now.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 08 Dec 2022 15:59:22 +0200 |
parents | d56a0e86067a |
children |
comparison
equal
deleted
inserted
replaced
2585:ef6c826c5b7a | 2586:9807ae37ad69 |
---|---|
21 static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 21 static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
22 #define JM_SAMPLE_MODE_MASK (jsampFlipSign | jsampSwapEndianess | jsampSplit | jsampDelta) | 22 #define JM_SAMPLE_MODE_MASK (jsampFlipSign | jsampSwapEndianess | jsampSplit | jsampDelta) |
23 | 23 |
24 | 24 |
25 char *optInFilename = NULL, *optOutFilename = NULL; | 25 char *optInFilename = NULL, *optOutFilename = NULL; |
26 BOOL optIgnoreErrors = FALSE, | 26 bool optIgnoreErrors = false, |
27 optStripExtInstr = FALSE, | 27 optStripExtInstr = false, |
28 optStripInstr = FALSE, | 28 optStripInstr = false, |
29 optStripSamples = FALSE, | 29 optStripSamples = false, |
30 optOptimize = FALSE; | 30 optOptimize = false; |
31 | 31 |
32 int optPatternMode = PATMODE_COMP_HORIZ, | 32 int optPatternMode = PATMODE_COMP_HORIZ, |
33 optSampMode16 = jsampDelta, | 33 optSampMode16 = jsampDelta, |
34 optSampMode8 = jsampFlipSign | jsampDelta; | 34 optSampMode8 = jsampFlipSign | jsampDelta; |
35 | 35 |
84 " 8 = Split and de-interleave hi/lo bytes (affects 16-bit only)\n" | 84 " 8 = Split and de-interleave hi/lo bytes (affects 16-bit only)\n" |
85 "\n" | 85 "\n" |
86 ); | 86 ); |
87 } | 87 } |
88 | 88 |
89 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) | 89 bool argHandleOpt(const int optN, char *optArg, char *currArg) |
90 { | 90 { |
91 switch (optN) | 91 switch (optN) |
92 { | 92 { |
93 case 0: | 93 case 0: |
94 argShowHelp(); | 94 argShowHelp(); |
103 case 2: | 103 case 2: |
104 dmVerbosity++; | 104 dmVerbosity++; |
105 break; | 105 break; |
106 | 106 |
107 case 10: | 107 case 10: |
108 optIgnoreErrors = TRUE; | 108 optIgnoreErrors = true; |
109 break; | 109 break; |
110 | 110 |
111 case 12: | 111 case 12: |
112 optPatternMode = atoi(optArg); | 112 optPatternMode = atoi(optArg); |
113 if (optPatternMode <= 0 || optPatternMode >= PATMODE_LAST) | 113 if (optPatternMode <= 0 || optPatternMode >= PATMODE_LAST) |
114 { | 114 { |
115 dmErrorMsg("Unknown pattern conversion mode %d\n", optPatternMode); | 115 dmErrorMsg("Unknown pattern conversion mode %d\n", optPatternMode); |
116 return FALSE; | 116 return false; |
117 } | 117 } |
118 break; | 118 break; |
119 | 119 |
120 case 14: optStripExtInstr = TRUE; break; | 120 case 14: optStripExtInstr = true; break; |
121 case 16: optStripInstr = TRUE; break; | 121 case 16: optStripInstr = true; break; |
122 case 18: optStripSamples = TRUE; break; | 122 case 18: optStripSamples = true; break; |
123 | 123 |
124 case 20: optSampMode8 = atoi(optArg) & JM_SAMPLE_MODE_MASK; break; | 124 case 20: optSampMode8 = atoi(optArg) & JM_SAMPLE_MODE_MASK; break; |
125 case 22: optSampMode16 = atoi(optArg) & JM_SAMPLE_MODE_MASK; break; | 125 case 22: optSampMode16 = atoi(optArg) & JM_SAMPLE_MODE_MASK; break; |
126 | 126 |
127 case 24: optOptimize = TRUE; break; | 127 case 24: optOptimize = true; break; |
128 | 128 |
129 default: | 129 default: |
130 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); | 130 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); |
131 return FALSE; | 131 return false; |
132 } | 132 } |
133 | 133 |
134 return TRUE; | 134 return true; |
135 } | 135 } |
136 | 136 |
137 | 137 |
138 BOOL argHandleFile(char *currArg) | 138 bool argHandleFile(char *currArg) |
139 { | 139 { |
140 // Was not option argument | 140 // Was not option argument |
141 if (!optInFilename) | 141 if (!optInFilename) |
142 optInFilename = currArg; | 142 optInFilename = currArg; |
143 else | 143 else |
144 if (!optOutFilename) | 144 if (!optOutFilename) |
145 optOutFilename = currArg; | 145 optOutFilename = currArg; |
146 else | 146 else |
147 { | 147 { |
148 dmErrorMsg("Too many filename arguments specified, '%s'.\n", currArg); | 148 dmErrorMsg("Too many filename arguments specified, '%s'.\n", currArg); |
149 return FALSE; | 149 return false; |
150 } | 150 } |
151 | 151 |
152 return TRUE; | 152 return true; |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 static inline const JSSNote * jssGetNotePtr(const JSSPattern *pattern, const int channel, const int row) | 156 static inline const JSSNote * jssGetNotePtr(const JSSPattern *pattern, const int channel, const int row) |
157 { | 157 { |
163 | 163 |
164 | 164 |
165 /* These functions and the macro mess are meant to make the | 165 /* These functions and the macro mess are meant to make the |
166 * conversion routines themselves clearer and simpler. | 166 * conversion routines themselves clearer and simpler. |
167 */ | 167 */ |
168 BOOL jsPutByte(Uint8 *patBuf, size_t patBufSize, size_t *npatBuf, Uint8 val) | 168 bool jsPutByte(Uint8 *patBuf, size_t patBufSize, size_t *npatBuf, Uint8 val) |
169 { | 169 { |
170 if (*npatBuf >= patBufSize) | 170 if (*npatBuf >= patBufSize) |
171 return FALSE; | 171 return false; |
172 else | 172 else |
173 { | 173 { |
174 patBuf[*npatBuf] = val; | 174 patBuf[*npatBuf] = val; |
175 (*npatBuf)++; | 175 (*npatBuf)++; |
176 return TRUE; | 176 return true; |
177 } | 177 } |
178 } | 178 } |
179 | 179 |
180 #define JSPUTBYTE(x) do { if (!jsPutByte(patBuf, patBufSize, patSize, x)) return DMERR_BOUNDS; } while (0) | 180 #define JSPUTBYTE(x) do { if (!jsPutByte(patBuf, patBufSize, patSize, x)) return DMERR_BOUNDS; } while (0) |
181 | 181 |
508 | 508 |
509 #undef JSFOREACHNOTE1 | 509 #undef JSFOREACHNOTE1 |
510 #undef JSFOREACHNOTE2 | 510 #undef JSFOREACHNOTE2 |
511 | 511 |
512 | 512 |
513 static BOOL jssMODWriteEnvelope(DMResource *outFile, const JSSEnvelope *env, const char *name, const int ninst) | 513 static bool jssMODWriteEnvelope(DMResource *outFile, const JSSEnvelope *env, const char *name, const int ninst) |
514 { | 514 { |
515 BOOL ok = | 515 bool ok = |
516 dmf_write_byte(outFile, env->flags) && | 516 dmf_write_byte(outFile, env->flags) && |
517 dmf_write_byte(outFile, env->npoints) && | 517 dmf_write_byte(outFile, env->npoints) && |
518 dmf_write_byte(outFile, env->sustain) && | 518 dmf_write_byte(outFile, env->sustain) && |
519 dmf_write_byte(outFile, env->loopS) && | 519 dmf_write_byte(outFile, env->loopS) && |
520 dmf_write_byte(outFile, env->loopE); | 520 dmf_write_byte(outFile, env->loopE); |
743 "Extended instrument #%d is NULL!\n", | 743 "Extended instrument #%d is NULL!\n", |
744 index); | 744 index); |
745 } | 745 } |
746 | 746 |
747 // Misc data | 747 // Misc data |
748 BOOL ok = | 748 bool ok = |
749 dmf_write_byte(outFile, einst->nsamples) && | 749 dmf_write_byte(outFile, einst->nsamples) && |
750 dmf_write_byte(outFile, einst->vibratoType) && | 750 dmf_write_byte(outFile, einst->vibratoType) && |
751 dmf_write_le16(outFile, einst->vibratoSweep) && | 751 dmf_write_le16(outFile, einst->vibratoSweep) && |
752 dmf_write_le16(outFile, einst->vibratoDepth) && | 752 dmf_write_le16(outFile, einst->vibratoDepth) && |
753 dmf_write_le16(outFile, einst->vibratoRate) && | 753 dmf_write_le16(outFile, einst->vibratoRate) && |
861 | 861 |
862 | 862 |
863 /* Scan given pattern for used instruments and channels. | 863 /* Scan given pattern for used instruments and channels. |
864 * Also checks if the pattern is empty. | 864 * Also checks if the pattern is empty. |
865 */ | 865 */ |
866 BOOL jssScanPattern(const JSSModule *module, const JSSPattern *pattern, | 866 bool jssScanPattern(const JSSModule *module, const JSSPattern *pattern, |
867 const int npattern, BOOL *usedExtInstruments, BOOL *usedChannels) | 867 const int npattern, bool *usedExtInstruments, bool *usedChannels) |
868 { | 868 { |
869 JSSNote *n = pattern->data; | 869 JSSNote *n = pattern->data; |
870 BOOL empty = TRUE; | 870 bool empty = true; |
871 | 871 |
872 // Check all notes in this pattern | 872 // Check all notes in this pattern |
873 for (int row = 0; row < pattern->nrows; row++) | 873 for (int row = 0; row < pattern->nrows; row++) |
874 for (int channel = 0; channel < pattern->nchannels; channel++, n++) | 874 for (int channel = 0; channel < pattern->nchannels; channel++, n++) |
875 { | 875 { |
877 if (usedExtInstruments != NULL && | 877 if (usedExtInstruments != NULL && |
878 n->instrument != jsetNotSet) | 878 n->instrument != jsetNotSet) |
879 { | 879 { |
880 // Is it valid? | 880 // Is it valid? |
881 if (n->instrument >= 0 && n->instrument < module->nextInstruments) | 881 if (n->instrument >= 0 && n->instrument < module->nextInstruments) |
882 usedExtInstruments[n->instrument] = TRUE; | 882 usedExtInstruments[n->instrument] = true; |
883 else | 883 else |
884 { | 884 { |
885 dmMsg(2, "Pattern 0x%x, row=0x%x, chn=%d has invalid instrument 0x%x\n", | 885 dmMsg(2, "Pattern 0x%x, row=0x%x, chn=%d has invalid instrument 0x%x\n", |
886 npattern + 1, row, channel, n->instrument + 1); | 886 npattern + 1, row, channel, n->instrument + 1); |
887 } | 887 } |
893 n->volume != jsetNotSet || | 893 n->volume != jsetNotSet || |
894 n->effect != jsetNotSet || | 894 n->effect != jsetNotSet || |
895 n->param != jsetNotSet) | 895 n->param != jsetNotSet) |
896 { | 896 { |
897 if (usedChannels != NULL) | 897 if (usedChannels != NULL) |
898 usedChannels[channel] = TRUE; | 898 usedChannels[channel] = true; |
899 | 899 |
900 empty = FALSE; | 900 empty = false; |
901 } | 901 } |
902 } | 902 } |
903 | 903 |
904 return empty; | 904 return empty; |
905 } | 905 } |
906 | 906 |
907 | 907 |
908 /* Check if two given patterns are dupes | 908 /* Check if two given patterns are dupes |
909 */ | 909 */ |
910 BOOL jssComparePattern(const JSSPattern *pat1, const JSSPattern *pat2) | 910 bool jssComparePattern(const JSSPattern *pat1, const JSSPattern *pat2) |
911 { | 911 { |
912 return | 912 return |
913 pat1->nrows == pat2->nrows && | 913 pat1->nrows == pat2->nrows && |
914 pat1->nchannels == pat2->nchannels && | 914 pat1->nchannels == pat2->nchannels && |
915 memcmp(pat1->data, pat2->data, sizeof(JSSNote) * pat1->nrows * pat1->nchannels) == 0; | 915 memcmp(pat1->data, pat2->data, sizeof(JSSNote) * pat1->nrows * pat1->nchannels) == 0; |
925 * | 925 * |
926 * This should be re-written to copy the data instead. | 926 * This should be re-written to copy the data instead. |
927 */ | 927 */ |
928 JSSModule *jssOptimizeModule(JSSModule *src) | 928 JSSModule *jssOptimizeModule(JSSModule *src) |
929 { | 929 { |
930 BOOL usedPatterns[jsetMaxPatterns + 1], | 930 bool usedPatterns[jsetMaxPatterns + 1], |
931 usedInstruments[jsetMaxInstruments + 1], | 931 usedInstruments[jsetMaxInstruments + 1], |
932 usedExtInstruments[jsetMaxInstruments + 1]; | 932 usedExtInstruments[jsetMaxInstruments + 1]; |
933 int mapExtInstruments[jsetMaxInstruments + 1], | 933 int mapExtInstruments[jsetMaxInstruments + 1], |
934 mapInstruments[jsetMaxInstruments + 1], | 934 mapInstruments[jsetMaxInstruments + 1], |
935 mapPatterns[jsetMaxPatterns + 1], | 935 mapPatterns[jsetMaxPatterns + 1], |
960 } | 960 } |
961 | 961 |
962 // Initialize values | 962 // Initialize values |
963 for (int i = 0; i <= jsetMaxInstruments; i++) | 963 for (int i = 0; i <= jsetMaxInstruments; i++) |
964 { | 964 { |
965 usedExtInstruments[i] = FALSE; | 965 usedExtInstruments[i] = false; |
966 usedInstruments[i] = FALSE; | 966 usedInstruments[i] = false; |
967 mapExtInstruments[i] = jsetNotSet; | 967 mapExtInstruments[i] = jsetNotSet; |
968 mapInstruments[i] = jsetNotSet; | 968 mapInstruments[i] = jsetNotSet; |
969 } | 969 } |
970 | 970 |
971 for (int i = 0; i <= jsetMaxPatterns; i++) | 971 for (int i = 0; i <= jsetMaxPatterns; i++) |
972 { | 972 { |
973 usedPatterns[i] = FALSE; | 973 usedPatterns[i] = false; |
974 mapPatterns[i] = jsetNotSet; | 974 mapPatterns[i] = jsetNotSet; |
975 dupPatterns[i] = jsetNotSet; | 975 dupPatterns[i] = jsetNotSet; |
976 } | 976 } |
977 | 977 |
978 // | 978 // |
987 { | 987 { |
988 JSSPattern *pattern = src->patterns[npat]; | 988 JSSPattern *pattern = src->patterns[npat]; |
989 if (pattern != NULL) | 989 if (pattern != NULL) |
990 { | 990 { |
991 // Scan for used instruments etc | 991 // Scan for used instruments etc |
992 BOOL empty = jssScanPattern(src, pattern, npat, usedExtInstruments, NULL); | 992 bool empty = jssScanPattern(src, pattern, npat, usedExtInstruments, NULL); |
993 | 993 |
994 // Empty patterns with known number of rows are "removed" | 994 // Empty patterns with known number of rows are "removed" |
995 if (empty && pattern->nrows == jsetDefaultRows) | 995 if (empty && pattern->nrows == jsetDefaultRows) |
996 { | 996 { |
997 src->orderList[norder] = jsetNotSet; | 997 src->orderList[norder] = jsetNotSet; |
998 usedPatterns[npat] = FALSE; | 998 usedPatterns[npat] = false; |
999 } | 999 } |
1000 else | 1000 else |
1001 usedPatterns[npat] = TRUE; | 1001 usedPatterns[npat] = true; |
1002 } | 1002 } |
1003 else | 1003 else |
1004 { | 1004 { |
1005 dmErrorMsg("Pattern 0x%x is used on order 0x%x, but has no data!\n", | 1005 dmErrorMsg("Pattern 0x%x is used on order 0x%x, but has no data!\n", |
1006 npat, norder); | 1006 npat, norder); |
1033 if (eip->sNumForNotes[note] != jsetNotSet) | 1033 if (eip->sNumForNotes[note] != jsetNotSet) |
1034 { | 1034 { |
1035 int q = eip->sNumForNotes[note]; | 1035 int q = eip->sNumForNotes[note]; |
1036 if (q >= 0 && q < src->ninstruments) | 1036 if (q >= 0 && q < src->ninstruments) |
1037 { | 1037 { |
1038 usedInstruments[q] = TRUE; | 1038 usedInstruments[q] = true; |
1039 } | 1039 } |
1040 else | 1040 else |
1041 { | 1041 { |
1042 dmErrorMsg("Ext.instrument #%d sNumForNotes[%d] value out range (%d < %d).\n", | 1042 dmErrorMsg("Ext.instrument #%d sNumForNotes[%d] value out range (%d < %d).\n", |
1043 neinst + 1, note, src->ninstruments, q + 1); | 1043 neinst + 1, note, src->ninstruments, q + 1); |
1329 // Initialize miniJSS | 1329 // Initialize miniJSS |
1330 jssInit(); | 1330 jssInit(); |
1331 | 1331 |
1332 // Read file | 1332 // Read file |
1333 dmMsg(1, "Reading XM-format file ...\n"); | 1333 dmMsg(1, "Reading XM-format file ...\n"); |
1334 res = jssLoadXM(inFile, &src, FALSE); | 1334 res = jssLoadXM(inFile, &src, false); |
1335 dmf_close(inFile); | 1335 dmf_close(inFile); |
1336 if (res != 0) | 1336 if (res != 0) |
1337 { | 1337 { |
1338 dmErrorMsg("Error while loading XM file (%d), ", res); | 1338 dmErrorMsg("Error while loading XM file (%d), ", res); |
1339 if (optIgnoreErrors) | 1339 if (optIgnoreErrors) |
1344 goto out; | 1344 goto out; |
1345 } | 1345 } |
1346 } | 1346 } |
1347 | 1347 |
1348 // Check stripping settings | 1348 // Check stripping settings |
1349 if (optStripExtInstr) optStripInstr = TRUE; | 1349 if (optStripExtInstr) optStripInstr = true; |
1350 if (optStripInstr) optStripSamples = TRUE; | 1350 if (optStripInstr) optStripSamples = true; |
1351 | 1351 |
1352 // Remove samples | 1352 // Remove samples |
1353 if (optStripSamples) | 1353 if (optStripSamples) |
1354 { | 1354 { |
1355 dmMsg(1, "Stripping samples...\n"); | 1355 dmMsg(1, "Stripping samples...\n"); |