History

Support loading XMs with >32 chans and instrs. with >16 samps.

...but discard the extra channels and samples! Also did some other fixes.

Olav Sørensen committed 6 years ago

Commit 09ef04f1 parent 2f4495e1 file · +190 −89Browse files

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

Unified · Split

src/ft2_module_loader.c+190−89
@@ -136,17 +136,18 @@ static SDL_Thread *thread; · 135 unmodified lines
136136
137137 // these temporarily read to, then copied to real struct if load was OK (should not need to be volatile'd)
138138 static int16_t pattLensTmp[MAX_PATTERNS];
139+static uint32_t extraSampleLengths[32-MAX_SMP_PER_INST]; // ModPlug Tracker & OpenMPT supports up to 32 samples per instrument in .XM
139140 static tonTyp *pattTmp[MAX_PATTERNS];
140−static instrTyp *instrTmp[1 + MAX_INST];
141+static instrTyp *instrTmp[1+MAX_INST];
141142 static songTyp songTmp;
142143
143144 static void setupLoadedModule(void);
144145 static void freeTmpModule(void);
145−static bool loadInstrHeader(FILE *f, uint16_t i);
146−static bool loadInstrSample(FILE *f, uint16_t i);
146+static bool loadInstrHeader(FILE *f, uint16_t i, bool externalThreadFlag);
147+static bool loadInstrSample(FILE *f, uint16_t i, bool externalThreadFlag);
147148 void unpackPatt(uint8_t *dst, uint8_t *src, uint16_t len, int32_t antChn);
148149 static bool tmpPatternEmpty(uint16_t nr);
149−static bool loadPatterns(FILE *f, uint16_t antPtn);
150+static bool loadPatterns(FILE *f, uint16_t antPtn, bool externalThreadFlag);
150151
151152 void checkSampleRepeat(sampleTyp *s);
152153
@@ -160,13 +161,11 @@ static bool allocateTmpInstr(int16_t nr) · 7 unmodified lines
160161 if (instrTmp[nr] != NULL)
161162 return false; // already allocated
162163
163− p = (instrTyp *)malloc(sizeof (instrTyp));
164+ p = (instrTyp *)calloc(1, sizeof (instrTyp));
164165 if (p == NULL)
165166 return false;
166167
167− memset(p, 0, sizeof (instrTyp));
168−
169− for (int8_t i = 0; i < 16; i++) // set standard sample pan/vol
168+ for (int8_t i = 0; i < MAX_SMP_PER_INST; i++) // set standard sample pan/vol
170169 {
171170 p->samp[i].pan = 128;
172171 p->samp[i].vol = 64;
@@ -213,7 +212,7 @@ static uint8_t getModType(uint8_t *numChannels, const char *id) · 40 unmodified lines
213212 return modFormat;
214213 }
215214
216−static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread)
215+static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool externalThreadFlag)
217216 {
218217 char ID[16];
219218 bool mightBeSTK, lateSTKVerFlag, veryLateSTKVerFlag;
@@ -226,7 +225,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 6 unmodified lines
226225 songMOD15HeaderTyp h_MOD15;
227226 int16_t (*showMsg)(int16_t, const char *, const char *);
228227
229− showMsg = fromExternalThread ? okBoxThreadSafe : okBox;
228+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
230229
231230 veryLateSTKVerFlag = false; // "DFJ SoundTracker III" nad later
232231 lateSTKVerFlag = false; // "TJC SoundTracker II" and later
@@ -318,7 +317,7 @@ static bool loadMusicMOD(FILE *f, uint32_t fileLength, bool fromExternalThread) · 85 unmodified lines
318317 }
319318
320319 if (modFormat == FORMAT_MK && songTmp.len == 129)
321− songTmp.len = 127; // fixes a specific copy of beatwave.mod
320+ songTmp.len = 127; // fixes a specific copy of beatwave.mod (FIXME: Do we want to keep this digsuting hack?)
322321
323322 if (songTmp.antChn == 0 || songTmp.len < 1 || songTmp.len > 128 || (mightBeSTK && songTmp.repS > 220))
324323 {
@@ -735,7 +734,7 @@ static uint8_t stmTempoToBPM(uint8_t tempo) // ported from original ST2.3 replay · 410 unmodified lines
735734 return (uint8_t)CLAMP(bpm, 32, 255); // result can be slightly off, but close enough...
736735 }
737736
738−static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread)
737+static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool externalThreadFlag)
739738 {
740739 uint8_t typ, tempo;
741740 int16_t i, j, k, ap, tmp;
@@ -745,19 +744,19 @@ static bool loadMusicSTM(FILE *f, uint32_t fileLength, bool fromExternalThread) · 3 unmodified lines
745744 songSTMHeaderTyp h_STM;
746745 int16_t (*showMsg)(int16_t, const char *, const char *);
747746
748− showMsg = fromExternalThread ? okBoxThreadSafe : okBox;
747+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
749748
750749 rewind(f);
751750
752751 // start loading STM
753752
754753 if (fread(&h_STM, 1, sizeof (h_STM), f) != sizeof (h_STM))
755− return loadMusicMOD(f, fileLength, fromExternalThread); // file is not a .stm, try to load as .mod
754+ return loadMusicMOD(f, fileLength, externalThreadFlag); // file is not a .stm, try to load as .mod
756755
757756 if (memcmp(h_STM.sig, "!Scream!", 8) && memcmp(h_STM.sig, "BMOD2STM", 8) &&
758757 memcmp(h_STM.sig, "WUZAMOD!", 8) && memcmp(h_STM.sig, "SWavePro", 8))
759758 {
760− return loadMusicMOD(f, fileLength, fromExternalThread); // file is not a .stm, try to load as .mod
759+ return loadMusicMOD(f, fileLength, externalThreadFlag); // file is not a .stm, try to load as .mod
761760 }
762761
763762 loadedFormat = FORMAT_STM;
@@ -1007,7 +1006,7 @@ static int8_t countS3MChannels(uint16_t antPtn) · 243 unmodified lines
10071006 return channels;
10081007 }
10091008
1010−static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread)
1009+static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool externalThreadFlag)
10111010 {
10121011 int8_t *tmpSmp;
10131012 uint8_t ha[2048];
@@ -1022,17 +1021,17 @@ static bool loadMusicS3M(FILE *f, uint32_t dataLength, bool fromExternalThread) · 8 unmodified lines
10221021 songS3MinstrHeaderTyp h_S3MInstr;
10231022 int16_t (*showMsg)(int16_t, const char *, const char *);
10241023
1025− showMsg = fromExternalThread ? okBoxThreadSafe : okBox;
1024+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
10261025
10271026 rewind(f);
10281027
10291028 // start loading S3M
10301029
10311030 if (fread(&h_S3M, 1, sizeof (h_S3M), f) != sizeof (h_S3M))
1032− return loadMusicSTM(f, dataLength, fromExternalThread); // not a .s3m, try loading as .stm
1031+ return loadMusicSTM(f, dataLength, externalThreadFlag); // not a .s3m, try loading as .stm
10331032
10341033 if (memcmp(h_S3M.id, "SCRM", 4))
1035− return loadMusicSTM(f, dataLength, fromExternalThread); // not a .s3m, try loading as .stm
1034+ return loadMusicSTM(f, dataLength, externalThreadFlag); // not a .s3m, try loading as .stm
10361035
10371036 loadedFormat = FORMAT_S3M;
10381037
@@ -1651,7 +1650,7 @@ s3mLoadError: · 612 unmodified lines
16511650 return false;
16521651 }
16531652
1654−bool doLoadMusic(bool fromExternalThread)
1653+bool doLoadMusic(bool externalThreadFlag)
16551654 {
16561655 char tmpText[128];
16571656 int16_t k;
@@ -1661,7 +1660,7 @@ bool doLoadMusic(bool fromExternalThread) · 3 unmodified lines
16611660 FILE *f;
16621661 int16_t (*showMsg)(int16_t, const char *, const char *);
16631662
1664− showMsg = fromExternalThread ? okBoxThreadSafe : okBox;
1663+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
16651664
16661665 linearFreqTable = false;
16671666
@@ -1686,10 +1685,10 @@ bool doLoadMusic(bool fromExternalThread) · 18 unmodified lines
16861685
16871686 // start loading
16881687 if (fread(&h, 1, sizeof (h), f) != sizeof (h))
1689− return loadMusicS3M(f, filelength, fromExternalThread); // not a .xm file, try to load as .s3m
1688+ return loadMusicS3M(f, filelength, externalThreadFlag); // not a .xm file, try to load as .s3m
16901689
16911690 if (memcmp(h.sig, "Extended Module: ", 17))
1692− return loadMusicS3M(f, filelength, fromExternalThread); // not a .xm file, try to load as .s3m
1691+ return loadMusicS3M(f, filelength, externalThreadFlag); // not a .xm file, try to load as .s3m
16931692
16941693 loadedFormat = FORMAT_XM;
16951694
@@ -1700,7 +1699,7 @@ bool doLoadMusic(bool fromExternalThread) · 4 unmodified lines
17001699 const int32_t major = (h.ver >> 8) & 0x0F;
17011700 const int32_t minor = h.ver & 0xFF;
17021701
1703− sprintf(tmpText, "Error loading .xm: Unsupported file version (v%01X.%02X)", major, minor);
1702+ sprintf(tmpText, "Error loading XM: Unsupported file version (v%01X.%02X).", major, minor);
17041703 showMsg(0, "System message", tmpText);
17051704
17061705 moduleFailedToLoad = true;
@@ -1709,29 +1708,26 @@ bool doLoadMusic(bool fromExternalThread) · 2 unmodified lines
17091708
17101709 if (h.len > MAX_ORDERS)
17111710 {
1712− showMsg(0, "System message", "Error loading .xm: The song has more than 256 orders!");
1711+ showMsg(0, "System message", "Error loading XM: The song has more than 256 orders!");
17131712 goto xmLoadError;
17141713 }
17151714
17161715 if (h.antPtn > MAX_PATTERNS)
17171716 {
1718− showMsg(0, "System message", "Error loading .xm: The song has more than 256 patterns!");
1717+ showMsg(0, "System message", "Error loading XM: The song has more than 256 patterns!");
17191718 goto xmLoadError;
17201719 }
17211720
1722− if (h.antChn == 0 || h.antChn > MAX_VOICES)
1721+ if (h.antChn == 0)
17231722 {
1724− showMsg(0, "System message", "Error loading .xm: Incompatible amount of channels!");
1723+ showMsg(0, "System message", "Error loading XM: This file is corrupt.");
17251724 goto xmLoadError;
17261725 }
17271726
1728− if (h.antInstrs > MAX_INST)
1729− showMsg(0, "System message", "This module has over 128 instruments! Only the first 128 will be loaded.");
1730−
17311727 fseek(f, 60 + h.headerSize, SEEK_SET);
17321728 if (filelength != 336 && feof(f)) // 336 in length at this point = empty XM
17331729 {
1734− showMsg(0, "System message", "Error loading .xm: The module is empty!");
1730+ showMsg(0, "System message", "Error loading XM: The module is empty!");
17351731 goto xmLoadError;
17361732 }
17371733
@@ -1768,62 +1764,81 @@ bool doLoadMusic(bool fromExternalThread) · 30 unmodified lines
17681764 else
17691765 memcpy(songTmp.songTab, h.songTab, songTmp.len);
17701766
1767+ // some strange XMs have the order list padded with 0xFF, remove them!
1768+ for (int16_t j = 255; j >= 0; j--)
1769+ {
1770+ if (songTmp.songTab[j] != 0xFF)
1771+ break;
1772+
1773+ if (songTmp.len > j)
1774+ songTmp.len = j;
1775+ }
1776+
1777+ // even though XM supports 256 orders, FT2 supports only 255...
1778+ if (songTmp.len > 0xFF)
1779+ songTmp.len = 0xFF;
1780+
17711781 if (songTmp.ver < 0x0104)
17721782 {
1773− // old FT2 format
1783+ // XM v1.02 and XM v1.03
17741784
17751785 for (i = 1; i <= h.antInstrs; i++)
17761786 {
1777− if (!loadInstrHeader(f, i))
1778− {
1779− showMsg(0, "System message", "Error loading .xm: Either a corrupt or a non-supported module!");
1787+ if (!loadInstrHeader(f, i, externalThreadFlag))
17801788 goto xmLoadError;
1781− }
17821789 }
17831790
1784− if (!loadPatterns(f, h.antPtn))
1785− {
1786− // error message is shown inside loadPattern()
1791+ if (!loadPatterns(f, h.antPtn, externalThreadFlag))
17871792 goto xmLoadError;
1788− }
17891793
17901794 for (i = 1; i <= h.antInstrs; i++)
17911795 {
1792− if (!loadInstrSample(f, i))
1793− {
1794− showMsg(0, "System message", "Not enough memory!");
1796+ if (!loadInstrSample(f, i, externalThreadFlag))
17951797 goto xmLoadError;
1796− }
17971798 }
17981799 }
17991800 else
18001801 {
1801− // current FT2 format
1802+ // XM v1.04 (latest version)
18021803
1803− if (!loadPatterns(f, h.antPtn))
1804− {
1805− // error message is shown inside loadPattern()
1804+ if (!loadPatterns(f, h.antPtn, externalThreadFlag))
18061805 goto xmLoadError;
1807− }
18081806
18091807 for (i = 1; i <= h.antInstrs; i++)
18101808 {
1811− if (!loadInstrHeader(f, i))
1812− {
1813− showMsg(0, "System message", "Error loading .xm: Either a corrupt or a non-supported module!");
1814− goto xmLoadError;
1815− }
1816−
1817− if (!loadInstrSample(f, i))
1818− {
1819− showMsg(0, "System message", "Not enough memory!");
1820− goto xmLoadError;
1821− }
1809+ if (!loadInstrHeader(f, i, externalThreadFlag)) goto xmLoadError;
1810+ if (!loadInstrSample(f, i, externalThreadFlag)) goto xmLoadError;
18221811 }
18231812 }
18241813
18251814 fclose(f);
18261815
1816+ /* We support loading XMs with up to 32 samples per instrument (ModPlug/OpenMPT),
1817+ ** but only the first 16 will be loaded. Now make sure we set the number of samples
1818+ ** back to max 16 in the headers before loading is done.
1819+ */
1820+ bool instrHasMoreThan16Samples = false;
1821+ for (i = 1; i <= MAX_INST; i++)
1822+ {
1823+ if (instrTmp[i] != NULL && instrTmp[i]->antSamp > MAX_SMP_PER_INST)
1824+ {
1825+ instrHasMoreThan16Samples = true;
1826+ instrTmp[i]->antSamp = MAX_SMP_PER_INST;
1827+ }
1828+ }
1829+
1830+ if (songTmp.antChn > MAX_VOICES)
1831+ {
1832+ songTmp.antChn = MAX_VOICES;
1833+ showMsg(0, "System message", "Warning: This XM contains >32 channels. The extra channels will be discarded!");
1834+ }
1835+
1836+ if (h.antInstrs > MAX_INST)
1837+ showMsg(0, "System message", "Warning: This XM contains >128 instruments. The extra instruments will be discarded!");
1838+
1839+ if (instrHasMoreThan16Samples)
1840+ showMsg(0, "System message", "Warning: This XM contains instrument(s) with >16 samples. The extra samples will be discarded!");
1841+
18271842 moduleLoaded = true;
18281843 return true;
18291844
@@ -1908,9 +1923,9 @@ bool loadMusicUnthreaded(UNICHAR *filenameU, bool autoPlay) · 78 unmodified lines
19081923 return false;
19091924 }
19101925
1911−static void freeTmpModule(void)
1926+static void freeTmpModule(void) // called on module load error
19121927 {
1913− uint16_t i;
1928+ int32_t i, j;
19141929
19151930 // free all patterns
19161931 for (i = 0; i < MAX_PATTERNS; i++)
@@ -1927,10 +1942,10 @@ static void freeTmpModule(void) · 10 unmodified lines
19271942 {
19281943 if (instrTmp[i] != NULL)
19291944 {
1930− for (uint8_t j = 0; j < MAX_SMP_PER_INST; j++)
1945+ for (j = 0; j < MAX_SMP_PER_INST; j++)
19311946 {
1932− if (instrTmp[i]->samp[j].pek != NULL)
1933− free(instrTmp[i]->samp[j].pek);
1947+ if (instrTmp[i]->samp[j].origPek != NULL)
1948+ free(instrTmp[i]->samp[j].origPek);
19341949 }
19351950
19361951 free(instrTmp[i]);
@@ -1939,7 +1954,7 @@ static void freeTmpModule(void) · 2 unmodified lines
19391954 }
19401955 }
19411956
1942−static bool loadInstrHeader(FILE *f, uint16_t i)
1957+static bool loadInstrHeader(FILE *f, uint16_t i, bool externalThreadFlag)
19431958 {
19441959 int8_t k;
19451960 uint8_t j;
@@ -1948,24 +1963,38 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 2 unmodified lines
19481963 instrTyp *ins;
19491964 sampleHeaderTyp *src;
19501965 sampleTyp *s;
1966+ int16_t (*showMsg)(int16_t, const char *, const char *);
19511967
1952− memset(&ih, 0, INSTR_HEADER_SIZE);
1968+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
19531969
1970+ memset(extraSampleLengths, 0, sizeof (extraSampleLengths));
1971+ memset(&ih, 0, sizeof (ih));
19541972 fread(&ih.instrSize, 4, 1, f);
19551973
19561974 readSize = ih.instrSize;
1957− if (readSize < 4 || readSize > INSTR_HEADER_SIZE)
1975+
1976+ // yes, some XMs can have a header size of 0, and it usually means 263 bytes (INSTR_HEADER_SIZE)
1977+ if (readSize == 0 || readSize > INSTR_HEADER_SIZE)
19581978 readSize = INSTR_HEADER_SIZE;
19591979
1980+ if (readSize < 4)
1981+ {
1982+ showMsg(0, "System message", "Error loading XM: This file is corrupt (or not supported)!");
1983+ return false;
1984+ }
1985+
19601986 // load instrument data into temp buffer
19611987 fread(ih.name, readSize-4, 1, f); // -4 = skip ih.instrSize
19621988
19631989 // FT2 bugfix: skip instrument header data if instrSize is above INSTR_HEADER_SIZE
19641990 if (ih.instrSize > INSTR_HEADER_SIZE)
1965− fseek(f, ih.instrSize - INSTR_HEADER_SIZE, SEEK_CUR);
1991+ fseek(f, ih.instrSize-INSTR_HEADER_SIZE, SEEK_CUR);
19661992
1967− if (ih.antSamp > MAX_SMP_PER_INST)
1993+ if (ih.antSamp < 0 || ih.antSamp > 32)
1994+ {
1995+ showMsg(0, "System message", "Error loading XM: This file is corrupt (or not supported)!");
19681996 return false;
1997+ }
19691998
19701999 if (i <= MAX_INST)
19712000 {
@@ -1987,7 +2016,10 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 15 unmodified lines
19872016 if (i <= MAX_INST)
19882017 {
19892018 if (!allocateTmpInstr(i))
2019+ {
2020+ showMsg(0, "System message", "Not enough memory!");
19902021 return false;
2022+ }
19912023
19922024 // copy instrument header elements to our instrument struct
19932025
@@ -2028,8 +2060,8 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 34 unmodified lines
20282060
20292061 for (j = 0; j < 96; j++)
20302062 {
2031− if (ins->ta[j] > 15)
2032− ins->ta[j] = 15;
2063+ if (ins->ta[j] >= MAX_SMP_PER_INST)
2064+ ins->ta[j] = MAX_SMP_PER_INST-1;
20332065 }
20342066
20352067 if (ins->envVPAnt > 12) ins->envVPAnt = 12;
@@ -2050,12 +2082,30 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 14 unmodified lines
20502082 }
20512083 }
20522084
2053− if (fread(ih.samp, ih.antSamp * sizeof (sampleHeaderTyp), 1, f) != 1)
2085+ int32_t sampleHeadersToRead = ih.antSamp;
2086+ if (sampleHeadersToRead > MAX_SMP_PER_INST)
2087+ sampleHeadersToRead = MAX_SMP_PER_INST;
2088+
2089+ if (fread(ih.samp, sampleHeadersToRead * sizeof (sampleHeaderTyp), 1, f) != 1)
2090+ {
2091+ showMsg(0, "System message", "General I/O error during loading!");
20542092 return false;
2093+ }
2094+
2095+ // if instrument contains more than 16 sample headers (unsupported), skip them
2096+ if (ih.antSamp > MAX_SMP_PER_INST) // can only be 0..32 at this point
2097+ {
2098+ const int32_t samplesToSkip = ih.antSamp-MAX_SMP_PER_INST;
2099+ for (j = 0; j < samplesToSkip; j++)
2100+ {
2101+ fread(&extraSampleLengths[j], 4, 1, f); // used for skipping data in loadInstrSample()
2102+ fseek(f, sizeof (sampleHeaderTyp)-4, SEEK_CUR);
2103+ }
2104+ }
20552105
20562106 if (i <= MAX_INST)
20572107 {
2058− for (j = 0; j < ih.antSamp; j++)
2108+ for (j = 0; j < sampleHeadersToRead; j++)
20592109 {
20602110 s = &instrTmp[i]->samp[j];
20612111 src = &ih.samp[j];
@@ -2105,17 +2155,23 @@ void checkSampleRepeat(sampleTyp *s) · 43 unmodified lines
21052155 if (s->repL == 0) s->typ &= ~3; // non-FT2 fix: force loop off if looplen is 0
21062156 }
21072157
2108−static bool loadInstrSample(FILE *f, uint16_t i)
2158+static bool loadInstrSample(FILE *f, uint16_t i, bool externalThreadFlag)
21092159 {
21102160 int8_t *newPtr;
21112161 uint16_t j, k;
21122162 int32_t l, bytesToSkip;
21132163 sampleTyp *s;
2164+ int16_t (*showMsg)(int16_t, const char *, const char *);
2165+
2166+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
21142167
21152168 if (i > MAX_INST || instrTmp[i] == NULL)
21162169 return true; // yes, let's just pretend they got loaded
21172170
21182171 k = instrTmp[i]->antSamp;
2172+ if (k > MAX_SMP_PER_INST)
2173+ k = MAX_SMP_PER_INST;
2174+
21192175 for (j = 0; j < k; j++)
21202176 {
21212177 s = &instrTmp[i]->samp[j];
@@ -2147,14 +2203,17 @@ static bool loadInstrSample(FILE *f, uint16_t i) · 25 unmodified lines
21472203 s->pek = NULL;
21482204 s->origPek = (int8_t *)malloc(l + LOOP_FIX_LEN);
21492205 if (s->origPek == NULL)
2206+ {
2207+ showMsg(0, "System message", "Not enough memory!");
21502208 return false;
2209+ }
21512210
21522211 s->pek = s->origPek + SMP_DAT_OFFSET;
21532212
2154− int32_t bytesRead = (int32_t)fread(s->pek, 1, l, f);
2213+ const int32_t bytesRead = (int32_t)fread(s->pek, 1, l, f);
21552214 if (bytesRead < l)
21562215 {
2157− int32_t bytesToClear = l - bytesRead;
2216+ const int32_t bytesToClear = l - bytesRead;
21582217 memset(&s->pek[bytesRead], 0, bytesToClear);
21592218 }
21602219
@@ -2192,23 +2251,37 @@ static bool loadInstrSample(FILE *f, uint16_t i) · 31 unmodified lines
21922251 fixSample(s);
21932252 }
21942253
2254+ if (instrTmp[i]->antSamp > MAX_SMP_PER_INST)
2255+ {
2256+ const int32_t samplesToSkip = instrTmp[i]->antSamp-MAX_SMP_PER_INST;
2257+ for (i = 0; i < samplesToSkip; i++)
2258+ {
2259+ if (extraSampleLengths[i] > 0)
2260+ fseek(f, extraSampleLengths[i], SEEK_CUR);
2261+ }
2262+ }
2263+
21952264 return true;
21962265 }
21972266
21982267 void unpackPatt(uint8_t *dst, uint8_t *src, uint16_t len, int32_t antChn)
21992268 {
22002269 uint8_t note, data;
2201− int32_t srcEnd, srcIdx;
2270+ int32_t srcEnd, srcIdx, j;
22022271
22032272 if (dst == NULL)
22042273 return;
22052274
2206− srcEnd = len * TRACK_WIDTH;
2275+ srcEnd = len * (sizeof (tonTyp) * antChn);
22072276 srcIdx = 0;
22082277
2278+ int32_t numChannels = antChn;
2279+ if (numChannels > MAX_VOICES)
2280+ numChannels = MAX_VOICES;
2281+
22092282 for (int32_t i = 0; i < len; i++)
22102283 {
2211− for (int32_t j = 0; j < antChn; j++)
2284+ for (j = 0; j < numChannels; j++)
22122285 {
22132286 if (srcIdx >= srcEnd)
22142287 return; // error!
@@ -2245,8 +2318,35 @@ void unpackPatt(uint8_t *dst, uint8_t *src, uint16_t len, int32_t antChn) · 30 unmodified lines
22452318 srcIdx += sizeof (tonTyp);
22462319 }
22472320
2248− // skip unused channels
2249− dst += sizeof (tonTyp) * (MAX_VOICES - antChn);
2321+ // if more than 32 channels, skip rest of the channels for this row
2322+ for (; j < antChn; j++)
2323+ {
2324+ if (srcIdx >= srcEnd)
2325+ return; // error!
2326+
2327+ note = *src++;
2328+ if (note & 0x80)
2329+ {
2330+ if (note & 0x01) src++;
2331+ if (note & 0x02) src++;
2332+ if (note & 0x04) src++;
2333+ if (note & 0x08) src++;
2334+ if (note & 0x10) src++;
2335+ }
2336+ else
2337+ {
2338+ src++;
2339+ src++;
2340+ src++;
2341+ src++;
2342+ }
2343+
2344+ srcIdx += sizeof (tonTyp);
2345+ }
2346+
2347+ // if song has <32 channels, align pointer to next row (skip unused channels)
2348+ if (antChn < MAX_VOICES)
2349+ dst += sizeof (tonTyp) * (MAX_VOICES - antChn);
22502350 }
22512351 }
22522352
@@ -2279,15 +2379,17 @@ void clearUnusedChannels(tonTyp *p, int16_t pattLen, int32_t antChn) · 26 unmodified lines
22792379 memset(&p[(i * MAX_VOICES) + antChn], 0, sizeof (tonTyp) * (MAX_VOICES - antChn));
22802380 }
22812381
2282−static bool loadPatterns(FILE *f, uint16_t antPtn)
2382+static bool loadPatterns(FILE *f, uint16_t antPtn, bool externalThreadFlag)
22832383 {
22842384 bool pattLenWarn;
22852385 uint8_t tmpLen;
22862386 uint16_t i;
22872387 patternHeaderTyp ph;
2388+ int16_t (*showMsg)(int16_t, const char *, const char *);
22882389
2289− pattLenWarn = false;
2390+ showMsg = externalThreadFlag ? okBoxThreadSafe : okBox;
22902391
2392+ pattLenWarn = false;
22912393 for (i = 0; i < antPtn; i++)
22922394 {
22932395 if (fread(&ph.patternHeaderSize, 4, 1, f) != 1)
@@ -2337,7 +2439,7 @@ static bool loadPatterns(FILE *f, uint16_t antPtn) · 43 unmodified lines
23372439 pattTmp[i] = (tonTyp *)calloc((MAX_PATT_LEN * TRACK_WIDTH) + 16, 1);
23382440 if (pattTmp[i] == NULL)
23392441 {
2340− okBoxThreadSafe(0, "System message", "Not enough memory!");
2442+ showMsg(0, "System message", "Not enough memory!");
23412443 return false;
23422444 }
23432445
@@ -2345,7 +2447,6 @@ static bool loadPatterns(FILE *f, uint16_t antPtn) · 1 unmodified line
23452447 goto pattCorrupt;
23462448
23472449 unpackPatt((uint8_t *)pattTmp[i], packedPattData, pattLensTmp[i], songTmp.antChn);
2348−
23492450 clearUnusedChannels(pattTmp[i], pattLensTmp[i], songTmp.antChn);
23502451 }
23512452
@@ -2362,12 +2463,12 @@ static bool loadPatterns(FILE *f, uint16_t antPtn) · 10 unmodified lines
23622463 }
23632464
23642465 if (pattLenWarn)
2365− okBoxThreadSafe(0, "System message", "This module contains pattern(s) with a length above 256! They will be truncated.");
2466+ showMsg(0, "System message", "This module contains pattern(s) with a length above 256! They will be truncated.");
23662467
23672468 return true;
23682469
23692470 pattCorrupt:
2370− okBoxThreadSafe(0, "System message", "Error loading .xm: Either a corrupt or a non-supported module!");
2471+ showMsg(0, "System message", "Error loading XM: This file is corrupt!");
23712472 return false;
23722473 }
23732474

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