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");