- 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
Showing the changes to src/ft2_module_loader.c (1 of 25 files). Show all
Unified · Split
| @@ -184,7 +184,7 @@ static uint8_t getModType(uint8_t *numChannels, const char *id) · 183 unmodified lines | ||
| 184 | 184 | |
| 185 | 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 | 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 | 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 | 203 | else if (IS_ID("N.T.", id)) |
| 209 | 204 | { |
| 210 | 205 | modFormat = FORMAT_NT; // NoiseTracker |
| @@ -364,23 +359,23 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 153 unmodified lines | ||
| 364 | 359 | */ |
| 365 | 360 | modFormat = FORMAT_STK; |
| 366 | 361 | |
| 367 | − if (h_MOD15.repS == 0) | |
| 368 | − h_MOD15.repS = 120; | |
| 362 | + if (songTmp.repS == 0) | |
| 363 | + songTmp.repS = 120; | |
| 369 | 364 | |
| 370 | − // jjk55.mod by Jesper Kyd has a bogus STK tempo value that should be ignored | |
| 365 | + // jjk55.mod by Jesper Kyd has a bogus STK tempo value that should be ignored (hackish!) | |
| 371 | 366 | if (!strcmp("jjk55", h_MOD31.name)) |
| 372 | − h_MOD15.repS = 120; | |
| 367 | + songTmp.repS = 120; | |
| 373 | 368 | |
| 374 | 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) | |
| 378 | − h_MOD15.repS = 220; | |
| 372 | + if (songTmp.repS > 220) | |
| 373 | + songTmp.repS = 220; | |
| 379 | 374 | |
| 380 | 375 | // convert UST tempo to BPM |
| 381 | 376 | uint16_t ciaPeriod = (240 - songTmp.repS) * 122; |
| 382 | 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 | 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 | 445 | ton->effTyp = bytes[2] & 0x0F; |
| 451 | 446 | ton->eff = bytes[3]; |
| 452 | 447 | |
| 453 | − if (mightBeSTK) | |
| 448 | + if (modFormat == FORMAT_STK) | |
| 454 | 449 | { |
| 455 | 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 | 516 | // 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 | 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 | 685 | /* For Ultimate SoundTracker modules, only the loop area of a looped sample is played. |
| 691 | 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 | 690 | s->len -= s->repS; |
| 696 | 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 | 702 | // clear repL and repS on non-looping samples... |
| 708 | − if ((s->typ & 3) == 0) | |
| 703 | + if (s->typ == 0) | |
| 709 | 704 | { |
| 710 | 705 | s->repL = 0; |
| 711 | 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 | 730 | uint16_t hz = 50; |
| 736 | 731 | |
| 737 | 732 | hz -= ((slowdowns[tempo >> 4] * (tempo & 15)) >> 4); // can and will underflow |
| 738 | − | |
| 739 | − bpm = (int32_t)((hz * 2.5) + 0.5); | |
| 733 | + bpm = (hz << 1) + (hz >> 1); // BPM = hz * 2.5 | |
| 740 | 734 | return (uint8_t)CLAMP(bpm, 32, 255); // result can be slightly off, but close enough... |
| 741 | 735 | } |
| 742 | 736 | |
| 743 | 737 | static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) |
| 744 | 738 | { |
| 745 | − bool check3xx; | |
| 746 | − uint8_t typ, tmp8, tempo; | |
| 739 | + uint8_t typ, tempo; | |
| 747 | 740 | int16_t i, j, k, ai, ap, tmp; |
| 748 | 741 | uint16_t a; |
| 749 | − int32_t len; | |
| 750 | 742 | tonTyp *ton; |
| 751 | 743 | sampleTyp *s; |
| 752 | 744 | songSTMHeaderTyp h_STM; |
| @@ -887,19 +879,6 @@ static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) · 134 unmodified lines | ||
| 887 | 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 | 882 | if (ton->effTyp > 35) |
| 904 | 883 | { |
| 905 | 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 | 968 | fclose(f); |
| 1061 | 969 | |
| 1062 | 970 | moduleLoaded = true; |
| @@ -1102,14 +1010,14 @@ static int8_t countS3MChannels(uint16_t antPtn) · 39 unmodified lines | ||
| 1102 | 1010 | static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) |
| 1103 | 1011 | { |
| 1104 | 1012 | int8_t *tmpSmp; |
| 1105 | − bool check3xx, illegalUxx; | |
| 1013 | + bool illegalUxx; | |
| 1106 | 1014 | uint8_t ha[2048]; |
| 1107 | − uint8_t s3mLastDEff[32], s3mLastEEff[32], s3mLastFEff[32]; | |
| 1108 | − uint8_t s3mLastSEff[32], s3mLastJEff[32], s3mLastGInstr[32], typ; | |
| 1015 | + uint8_t alastnfo[32], alastefx[32], alastvibnfo[32], s3mLastGInstr[32]; | |
| 1016 | + uint8_t typ; | |
| 1109 | 1017 | int16_t ai, ap, ver, ii, kk, tmp; |
| 1110 | 1018 | uint16_t ptnOfs[256]; |
| 1111 | 1019 | int32_t i, j, k, len; |
| 1112 | − tonTyp ton, *pattTon; | |
| 1020 | + tonTyp ton; | |
| 1113 | 1021 | sampleTyp *s; |
| 1114 | 1022 | songS3MHeaderTyp h_S3M; |
| 1115 | 1023 | songS3MinstrHeaderTyp h_S3MInstr; |
| @@ -1143,13 +1051,7 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 27 unmodified lines | ||
| 1143 | 1051 | goto s3mLoadError; |
| 1144 | 1052 | } |
| 1145 | 1053 | |
| 1146 | − // count real song table entries | |
| 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; | |
| 1054 | + songTmp.len = h_S3M.songTabLen; | |
| 1153 | 1055 | |
| 1154 | 1056 | // remove pattern separators (254) |
| 1155 | 1057 | k = 0; |
| @@ -1165,11 +1067,20 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 9 unmodified lines | ||
| 1165 | 1067 | if (k <= songTmp.len) |
| 1166 | 1068 | songTmp.len -= (uint16_t)k; |
| 1167 | 1069 | 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 | 1081 | // clear unused song table entries |
| 1171 | 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 | 1085 | songTmp.speed = h_S3M.defTempo; |
| 1175 | 1086 | if (songTmp.speed < 32) |
| @@ -1226,11 +1137,9 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 50 unmodified lines | ||
| 1226 | 1137 | if (ptnOfs[i] == 0) |
| 1227 | 1138 | continue; // empty pattern |
| 1228 | 1139 | |
| 1229 | − memset(s3mLastDEff, 0, sizeof (s3mLastDEff)); | |
| 1230 | − memset(s3mLastEEff, 0, sizeof (s3mLastEEff)); | |
| 1231 | − memset(s3mLastFEff, 0, sizeof (s3mLastFEff)); | |
| 1232 | − memset(s3mLastSEff, 0, sizeof (s3mLastSEff)); | |
| 1233 | − memset(s3mLastJEff, 0, sizeof (s3mLastJEff)); | |
| 1140 | + memset(alastnfo, 0, sizeof (alastnfo)); | |
| 1141 | + memset(alastefx, 0, sizeof (alastefx)); | |
| 1142 | + memset(alastvibnfo, 0, sizeof (alastvibnfo)); | |
| 1234 | 1143 | memset(s3mLastGInstr, 0, sizeof (s3mLastGInstr)); |
| 1235 | 1144 | |
| 1236 | 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 | − // volume | |
| 1207 | + // volume column | |
| 1299 | 1208 | if (typ & 64) |
| 1300 | 1209 | { |
| 1301 | 1210 | ton.vol = pattBuff[k++]; |
| @@ -1312,28 +1221,42 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 10 unmodified lines | ||
| 1312 | 1221 | ton.effTyp = pattBuff[k++]; |
| 1313 | 1222 | ton.eff = pattBuff[k++]; |
| 1314 | 1223 | |
| 1315 | − if (ton.eff == 0) | |
| 1224 | + if (ton.eff > 0) | |
| 1316 | 1225 | { |
| 1317 | − if (ton.effTyp == 4) | |
| 1318 | − { | |
| 1319 | − if ((s3mLastDEff[ii] & 0xF0) == 0xF0 || (s3mLastDEff[ii] & 0x0F) == 0x0F) | |
| 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]; | |
| 1226 | + alastnfo[ii] = ton.eff; | |
| 1227 | + if (ton.effTyp == 8 || ton.effTyp == 21) | |
| 1228 | + alastvibnfo[ii] = ton.eff; // H/U | |
| 1326 | 1229 | } |
| 1327 | − | |
| 1328 | − if (ton.eff != 0) | |
| 1230 | + | |
| 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; | |
| 1331 | − else if (ton.effTyp == 5) s3mLastEEff[ii] = ton.eff; | |
| 1332 | − else if (ton.effTyp == 6) s3mLastFEff[ii] = ton.eff; | |
| 1333 | − else if (ton.effTyp == 10) s3mLastJEff[ii] = ton.eff; | |
| 1334 | − else if (ton.effTyp == 19) s3mLastSEff[ii] = ton.eff; | |
| 1234 | + uint8_t efx = ton.effTyp; | |
| 1235 | + if (efx == 8 || efx == 21) // H/U | |
| 1236 | + ton.eff = alastvibnfo[ii]; | |
| 1237 | + else if ((efx >= 4 && efx <= 12) || (efx >= 17 && efx <= 19)) // D/E/F/I/J/K/L/Q/R/S | |
| 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 | 1260 | switch (ton.effTyp) |
| 1338 | 1261 | { |
| 1339 | 1262 | case 1: // A |
| @@ -1351,14 +1274,12 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 11 unmodified lines | ||
| 1351 | 1274 | case 3: ton.effTyp = 0xD; break; // C |
| 1352 | 1275 | case 4: // D |
| 1353 | 1276 | { |
| 1354 | − if ((ton.eff & 0xF0) == 0) ton.effTyp = 0xA; | |
| 1355 | − else if ((ton.eff & 0x0F) == 0) ton.effTyp = 0xA; | |
| 1356 | − else if ((ton.eff & 0xF0) == 0xF0) | |
| 1277 | + if (ton.eff > 0xF0) // fine slide up | |
| 1357 | 1278 | { |
| 1358 | 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 | 1284 | ton.effTyp = 0xE; |
| 1364 | 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 | 1287 | else |
| 1367 | 1288 | { |
| 1368 | 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 | 1291 | ton.eff &= 0x0F; |
| 1371 | − else | |
| 1372 | − ton.eff &= 0xF0; | |
| 1373 | 1292 | } |
| 1374 | 1293 | } |
| 1375 | 1294 | break; |
| @@ -1379,6 +1298,7 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 3 unmodified lines | ||
| 1379 | 1298 | { |
| 1380 | 1299 | if ((ton.eff & 0xF0) >= 0xE0) |
| 1381 | 1300 | { |
| 1301 | + // convert to fine slide | |
| 1382 | 1302 | if ((ton.eff & 0xF0) == 0xE0) |
| 1383 | 1303 | tmp = 0x21; |
| 1384 | 1304 | else |
| @@ -1392,9 +1312,15 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 7 unmodified lines | ||
| 1392 | 1312 | ton.eff |= 0x10; |
| 1393 | 1313 | |
| 1394 | 1314 | ton.effTyp = (uint8_t)tmp; |
| 1315 | + | |
| 1316 | + if (ton.effTyp == 0x21 && ton.eff == 0) | |
| 1317 | + { | |
| 1318 | + ton.effTyp = 0; | |
| 1319 | + } | |
| 1395 | 1320 | } |
| 1396 | 1321 | else |
| 1397 | 1322 | { |
| 1323 | + // convert to normal 1xx/2xx slide | |
| 1398 | 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 | 1329 | case 7: // G |
| 1404 | 1330 | { |
| 1331 | + ton.effTyp = 0x03; | |
| 1332 | + | |
| 1405 | 1333 | // fix illegal slides (to new instruments) |
| 1406 | 1334 | if (ton.instr != 0 && ton.instr != s3mLastGInstr[ii]) |
| 1407 | 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 | 1366 | break; |
| 1412 | 1367 | |
| 1413 | 1368 | case 8: ton.effTyp = 0x04; break; // H |
| 1414 | 1369 | case 9: ton.effTyp = 0x1D; break; // I |
| 1415 | 1370 | case 10: ton.effTyp = 0x00; break; // J |
| 1416 | − case 11: ton.effTyp = 0x06; break; // K | |
| 1417 | 1371 | case 12: ton.effTyp = 0x05; break; // L |
| 1418 | 1372 | case 15: ton.effTyp = 0x09; break; // O |
| 1419 | 1373 | 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 | 1383 | else if (tmp == 0x2) ton.eff |= 0x50; |
| 1430 | 1384 | else if (tmp == 0x3) ton.eff |= 0x40; |
| 1431 | 1385 | else if (tmp == 0x4) ton.eff |= 0x70; |
| 1432 | − // we ignore S8x (set 4-bit pan) becuase it's not compatible with FT2 panning | |
| 1386 | + // ignore S8x becuase it's not compatible with FT2 panning | |
| 1433 | 1387 | else if (tmp == 0xB) ton.eff |= 0x60; |
| 1434 | − else if (tmp == 0xC) ton.eff |= 0xC0; | |
| 1435 | − else if (tmp == 0xD) ton.eff |= 0xD0; | |
| 1388 | + else if (tmp == 0xC) // Note Cut | |
| 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 | 1417 | else if (tmp == 0xE) ton.eff |= 0xE0; |
| 1437 | 1418 | else if (tmp == 0xF) ton.eff |= 0xF0; |
| 1438 | 1419 | else |
| @@ -1454,40 +1435,18 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 15 unmodified lines | ||
| 1454 | 1435 | } |
| 1455 | 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 4 | |
| 1462 | − if ((ton.eff & 0x0F) == 0) // depth too low, remove effect | |
| 1463 | − { | |
| 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 | − } | |
| 1443 | + // Vxx > 0x40 does nothing in ST3 | |
| 1444 | + ton.effTyp = 0; | |
| 1445 | + ton.eff = 0; | |
| 1485 | 1446 | } |
| 1486 | 1447 | } |
| 1487 | 1448 | break; |
| 1488 | 1449 | |
| 1489 | − case 22: ton.effTyp = 0x10; break; // V | |
| 1490 | − | |
| 1491 | 1450 | default: |
| 1492 | 1451 | { |
| 1493 | 1452 | ton.effTyp = 0; |
| @@ -1500,40 +1459,6 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 6 unmodified lines | ||
| 1500 | 1459 | if (ton.instr != 0 && ton.effTyp != 0x3) |
| 1501 | 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 | 1462 | if (ton.effTyp > 35) |
| 1538 | 1463 | { |
| 1539 | 1464 | ton.effTyp = 0; |
| @@ -1610,10 +1535,10 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 70 unmodified lines | ||
| 1610 | 1535 | bool is16Bit = (h_S3MInstr.flags >> 2) & 1; |
| 1611 | 1536 | |
| 1612 | 1537 | if (is16Bit) // 16-bit |
| 1613 | − len *= 2; | |
| 1538 | + len <<= 1; | |
| 1614 | 1539 | |
| 1615 | 1540 | if (stereoSample) // stereo |
| 1616 | − len *= 2; | |
| 1541 | + len <<= 1; | |
| 1617 | 1542 | |
| 1618 | 1543 | tmpSmp = (int8_t *)malloc(len + LOOP_FIX_LEN); |
| 1619 | 1544 | if (tmpSmp == NULL) |
| @@ -1683,9 +1608,9 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 63 unmodified lines | ||
| 1683 | 1608 | s->origPek = tmpSmp; |
| 1684 | 1609 | s->pek = s->origPek + SMP_DAT_OFFSET; |
| 1685 | 1610 | |
| 1686 | − s->len *= 2; | |
| 1687 | − s->repS *= 2; | |
| 1688 | − s->repL *= 2; | |
| 1611 | + s->len <<= 1; | |
| 1612 | + s->repS <<= 1; | |
| 1613 | + s->repL <<= 1; | |
| 1689 | 1614 | } |
| 1690 | 1615 | 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 | 1640 | fclose(f); |
| 1784 | 1641 | |
| 1785 | 1642 | songTmp.antChn = countS3MChannels(ap); |
| @@ -2566,30 +2423,37 @@ static void setupLoadedModule(void) · 780 unmodified lines | ||
| 2566 | 2423 | // support non-even channel numbers |
| 2567 | 2424 | if (song.antChn & 1) |
| 2568 | 2425 | { |
| 2569 | − if (++song.antChn > MAX_VOICES) | |
| 2426 | + song.antChn++; | |
| 2427 | + if (song.antChn > MAX_VOICES) | |
| 2570 | 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 | 2435 | song.repS = 0; |
| 2575 | 2436 | |
| 2576 | 2437 | song.globVol = 64; |
| 2577 | − song.timer = 1; | |
| 2578 | 2438 | |
| 2579 | 2439 | setScrollBarEnd(SB_POS_ED, (song.len - 1) + 5); |
| 2580 | 2440 | setScrollBarPos(SB_POS_ED, 0, false); |
| 2581 | 2441 | |
| 2582 | 2442 | resetChannels(); |
| 2583 | − setPos(0, 0, false); | |
| 2443 | + setPos(0, 0, true); | |
| 2584 | 2444 | setSpeed(song.speed); |
| 2585 | 2445 | |
| 2586 | 2446 | editor.tmpPattern = editor.editPattern; // set kludge variable |
| 2587 | 2447 | editor.speed = song.speed; |
| 2588 | 2448 | editor.tempo = song.tempo; |
| 2589 | − editor.timer = 1; | |
| 2449 | + editor.timer = song.timer; | |
| 2590 | 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 | 2457 | unlockMixerCallback(); |
| 2594 | 2458 | |
| 2595 | 2459 | editor.currVolEnvPoint = 0; |
| @@ -2602,9 +2466,10 @@ static void setupLoadedModule(void) · 6 unmodified lines | ||
| 2602 | 2466 | updateChanNums(); |
| 2603 | 2467 | resetWavRenderer(); |
| 2604 | 2468 | clearPattMark(); |
| 2605 | − song.musicTime = 0; | |
| 2606 | 2469 | resetTrimSizes(); |
| 2607 | 2470 | |
| 2471 | + song.musicTime = 0; | |
| 2472 | + | |
| 2608 | 2473 | diskOpSetFilename(DISKOP_ITEM_MODULE, editor.tmpFilenameU); |
| 2609 | 2474 | |
| 2610 | 2475 | // redraw top part of screen |