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:
Solomon Peachy 2025-01-03 08:34:47 -05:00
parent 08c32cee7c
commit af7ed73f31
29 changed files with 1860 additions and 706 deletions

View file

@ -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;
}