mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
FS#13539: Resync mikmod plugin with upstream
Brings it up to libmikmod 3.3.12, relased 2024-12-31 Also fix a segfault that only happened on simulators when using non-default samplerates. Change-Id: I2ade2d72a00edab5395328fe76a88a88516aac72
This commit is contained in:
parent
08c32cee7c
commit
af7ed73f31
29 changed files with 1860 additions and 706 deletions
|
@ -84,10 +84,13 @@ typedef struct MODNOTE {
|
|||
static CHAR protracker[] = "Protracker";
|
||||
static CHAR startrekker[] = "Startrekker";
|
||||
static CHAR fasttracker[] = "Fasttracker";
|
||||
static CHAR oktalyser[] = "Oktalyser";
|
||||
static CHAR octalyser[] = "Octalyser";
|
||||
static CHAR oktalyzer[] = "Oktalyzer";
|
||||
static CHAR taketracker[] = "TakeTracker";
|
||||
static CHAR digitaltracker[] = "Digital Tracker MOD";
|
||||
static CHAR orpheus[] = "Imago Orpheus (MOD format)";
|
||||
static CHAR modsgrave[] = "Mod's Grave";
|
||||
static CHAR unknown[] = "Unknown tracker MOD";
|
||||
|
||||
static MODULEHEADER *mh = NULL;
|
||||
static MODNOTE *patbuf = NULL;
|
||||
|
@ -102,7 +105,7 @@ static int MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
|
|||
modtype = trekker = 0;
|
||||
|
||||
/* Protracker and variants */
|
||||
if ((!memcmp(id, "M.K.", 4)) || (!memcmp(id, "M!K!", 4))) {
|
||||
if ((!memcmp(id, "M.K.", 4)) || (!memcmp(id, "M!K!", 4)) || (!memcmp(id, "M&K!", 4))) {
|
||||
*descr = protracker;
|
||||
modtype = 0;
|
||||
*numchn = 4;
|
||||
|
@ -132,11 +135,11 @@ static int MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Oktalyser (Atari) */
|
||||
if (!memcmp(id, "CD81", 4)) {
|
||||
*descr = oktalyser;
|
||||
/* Octalyser (Atari) */
|
||||
if (!memcmp(id, "CD81", 4) || !memcmp(id, "CD61", 4)) {
|
||||
*descr = octalyser;
|
||||
modtype = 1;
|
||||
*numchn = 8;
|
||||
*numchn = id[2] - '0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -160,6 +163,27 @@ static int MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
|
|||
*numchn = (id[0] - '0') * 10 + (id[1] - '0');
|
||||
return 1;
|
||||
}
|
||||
/* Taketracker */
|
||||
if (!memcmp(id, "TDZ", 3) && (id[3] >= '1' && id[3] <= '3')) {
|
||||
*descr = taketracker;
|
||||
*numchn = (id[3] - '0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Digital Tracker */
|
||||
if (!memcmp(id, "FA0", 3) && (id[3] == '4' || id[3] == '6' || id[3] == '8')) {
|
||||
*descr = digitaltracker;
|
||||
*numchn = (id[3] - '0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Standard 4-channel MODs with unusual IDs. */
|
||||
if (!memcmp(id, "LARD", 4) /* judgement_day_gvine.mod */
|
||||
|| !memcmp(id, "NSMS", 4)) { /* kingdomofpleasure.mod */
|
||||
*descr = unknown;
|
||||
*numchn = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -368,6 +392,16 @@ static int MOD_Load(int curious)
|
|||
SAMPLE *q;
|
||||
MSAMPINFO *s;
|
||||
CHAR *descr;
|
||||
int maybewow = 1;
|
||||
ULONG samplelength = 0;
|
||||
ULONG filelength;
|
||||
ULONG pos;
|
||||
char adpcm[5];
|
||||
|
||||
pos = _mm_ftell(modreader);
|
||||
_mm_fseek(modreader, 0, SEEK_END);
|
||||
filelength = _mm_ftell(modreader);
|
||||
_mm_fseek(modreader, pos, SEEK_SET);
|
||||
|
||||
/* try to read module header */
|
||||
_mm_read_string((CHAR *)mh->songname, 20, modreader);
|
||||
|
@ -382,6 +416,11 @@ static int MOD_Load(int curious)
|
|||
s->volume = _mm_read_UBYTE(modreader);
|
||||
s->reppos = _mm_read_M_UWORD(modreader);
|
||||
s->replen = _mm_read_M_UWORD(modreader);
|
||||
/* Mod's Grave .WOW files are converted from .669 and thus
|
||||
do not have sample finetune or volume. */
|
||||
samplelength += (ULONG)s->length << 1;
|
||||
if (s->length && (s->finetune != 0x00 || s->volume != 0x40))
|
||||
maybewow = 0;
|
||||
}
|
||||
|
||||
mh->songlength = _mm_read_UBYTE(modreader);
|
||||
|
@ -394,6 +433,10 @@ static int MOD_Load(int curious)
|
|||
_mm_read_UBYTES(mh->positions, 128, modreader);
|
||||
_mm_read_UBYTES(mh->magic2, 4, modreader);
|
||||
|
||||
/* Mod's Grave .WOW files always use 0x00 for the "restart" byte. */
|
||||
if (mh->magic1 != 0x00)
|
||||
maybewow = 0;
|
||||
|
||||
if (_mm_eof(modreader)) {
|
||||
_mm_errno = MMERR_LOADING_HEADER;
|
||||
return 0;
|
||||
|
@ -406,6 +449,12 @@ static int MOD_Load(int curious)
|
|||
_mm_errno = MMERR_NOT_A_MODULE;
|
||||
return 0;
|
||||
}
|
||||
if (descr == digitaltracker) {
|
||||
/* Digital Tracker FA0x modules add four extra bytes after the
|
||||
* magic. These don't seem to have ever been used for their
|
||||
* intended purpose (rows per pattern and sample bits/rate). */
|
||||
_mm_read_M_ULONG(modreader);
|
||||
}
|
||||
if (trekker && of.numchn == 8)
|
||||
for (t = 0; t < 128; t++)
|
||||
/* if module pretends to be FLT8, yet the order table
|
||||
|
@ -443,6 +492,24 @@ static int MOD_Load(int curious)
|
|||
of.numpos = t + 1;
|
||||
}
|
||||
of.numpat++;
|
||||
|
||||
/* Mod's Grave .WOW files have an M.K. signature but they're actually 8 channel.
|
||||
The only way to distinguish them from a 4-channel M.K. file is to check the
|
||||
length of the .MOD against the expected length of a .WOW file with the same
|
||||
number of patterns as this file. To make things harder, Mod's Grave occasionally
|
||||
adds an extra byte to .WOW files and sometimes .MOD authors pad their files.
|
||||
Prior checks for WOW behavior should help eliminate false positives here.
|
||||
|
||||
Also note the length check relies on counting samples with a length word=1 to work. */
|
||||
if (modtype == 0 && maybewow == 1) {
|
||||
ULONG wowlength = MODULEHEADERSIZE + 4 + samplelength + of.numpat * (64 * 4 * 8);
|
||||
if ((filelength & ~1) == wowlength) {
|
||||
modtype = 1;
|
||||
descr = modsgrave;
|
||||
of.numchn = 8;
|
||||
}
|
||||
}
|
||||
|
||||
of.numtrk = of.numpat * of.numchn;
|
||||
|
||||
if (!AllocPositions(of.numpos))
|
||||
|
@ -450,12 +517,16 @@ static int MOD_Load(int curious)
|
|||
for (t = 0; t < of.numpos; t++)
|
||||
of.positions[t] = mh->positions[t];
|
||||
|
||||
if (!ML_LoadPatterns())
|
||||
return 0;
|
||||
|
||||
/* Finally, init the sampleinfo structures */
|
||||
of.numins = of.numsmp = 31;
|
||||
if (!AllocSamples())
|
||||
return 0;
|
||||
s = mh->samples;
|
||||
q = of.samples;
|
||||
pos = _mm_ftell(modreader);
|
||||
for (t = 0; t < of.numins; t++) {
|
||||
/* convert the samplename */
|
||||
q->samplename = DupStr(s->samplename, 23, 1);
|
||||
|
@ -474,15 +545,28 @@ static int MOD_Load(int curious)
|
|||
if (s->replen > 2)
|
||||
q->flags |= SF_LOOP;
|
||||
|
||||
q->seekpos = pos;
|
||||
/* Test for MODPlugin ADPCM. These are indicated by "ADPCM"
|
||||
* embedded at the start of each sample's data. :( */
|
||||
memset(adpcm, 0, sizeof(adpcm));
|
||||
_mm_read_UBYTES(adpcm, 5, modreader);
|
||||
if (!memcmp(adpcm, "ADPCM", 5)) {
|
||||
q->flags |= SF_ADPCM4;
|
||||
q->seekpos += 5;
|
||||
/* Stored half-length, plus a 16 byte table. */
|
||||
pos += s->length + 16 + 5;
|
||||
_mm_fseek(modreader, s->length + 16, SEEK_CUR);
|
||||
} else {
|
||||
pos += q->length;
|
||||
_mm_fseek(modreader, q->length - 5, SEEK_CUR);
|
||||
}
|
||||
|
||||
s++;
|
||||
q++;
|
||||
}
|
||||
|
||||
of.modtype = MikMod_strdup(descr);
|
||||
|
||||
if (!ML_LoadPatterns())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue