History

Pushed v1.15 code

- More improvements to S3M loader. Fixes "satellite one.s3m" and other S3Ms. - Up/down pushbutton delay has been increased even more, to prevent accidentally skipping too much. - Some other small miscellaneous changes not worth of a mention

Olav Sørensen committed 6 years ago

Commit 108c3331 parent aaa773b25 files · +435 −644Browse files

Showing the changes to src/ft2_module_loader.c (1 of 25 files). Show all

Unified · Split

src/ft2_module_loader.c+163−298
@@ -184,7 +184,7 @@ static uint8_t getModType(uint8_t *numChannels, const char *id) · 183 unmodified lines
184 184
185 if (IS_ID("M.K.", id) || IS_ID("M!K!", id) || IS_ID("NSMS", id) || IS_ID("LARD", id) || IS_ID("PATT", id))185 if (IS_ID("M.K.", id) || IS_ID("M!K!", id) || IS_ID("NSMS", id) || IS_ID("LARD", id) || IS_ID("PATT", id))
186 {186 {
187 modFormat = FORMAT_MK; // ProTracker or compatible 187 modFormat = FORMAT_MK; // ProTracker or compatible
188 }188 }
189 else if (id[1] == 'C' && id[2] == 'H' && id[3] == 'N')189 else if (id[1] == 'C' && id[2] == 'H' && id[3] == 'N')
190 {190 {
@@ -200,11 +200,6 @@ static uint8_t getModType(uint8_t *numChannels, const char *id) · 9 unmodified lines
200 {200 {
201 modFormat = FORMAT_FLT; // StarTrekker (4-channel modules only)201 modFormat = FORMAT_FLT; // StarTrekker (4-channel modules only)
202 }202 }
203 else if (IS_ID("FLT8", id))
204 {
205 modFormat = FORMAT_FLT; // StarTrekker (4-channel modules only)
206 *numChannels = 8;
207 }
208 else if (IS_ID("N.T.", id))203 else if (IS_ID("N.T.", id))
209 {204 {
210 modFormat = FORMAT_NT; // NoiseTracker205 modFormat = FORMAT_NT; // NoiseTracker
@@ -364,23 +359,23 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 153 unmodified lines
364 */359 */
365 modFormat = FORMAT_STK;360 modFormat = FORMAT_STK;
366 361
367 if (h_MOD15.repS == 0)362 if (songTmp.repS == 0)
368 h_MOD15.repS = 120;363 songTmp.repS = 120;
369 364
370 // jjk55.mod by Jesper Kyd has a bogus STK tempo value that should be ignored365 // jjk55.mod by Jesper Kyd has a bogus STK tempo value that should be ignored (hackish!)
371 if (!strcmp("jjk55", h_MOD31.name))366 if (!strcmp("jjk55", h_MOD31.name))
372 h_MOD15.repS = 120;367 songTmp.repS = 120;
373 368
374 // The "restart pos" field in STK is the inital tempo (must be converted to BPM first)369 // The "restart pos" field in STK is the inital tempo (must be converted to BPM first)
375 if (h_MOD15.repS != 120) // 120 is a special case and means 50Hz (125BPM)370 if (songTmp.repS != 120) // 120 is a special case and means 50Hz (125BPM)
376 {371 {
377 if (h_MOD15.repS > 220)372 if (songTmp.repS > 220)
378 h_MOD15.repS = 220;373 songTmp.repS = 220;
379 374
380 // convert UST tempo to BPM375 // convert UST tempo to BPM
381 uint16_t ciaPeriod = (240 - songTmp.repS) * 122;376 uint16_t ciaPeriod = (240 - songTmp.repS) * 122;
382 double dHz = 709379.0 / ciaPeriod;377 double dHz = 709379.0 / ciaPeriod;
383 int32_t BPM = (int32_t)((dHz * (125.0 / 50.0)) + 0.5);378 int32_t BPM = (int32_t)((dHz * 2.5) + 0.5);
384 379
385 songTmp.speed = (uint16_t)BPM;380 songTmp.speed = (uint16_t)BPM;
386 }381 }
@@ -450,7 +445,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 63 unmodified lines
450 ton->effTyp = bytes[2] & 0x0F;445 ton->effTyp = bytes[2] & 0x0F;
451 ton->eff = bytes[3];446 ton->eff = bytes[3];
452 447
453 if (mightBeSTK)448 if (modFormat == FORMAT_STK)
454 {449 {
455 if (ton->effTyp == 0xC || ton->effTyp == 0xD || ton->effTyp == 0xE)450 if (ton->effTyp == 0xC || ton->effTyp == 0xD || ton->effTyp == 0xE)
456 {451 {
@@ -519,7 +514,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 62 unmodified lines
519 }514 }
520 515
521 // pattern command conversion for non-PT formats516 // pattern command conversion for non-PT formats
522 if (modFormat == FORMAT_STK || modFormat == FORMAT_FT2 || modFormat == FORMAT_NT || modFormat == FORMAT_HMNT || modFormat == FORMAT_FLT)517 if (modFormat == FORMAT_STK || modFormat == FORMAT_NT || modFormat == FORMAT_HMNT || modFormat == FORMAT_FLT)
523 {518 {
524 for (a = 0; a < b; a++)519 for (a = 0; a < b; a++)
525 {520 {
@@ -690,7 +685,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 164 unmodified lines
690 /* For Ultimate SoundTracker modules, only the loop area of a looped sample is played.685 /* For Ultimate SoundTracker modules, only the loop area of a looped sample is played.
691 ** Skip loading of eventual data present before loop start.686 ** Skip loading of eventual data present before loop start.
692 */687 */
693 if (modFormat == FORMAT_STK && (s->repS > 0 && s->repL < s->len))688 if (modFormat == FORMAT_STK && s->repS > 0 && s->repL < s->len)
694 {689 {
695 s->len -= s->repS;690 s->len -= s->repS;
696 fseek(f, s->repS, SEEK_CUR);691 fseek(f, s->repS, SEEK_CUR);
@@ -705,7 +700,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 8 unmodified lines
705 }700 }
706 701
707 // clear repL and repS on non-looping samples...702 // clear repL and repS on non-looping samples...
708 if ((s->typ & 3) == 0)703 if (s->typ == 0)
709 {704 {
710 s->repL = 0;705 s->repL = 0;
711 s->repS = 0;706 s->repS = 0;
@@ -735,18 +730,15 @@ static uint8_t stmTempoToBPM(uint8_t tempo) // ported from original ST2.3 replay · 23 unmodified lines
735 uint16_t hz = 50;730 uint16_t hz = 50;
736 731
737 hz -= ((slowdowns[tempo >> 4] * (tempo & 15)) >> 4); // can and will underflow732 hz -= ((slowdowns[tempo >> 4] * (tempo & 15)) >> 4); // can and will underflow
738 733 bpm = (hz << 1) + (hz >> 1); // BPM = hz * 2.5
739 bpm = (int32_t)((hz * 2.5) + 0.5);
740 return (uint8_t)CLAMP(bpm, 32, 255); // result can be slightly off, but close enough...734 return (uint8_t)CLAMP(bpm, 32, 255); // result can be slightly off, but close enough...
741}735}
742 736
743static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread)737static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread)
744{738{
745 bool check3xx;739 uint8_t typ, tempo;
746 uint8_t typ, tmp8, tempo;
747 int16_t i, j, k, ai, ap, tmp;740 int16_t i, j, k, ai, ap, tmp;
748 uint16_t a;741 uint16_t a;
749 int32_t len;
750 tonTyp *ton;742 tonTyp *ton;
751 sampleTyp *s;743 sampleTyp *s;
752 songSTMHeaderTyp h_STM;744 songSTMHeaderTyp h_STM;
@@ -887,19 +879,6 @@ static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) · 134 unmodified lines
887 ton->eff = 0;879 ton->eff = 0;
888 }880 }
889 881
890 /* Remove any EDx with no note.
891 ** SDx with no note in ST3 = does nothing
892 ** EDx with no note in FT2 = still retriggers
893 */
894 if (ton->effTyp == 0xE && (ton->eff & 0xF0) == 0xD0)
895 {
896 if (ton->ton == 0 || ton->ton == 97)
897 {
898 ton->eff = 0;
899 ton->effTyp = 0;
900 }
901 }
902
903 if (ton->effTyp > 35)882 if (ton->effTyp > 35)
904 {883 {
905 ton->effTyp = 0;884 ton->effTyp = 0;
@@ -986,77 +965,6 @@ static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) · 80 unmodified lines
986 }965 }
987 }966 }
988 967
989 // non-FT2: fix overflown 9xx and illegal 3xx
990
991 for (i = 0; i < ap; i++)
992 {
993 if (pattTmp[i] == NULL)
994 continue;
995
996 for (k = 0; k < songTmp.antChn; k++)
997 {
998 check3xx = false;
999 for (j = 0; j < 64; j++)
1000 {
1001 ton = &pattTmp[i][(j * MAX_VOICES) + k];
1002
1003 if (ton->ton > 0 && ton->ton < 97 && ton->effTyp != 0x3)
1004 check3xx = true;
1005
1006 if (ton->ton > 0 && ton->ton < 97 && ton->effTyp == 0x3)
1007 check3xx = false;
1008
1009 if (check3xx && ton->effTyp == 0x3)
1010 {
1011 if (ton->ton == 0 || ton->ton == 97)
1012 {
1013 ton->effTyp = 0;
1014 ton->eff = 0;
1015 }
1016 }
1017
1018 if (ton->effTyp == 0x9 && ton->eff > 0)
1019 {
1020 if (ton->instr != 0 && ton->instr <= ai)
1021 {
1022 s = &instrTmp[ton->instr]->samp[0];
1023 len = s->len;
1024
1025 tmp8 = 0;
1026 if (len > 0)
1027 {
1028 tmp8 = ton->eff;
1029
1030 int32_t newLen = len >> 8;
1031 if (tmp8 >= newLen)
1032 {
1033 if (newLen < 1)
1034 tmp8 = 0;
1035 else
1036 tmp8 = (uint8_t)(newLen - 1);
1037 }
1038 }
1039
1040 if (tmp8 > 0)
1041 {
1042 ton->eff = tmp8;
1043 }
1044 else
1045 {
1046 ton->effTyp = 0;
1047 ton->eff = 0;
1048 }
1049 }
1050 else
1051 {
1052 ton->effTyp = 0;
1053 ton->eff = 0;
1054 }
1055 }
1056 }
1057 }
1058 }
1059
1060 fclose(f);968 fclose(f);
1061 969
1062 moduleLoaded = true;970 moduleLoaded = true;
@@ -1102,14 +1010,14 @@ static int8_t countS3MChannels(uint16_t antPtn) · 39 unmodified lines
1102static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread)1010static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread)
1103{1011{
1104 int8_t *tmpSmp;1012 int8_t *tmpSmp;
1105 bool check3xx, illegalUxx;1013 bool illegalUxx;
1106 uint8_t ha[2048];1014 uint8_t ha[2048];
1107 uint8_t s3mLastDEff[32], s3mLastEEff[32], s3mLastFEff[32];1015 uint8_t alastnfo[32], alastefx[32], alastvibnfo[32], s3mLastGInstr[32];
1108 uint8_t s3mLastSEff[32], s3mLastJEff[32], s3mLastGInstr[32], typ;1016 uint8_t typ;
1109 int16_t ai, ap, ver, ii, kk, tmp;1017 int16_t ai, ap, ver, ii, kk, tmp;
1110 uint16_t ptnOfs[256];1018 uint16_t ptnOfs[256];
1111 int32_t i, j, k, len;1019 int32_t i, j, k, len;
1112 tonTyp ton, *pattTon;1020 tonTyp ton;
1113 sampleTyp *s;1021 sampleTyp *s;
1114 songS3MHeaderTyp h_S3M;1022 songS3MHeaderTyp h_S3M;
1115 songS3MinstrHeaderTyp h_S3MInstr;1023 songS3MinstrHeaderTyp h_S3MInstr;
@@ -1143,13 +1051,7 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 27 unmodified lines
1143 goto s3mLoadError;1051 goto s3mLoadError;
1144 }1052 }
1145 1053
1146 // count real song table entries1054 songTmp.len = h_S3M.songTabLen;
1147 songTmp.len = 256;
1148 while (songTmp.len > 0 && songTmp.songTab[songTmp.len-1] == 255)
1149 songTmp.len--;
1150
1151 if (songTmp.len == 256)
1152 songTmp.len = 255;
1153 1055
1154 // remove pattern separators (254)1056 // remove pattern separators (254)
1155 k = 0;1057 k = 0;
@@ -1165,11 +1067,20 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 9 unmodified lines
1165 if (k <= songTmp.len)1067 if (k <= songTmp.len)
1166 songTmp.len -= (uint16_t)k;1068 songTmp.len -= (uint16_t)k;
1167 else1069 else
1168 songTmp.len = 0;1070 songTmp.len = 1;
1071
1072 for (i = 1; i < songTmp.len; i++)
1073 {
1074 if (songTmp.songTab[i] == 255)
1075 {
1076 songTmp.len = (uint16_t)i;
1077 break;
1078 }
1079 }
1169 1080
1170 // clear unused song table entries1081 // clear unused song table entries
1171 if (songTmp.len < 255)1082 if (songTmp.len < 255)
1172 memset(&songTmp.songTab[songTmp.len], 0, 256 - songTmp.len);1083 memset(&songTmp.songTab[songTmp.len], 0, 255-songTmp.len);
1173 1084
1174 songTmp.speed = h_S3M.defTempo;1085 songTmp.speed = h_S3M.defTempo;
1175 if (songTmp.speed < 32)1086 if (songTmp.speed < 32)
@@ -1226,11 +1137,9 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 50 unmodified lines
1226 if (ptnOfs[i] == 0)1137 if (ptnOfs[i] == 0)
1227 continue; // empty pattern1138 continue; // empty pattern
1228 1139
1229 memset(s3mLastDEff, 0, sizeof (s3mLastDEff));1140 memset(alastnfo, 0, sizeof (alastnfo));
1230 memset(s3mLastEEff, 0, sizeof (s3mLastEEff));1141 memset(alastefx, 0, sizeof (alastefx));
1231 memset(s3mLastFEff, 0, sizeof (s3mLastFEff));1142 memset(alastvibnfo, 0, sizeof (alastvibnfo));
1232 memset(s3mLastSEff, 0, sizeof (s3mLastSEff));
1233 memset(s3mLastJEff, 0, sizeof (s3mLastJEff));
1234 memset(s3mLastGInstr, 0, sizeof (s3mLastGInstr));1143 memset(s3mLastGInstr, 0, sizeof (s3mLastGInstr));
1235 1144
1236 fseek(f, ptnOfs[i] << 4, SEEK_SET);1145 fseek(f, ptnOfs[i] << 4, SEEK_SET);
@@ -1295,7 +1204,7 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 58 unmodified lines
1295 }1204 }
1296 }1205 }
1297 1206
1298 // volume1207 // volume column
1299 if (typ & 64)1208 if (typ & 64)
1300 {1209 {
1301 ton.vol = pattBuff[k++];1210 ton.vol = pattBuff[k++];
@@ -1312,28 +1221,42 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 10 unmodified lines
1312 ton.effTyp = pattBuff[k++];1221 ton.effTyp = pattBuff[k++];
1313 ton.eff = pattBuff[k++];1222 ton.eff = pattBuff[k++];
1314 1223
1315 if (ton.eff == 0)1224 if (ton.eff > 0)
1316 {1225 {
1317 if (ton.effTyp == 4)1226 alastnfo[ii] = ton.eff;
1318 {1227 if (ton.effTyp == 8 || ton.effTyp == 21)
1319 if ((s3mLastDEff[ii] & 0xF0) == 0xF0 || (s3mLastDEff[ii] & 0x0F) == 0x0F)1228 alastvibnfo[ii] = ton.eff; // H/U
1320 ton.eff = s3mLastDEff[ii];
1321 }
1322 else if (ton.effTyp == 5) ton.eff = s3mLastEEff[ii];
1323 else if (ton.effTyp == 6) ton.eff = s3mLastFEff[ii];
1324 else if (ton.effTyp == 10) ton.eff = s3mLastJEff[ii];
1325 else if (ton.effTyp == 19) ton.eff = s3mLastSEff[ii];
1326 }1229 }
1327 1230
1328 if (ton.eff != 0)1231 // in ST3, a lot of effects directly share the same memory!
1232 if (ton.eff == 0 && ton.effTyp != 7) // G
1329 {1233 {
1330 if (ton.effTyp == 4) s3mLastDEff[ii] = ton.eff;1234 uint8_t efx = ton.effTyp;
1331 else if (ton.effTyp == 5) s3mLastEEff[ii] = ton.eff;1235 if (efx == 8 || efx == 21) // H/U
1332 else if (ton.effTyp == 6) s3mLastFEff[ii] = ton.eff;1236 ton.eff = alastvibnfo[ii];
1333 else if (ton.effTyp == 10) s3mLastJEff[ii] = ton.eff;1237 else if ((efx >= 4 && efx <= 12) || (efx >= 17 && efx <= 19)) // D/E/F/I/J/K/L/Q/R/S
1334 else if (ton.effTyp == 19) s3mLastSEff[ii] = ton.eff;1238 ton.eff = alastnfo[ii];
1239
1240 /* If effect data is zero and effect type was the same as last one, clear out
1241 ** data if it's not J or S (those have no memory in the equivalent XM effects).
1242 ** Also goes for extra fine pitch slides and fine volume slides,
1243 ** since they get converted to other effects.
1244 */
1245 if (efx == alastefx[ii] && ton.effTyp != 10 && ton.effTyp != 19) // J/S
1246 {
1247 uint8_t nfo = ton.eff;
1248 bool extraFinePitchSlides = (efx == 5 || efx == 6) && ((nfo & 0xF0) == 0xE0);
1249 bool fineVolSlides = (efx == 4 || efx == 11) &&
1250 ((nfo > 0xF0) || (((nfo & 0xF) == 0xF) && ((nfo & 0xF0) > 0)));
1251
1252 if (!extraFinePitchSlides && !fineVolSlides)
1253 ton.eff = 0;
1254 }
1335 }1255 }
1336 1256
1257 if (ton.effTyp > 0)
1258 alastefx[ii] = ton.effTyp;
1259
1337 switch (ton.effTyp)1260 switch (ton.effTyp)
1338 {1261 {
1339 case 1: // A1262 case 1: // A
@@ -1351,14 +1274,12 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 11 unmodified lines
1351 case 3: ton.effTyp = 0xD; break; // C1274 case 3: ton.effTyp = 0xD; break; // C
1352 case 4: // D1275 case 4: // D
1353 {1276 {
1354 if ((ton.eff & 0xF0) == 0) ton.effTyp = 0xA;1277 if (ton.eff > 0xF0) // fine slide up
1355 else if ((ton.eff & 0x0F) == 0) ton.effTyp = 0xA;
1356 else if ((ton.eff & 0xF0) == 0xF0)
1357 {1278 {
1358 ton.effTyp = 0xE;1279 ton.effTyp = 0xE;
1359 ton.eff = 0xB0 | (ton.eff & 15);1280 ton.eff = 0xB0 | (ton.eff & 0xF);
1360 }1281 }
1361 else if ((ton.eff & 0x0F) == 0x0F)1282 else if ((ton.eff & 0x0F) == 0x0F && (ton.eff & 0xF0) > 0) // fine slide down
1362 {1283 {
1363 ton.effTyp = 0xE;1284 ton.effTyp = 0xE;
1364 ton.eff = 0xA0 | (ton.eff >> 4);1285 ton.eff = 0xA0 | (ton.eff >> 4);
@@ -1366,10 +1287,8 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 1 unmodified line
1366 else1287 else
1367 {1288 {
1368 ton.effTyp = 0xA;1289 ton.effTyp = 0xA;
1369 if (ton.eff & 0x0F)1290 if (ton.eff & 0x0F) // on D/K, last nybble has first priority in ST3
1370 ton.eff &= 0x0F;1291 ton.eff &= 0x0F;
1371 else
1372 ton.eff &= 0xF0;
1373 }1292 }
1374 }1293 }
1375 break;1294 break;
@@ -1379,6 +1298,7 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 3 unmodified lines
1379 {1298 {
1380 if ((ton.eff & 0xF0) >= 0xE0)1299 if ((ton.eff & 0xF0) >= 0xE0)
1381 {1300 {
1301 // convert to fine slide
1382 if ((ton.eff & 0xF0) == 0xE0)1302 if ((ton.eff & 0xF0) == 0xE0)
1383 tmp = 0x21;1303 tmp = 0x21;
1384 else1304 else
@@ -1392,9 +1312,15 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 7 unmodified lines
1392 ton.eff |= 0x10;1312 ton.eff |= 0x10;
1393 1313
1394 ton.effTyp = (uint8_t)tmp;1314 ton.effTyp = (uint8_t)tmp;
1315
1316 if (ton.effTyp == 0x21 && ton.eff == 0)
1317 {
1318 ton.effTyp = 0;
1319 }
1395 }1320 }
1396 else1321 else
1397 {1322 {
1323 // convert to normal 1xx/2xx slide
1398 ton.effTyp = 7 - ton.effTyp;1324 ton.effTyp = 7 - ton.effTyp;
1399 }1325 }
1400 }1326 }
@@ -1402,18 +1328,46 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 1 unmodified line
1402 1328
1403 case 7: // G1329 case 7: // G
1404 {1330 {
1331 ton.effTyp = 0x03;
1332
1405 // fix illegal slides (to new instruments)1333 // fix illegal slides (to new instruments)
1406 if (ton.instr != 0 && ton.instr != s3mLastGInstr[ii])1334 if (ton.instr != 0 && ton.instr != s3mLastGInstr[ii])
1407 ton.instr = s3mLastGInstr[ii];1335 ton.instr = s3mLastGInstr[ii];
1336 }
1337 break;
1408 1338
1409 ton.effTyp = 0x03;1339 case 11: // K
1340 {
1341 if (ton.eff > 0xF0) // fine slide up
1342 {
1343 ton.effTyp = 0xE;
1344 ton.eff = 0xB0 | (ton.eff & 0xF);
1345
1346 // if volume column is unoccupied, set to vibrato
1347 if (ton.vol == 0)
1348 ton.vol = 0xB0;
1349 }
1350 else if ((ton.eff & 0x0F) == 0x0F && (ton.eff & 0xF0) > 0) // fine slide down
1351 {
1352 ton.effTyp = 0xE;
1353 ton.eff = 0xA0 | (ton.eff >> 4);
1354
1355 // if volume column is unoccupied, set to vibrato
1356 if (ton.vol == 0)
1357 ton.vol = 0xB0;
1358 }
1359 else
1360 {
1361 ton.effTyp = 0x6;
1362 if (ton.eff & 0x0F) // on D/K, last nybble has first priority in ST3
1363 ton.eff &= 0x0F;
1364 }
1410 }1365 }
1411 break;1366 break;
1412 1367
1413 case 8: ton.effTyp = 0x04; break; // H1368 case 8: ton.effTyp = 0x04; break; // H
1414 case 9: ton.effTyp = 0x1D; break; // I1369 case 9: ton.effTyp = 0x1D; break; // I
1415 case 10: ton.effTyp = 0x00; break; // J1370 case 10: ton.effTyp = 0x00; break; // J
1416 case 11: ton.effTyp = 0x06; break; // K
1417 case 12: ton.effTyp = 0x05; break; // L1371 case 12: ton.effTyp = 0x05; break; // L
1418 case 15: ton.effTyp = 0x09; break; // O1372 case 15: ton.effTyp = 0x09; break; // O
1419 case 17: ton.effTyp = 0x1B; break; // Q1373 case 17: ton.effTyp = 0x1B; break; // Q
@@ -1429,10 +1383,37 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 9 unmodified lines
1429 else if (tmp == 0x2) ton.eff |= 0x50;1383 else if (tmp == 0x2) ton.eff |= 0x50;
1430 else if (tmp == 0x3) ton.eff |= 0x40;1384 else if (tmp == 0x3) ton.eff |= 0x40;
1431 else if (tmp == 0x4) ton.eff |= 0x70;1385 else if (tmp == 0x4) ton.eff |= 0x70;
1432 // we ignore S8x (set 4-bit pan) becuase it's not compatible with FT2 panning1386 // ignore S8x becuase it's not compatible with FT2 panning
1433 else if (tmp == 0xB) ton.eff |= 0x60;1387 else if (tmp == 0xB) ton.eff |= 0x60;
1434 else if (tmp == 0xC) ton.eff |= 0xC0;1388 else if (tmp == 0xC) // Note Cut
1435 else if (tmp == 0xD) ton.eff |= 0xD0;1389 {
1390 ton.eff |= 0xC0;
1391 if (ton.eff == 0xC0)
1392 {
1393 // EC0 does nothing in ST3 but cuts voice in FT2, remove effect
1394 ton.effTyp = 0;
1395 ton.eff = 0;
1396 }
1397 }
1398 else if (tmp == 0xD) // Note Delay
1399 {
1400 ton.eff |= 0xD0;
1401 if (ton.ton == 0 || ton.ton == 97)
1402 {
1403 // EDx without a note does nothing in ST3 but retrigs in FT2, remove effect
1404 ton.effTyp = 0;
1405 ton.eff = 0;
1406 }
1407 else if (ton.eff == 0xD0)
1408 {
1409 // ED0 prevents note/smp/vol from updating in ST3, remove everything
1410 ton.ton = 0;
1411 ton.instr = 0;
1412 ton.vol = 0;
1413 ton.effTyp = 0;
1414 ton.eff = 0;
1415 }
1416 }
1436 else if (tmp == 0xE) ton.eff |= 0xE0;1417 else if (tmp == 0xE) ton.eff |= 0xE0;
1437 else if (tmp == 0xF) ton.eff |= 0xF0;1418 else if (tmp == 0xF) ton.eff |= 0xF0;
1438 else1419 else
@@ -1454,40 +1435,18 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 15 unmodified lines
1454 }1435 }
1455 break;1436 break;
1456 1437
1457 case 21: // U (fine vibrato, doesn't exist in FT2, do a poor conversion to normal vibrato)1438 case 22: // V
1458 {1439 {
1459 if ((ton.eff & 0x0F) != 0)1440 ton.effTyp = 0x10;
1441 if (ton.eff > 0x40)
1460 {1442 {
1461 ton.eff = (ton.eff & 0xF0) | (((ton.eff & 15) + 1) >> 2); // divide depth by 41443 // Vxx > 0x40 does nothing in ST3
1462 if ((ton.eff & 0x0F) == 0) // depth too low, remove effect1444 ton.effTyp = 0;
1463 {1445 ton.eff = 0;
1464 illegalUxx = true;
1465 ton.effTyp = 0;
1466 ton.eff = 0;
1467 }
1468 else
1469 {
1470 illegalUxx = false;
1471 ton.effTyp = 0x04;
1472 }
1473 }
1474 else
1475 {
1476 if (!illegalUxx)
1477 {
1478 ton.effTyp = 0x04;
1479 }
1480 else
1481 {
1482 ton.effTyp = 0;
1483 ton.eff = 0;
1484 }
1485 }1446 }
1486 }1447 }
1487 break;1448 break;
1488 1449
1489 case 22: ton.effTyp = 0x10; break; // V
1490
1491 default:1450 default:
1492 {1451 {
1493 ton.effTyp = 0;1452 ton.effTyp = 0;
@@ -1500,40 +1459,6 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 6 unmodified lines
1500 if (ton.instr != 0 && ton.effTyp != 0x3)1459 if (ton.instr != 0 && ton.effTyp != 0x3)
1501 s3mLastGInstr[ii] = ton.instr;1460 s3mLastGInstr[ii] = ton.instr;
1502 1461
1503 // EDx with no note does nothing in ST3 but retrigs in FT2, remove effect
1504 if (ton.effTyp == 0xE && (ton.eff & 0xF0) == 0xD0)
1505 {
1506 if (ton.ton == 0 || ton.ton == 97)
1507 {
1508 ton.effTyp = 0;
1509 ton.eff = 0;
1510 }
1511 }
1512
1513 // EDx with a zero will prevent note/instr/vol from updating in ST3, remove everything
1514 if (ton.effTyp == 0xE && ton.eff == 0xD0)
1515 {
1516 ton.ton = 0;
1517 ton.instr = 0;
1518 ton.vol = 0;
1519 ton.effTyp = 0;
1520 ton.eff = 0;
1521 }
1522
1523 // ECx with a zero does nothing in ST3 but cuts voice in FT2, remove effect
1524 if (ton.effTyp == 0xE && ton.eff == 0xC0)
1525 {
1526 ton.effTyp = 0;
1527 ton.eff = 0;
1528 }
1529
1530 // Vxx with a value higher than 64 (0x40) does nothing in ST3, remove effect
1531 if (ton.effTyp == 0x10 && ton.eff > 0x40)
1532 {
1533 ton.effTyp = 0;
1534 ton.eff = 0;
1535 }
1536
1537 if (ton.effTyp > 35)1462 if (ton.effTyp > 35)
1538 {1463 {
1539 ton.effTyp = 0;1464 ton.effTyp = 0;
@@ -1610,10 +1535,10 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 70 unmodified lines
1610 bool is16Bit = (h_S3MInstr.flags >> 2) & 1;1535 bool is16Bit = (h_S3MInstr.flags >> 2) & 1;
1611 1536
1612 if (is16Bit) // 16-bit1537 if (is16Bit) // 16-bit
1613 len *= 2;1538 len <<= 1;
1614 1539
1615 if (stereoSample) // stereo1540 if (stereoSample) // stereo
1616 len *= 2;1541 len <<= 1;
1617 1542
1618 tmpSmp = (int8_t *)malloc(len + LOOP_FIX_LEN);1543 tmpSmp = (int8_t *)malloc(len + LOOP_FIX_LEN);
1619 if (tmpSmp == NULL)1544 if (tmpSmp == NULL)
@@ -1683,9 +1608,9 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 63 unmodified lines
1683 s->origPek = tmpSmp;1608 s->origPek = tmpSmp;
1684 s->pek = s->origPek + SMP_DAT_OFFSET;1609 s->pek = s->origPek + SMP_DAT_OFFSET;
1685 1610
1686 s->len *= 2;1611 s->len <<= 1;
1687 s->repS *= 2;1612 s->repS <<= 1;
1688 s->repL *= 2;1613 s->repL <<= 1;
1689 }1614 }
1690 else1615 else
1691 {1616 {
@@ -1712,74 +1637,6 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 20 unmodified lines
1712 }1637 }
1713 }1638 }
1714 1639
1715 // non-FT2: fix overflown 9xx and illegal 3xx slides
1716
1717 for (i = 0; i < ap; i++)
1718 {
1719 if (pattTmp[i] == NULL)
1720 continue;
1721
1722 for (k = 0; k < songTmp.antChn; k++)
1723 {
1724 check3xx = false;
1725 for (j = 0; j < 64; j++)
1726 {
1727 pattTon = &pattTmp[i][(j * MAX_VOICES) + k];
1728
1729 // fix illegal 3xx slides
1730
1731 if (pattTon->ton > 0 && pattTon->ton < 97)
1732 check3xx = pattTon->effTyp != 0x3;
1733
1734 if (check3xx && pattTon->effTyp == 0x3)
1735 {
1736 if (pattTon->ton == 0 || pattTon->ton == 97)
1737 {
1738 pattTon->effTyp = 0;
1739 pattTon->eff = 0;
1740 }
1741 }
1742
1743 /* In ST3 in GUS mode, an overflowed sample offset behaves like this:
1744 ** - Non-looped sample: Cut voice
1745 ** - Looped sample: Wrap around loop point
1746 **
1747 ** What we do here is to change the sample offset value to point to
1748 ** the wrapped sample loop position. This may be off by up to 256 bytes
1749 ** though...
1750 */
1751
1752 if (pattTon->effTyp == 0x9 && pattTon->eff > 0 && pattTon->instr > 0 && pattTon->instr <= ai && ai <= 128)
1753 {
1754 instrTyp *ins = instrTmp[pattTon->instr];
1755 if (ins == NULL)
1756 continue; // empty instrument (sample)
1757
1758 s = &ins->samp[0];
1759 if (s->len > 0 && (s->typ & 1)) // only handle non-empty looping samples
1760 {
1761 uint32_t loopEnd = s->repS + s->repL;
1762 uint32_t offset = pattTon->eff * 256;
1763
1764 if (offset >= loopEnd)
1765 {
1766 if (s->repL >= 2)
1767 offset = s->repS + ((offset - loopEnd) % s->repL);
1768 else
1769 offset = s->repS;
1770
1771 offset = (offset + (1 << 7)) >> 8; // convert to rounded sample offset value
1772 if (offset > 255)
1773 offset = 255;
1774
1775 pattTon->eff = (uint8_t)offset;
1776 }
1777 }
1778 }
1779 }
1780 }
1781 }
1782
1783 fclose(f);1640 fclose(f);
1784 1641
1785 songTmp.antChn = countS3MChannels(ap);1642 songTmp.antChn = countS3MChannels(ap);
@@ -2566,30 +2423,37 @@ static void setupLoadedModule(void) · 780 unmodified lines
2566 // support non-even channel numbers2423 // support non-even channel numbers
2567 if (song.antChn & 1)2424 if (song.antChn & 1)
2568 {2425 {
2569 if (++song.antChn > MAX_VOICES)2426 song.antChn++;
2427 if (song.antChn > MAX_VOICES)
2570 song.antChn = MAX_VOICES;2428 song.antChn = MAX_VOICES;
2571 }2429 }
2572 2430
2573 if (song.repS > song.len)2431 if (song.len == 0)
2432 song.len = 1;
2433
2434 if (song.repS >= song.len)
2574 song.repS = 0;2435 song.repS = 0;
2575 2436
2576 song.globVol = 64;2437 song.globVol = 64;
2577 song.timer = 1;
2578 2438
2579 setScrollBarEnd(SB_POS_ED, (song.len - 1) + 5);2439 setScrollBarEnd(SB_POS_ED, (song.len - 1) + 5);
2580 setScrollBarPos(SB_POS_ED, 0, false);2440 setScrollBarPos(SB_POS_ED, 0, false);
2581 2441
2582 resetChannels();2442 resetChannels();
2583 setPos(0, 0, false);2443 setPos(0, 0, true);
2584 setSpeed(song.speed);2444 setSpeed(song.speed);
2585 2445
2586 editor.tmpPattern = editor.editPattern; // set kludge variable2446 editor.tmpPattern = editor.editPattern; // set kludge variable
2587 editor.speed = song.speed;2447 editor.speed = song.speed;
2588 editor.tempo = song.tempo;2448 editor.tempo = song.tempo;
2589 editor.timer = 1;2449 editor.timer = song.timer;
2590 editor.globalVol = song.globVol;2450 editor.globalVol = song.globVol;
2591 2451
2592 setFrqTab((loadedFormat == FORMAT_XM) ? linearFreqTable : false);2452 if (loadedFormat == FORMAT_XM)
2453 setFrqTab(linearFreqTable);
2454 else
2455 setFrqTab(false);
2456
2593 unlockMixerCallback();2457 unlockMixerCallback();
2594 2458
2595 editor.currVolEnvPoint = 0;2459 editor.currVolEnvPoint = 0;
@@ -2602,9 +2466,10 @@ static void setupLoadedModule(void) · 6 unmodified lines
2602 updateChanNums();2466 updateChanNums();
2603 resetWavRenderer();2467 resetWavRenderer();
2604 clearPattMark();2468 clearPattMark();
2605 song.musicTime = 0;
2606 resetTrimSizes();2469 resetTrimSizes();
2607 2470
2471 song.musicTime = 0;
2472
2608 diskOpSetFilename(DISKOP_ITEM_MODULE, editor.tmpFilenameU);2473 diskOpSetFilename(DISKOP_ITEM_MODULE, editor.tmpFilenameU);
2609 2474
2610 // redraw top part of screen2475 // redraw top part of screen

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t