📄 load_med.c
字号:
memset(mmdp = mmd0pat, 0, of.numchn * maxlines * sizeof(MMD0NOTE));
for (row = numlines; row; row--) {
for (col = numtracks; col; col--, mmdp++) {
mmdp->a = _mm_read_UBYTE(modreader);
mmdp->b = _mm_read_UBYTE(modreader);
mmdp->c = _mm_read_UBYTE(modreader);
}
}
for (col = 0; col < of.numchn; col++)
of.tracks[track++] = MED_Convert0(numlines, col);
}
return 1;
}
static BOOL LoadMMD1Patterns(void)
{
int t, row, col;
UWORD numtracks, numlines, maxlines = 0, track = 0;
MMD1NOTE *mmdp;
/* first, scan patterns to see how many channels are used */
for (t = 0; t < of.numpat; t++) {
_mm_fseek(modreader, ba[t], SEEK_SET);
numtracks = _mm_read_M_UWORD(modreader);
numlines = _mm_read_M_UWORD(modreader);
if (numtracks > of.numchn)
of.numchn = numtracks;
if (numlines > maxlines)
maxlines = numlines;
}
of.numtrk = of.numpat * of.numchn;
if (!AllocTracks())
return 0;
if (!AllocPatterns())
return 0;
if (!
(mmd1pat =
(MMD1NOTE *)_mm_calloc(of.numchn * (maxlines + 1),
sizeof(MMD1NOTE)))) return 0;
/* second read: really read and convert patterns */
for (t = 0; t < of.numpat; t++) {
_mm_fseek(modreader, ba[t], SEEK_SET);
numtracks = _mm_read_M_UWORD(modreader);
numlines = _mm_read_M_UWORD(modreader);
_mm_fseek(modreader, sizeof(ULONG), SEEK_CUR);
of.pattrows[t] = ++numlines;
memset(mmdp = mmd1pat, 0, of.numchn * maxlines * sizeof(MMD1NOTE));
for (row = numlines; row; row--) {
for (col = numtracks; col; col--, mmdp++) {
mmdp->a = _mm_read_UBYTE(modreader);
mmdp->b = _mm_read_UBYTE(modreader);
mmdp->c = _mm_read_UBYTE(modreader);
mmdp->d = _mm_read_UBYTE(modreader);
}
}
for (col = 0; col < of.numchn; col++)
of.tracks[track++] = MED_Convert1(numlines, col);
}
return 1;
}
BOOL MED_Load(BOOL curious)
{
int t;
ULONG sa[64];
MEDINSTHEADER s;
SAMPLE *q;
MEDSAMPLE *mss;
/* try to read module header */
mh->id = _mm_read_M_ULONG(modreader);
mh->modlen = _mm_read_M_ULONG(modreader);
mh->MEDSONGP = _mm_read_M_ULONG(modreader);
mh->psecnum = _mm_read_M_UWORD(modreader);
mh->pseq = _mm_read_M_UWORD(modreader);
mh->MEDBlockPP = _mm_read_M_ULONG(modreader);
mh->reserved1 = _mm_read_M_ULONG(modreader);
mh->MEDINSTHEADERPP = _mm_read_M_ULONG(modreader);
mh->reserved2 = _mm_read_M_ULONG(modreader);
mh->MEDEXPP = _mm_read_M_ULONG(modreader);
mh->reserved3 = _mm_read_M_ULONG(modreader);
mh->pstate = _mm_read_M_UWORD(modreader);
mh->pblock = _mm_read_M_UWORD(modreader);
mh->pline = _mm_read_M_UWORD(modreader);
mh->pseqnum = _mm_read_M_UWORD(modreader);
mh->actplayline = _mm_read_M_SWORD(modreader);
mh->counter = _mm_read_UBYTE(modreader);
mh->extra_songs = _mm_read_UBYTE(modreader);
/* Seek to MEDSONG struct */
_mm_fseek(modreader, mh->MEDSONGP, SEEK_SET);
/* Load the MED Song Header */
mss = ms->sample; /* load the sample data first */
for (t = 63; t; t--, mss++) {
mss->rep = _mm_read_M_UWORD(modreader);
mss->replen = _mm_read_M_UWORD(modreader);
mss->midich = _mm_read_UBYTE(modreader);
mss->midipreset = _mm_read_UBYTE(modreader);
mss->svol = _mm_read_UBYTE(modreader);
mss->strans = _mm_read_SBYTE(modreader);
}
ms->numblocks = _mm_read_M_UWORD(modreader);
ms->songlen = _mm_read_M_UWORD(modreader);
_mm_read_UBYTES(ms->playseq, 256, modreader);
ms->deftempo = _mm_read_M_UWORD(modreader);
ms->playtransp = _mm_read_SBYTE(modreader);
ms->flags = _mm_read_UBYTE(modreader);
ms->flags2 = _mm_read_UBYTE(modreader);
ms->tempo2 = _mm_read_UBYTE(modreader);
_mm_read_UBYTES(ms->trkvol, 16, modreader);
ms->mastervol = _mm_read_UBYTE(modreader);
ms->numsamples = _mm_read_UBYTE(modreader);
/* check for a bad header */
if (_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
/* load extension structure */
if (mh->MEDEXPP) {
_mm_fseek(modreader, mh->MEDEXPP, SEEK_SET);
me->nextmod = _mm_read_M_ULONG(modreader);
me->exp_smp = _mm_read_M_ULONG(modreader);
me->s_ext_entries = _mm_read_M_UWORD(modreader);
me->s_ext_entrsz = _mm_read_M_UWORD(modreader);
me->annotxt = _mm_read_M_ULONG(modreader);
me->annolen = _mm_read_M_ULONG(modreader);
me->iinfo = _mm_read_M_ULONG(modreader);
me->i_ext_entries = _mm_read_M_UWORD(modreader);
me->i_ext_entrsz = _mm_read_M_UWORD(modreader);
me->jumpmask = _mm_read_M_ULONG(modreader);
me->rgbtable = _mm_read_M_ULONG(modreader);
me->channelsplit = _mm_read_M_ULONG(modreader);
me->n_info = _mm_read_M_ULONG(modreader);
me->songname = _mm_read_M_ULONG(modreader);
me->songnamelen = _mm_read_M_ULONG(modreader);
me->dumps = _mm_read_M_ULONG(modreader);
}
/* seek to and read the samplepointer array */
_mm_fseek(modreader, mh->MEDINSTHEADERPP, SEEK_SET);
if (!_mm_read_M_ULONGS(sa, ms->numsamples, modreader)) {
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
/* alloc and read the blockpointer array */
if (!(ba = (ULONG *)_mm_calloc(ms->numblocks, sizeof(ULONG))))
return 0;
_mm_fseek(modreader, mh->MEDBlockPP, SEEK_SET);
if (!_mm_read_M_ULONGS(ba, ms->numblocks, modreader)) {
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
/* copy song positions */
if (!AllocPositions(ms->songlen))
return 0;
for (t = 0; t < ms->songlen; t++)
of.positions[t] = ms->playseq[t];
decimalvolumes = (ms->flags & 0x10) ? 0 : 1;
bpmtempos = (ms->flags2 & 0x20) ? 1 : 0;
if (bpmtempos) {
int bpmlen = (ms->flags2 & 0x1f) + 1;
of.initspeed = ms->tempo2;
of.inittempo = ms->deftempo * bpmlen / 4;
if (bpmlen != 4) {
/* Let's do some math : compute GCD of BPM beat length and speed */
int a, b;
a = bpmlen;
b = ms->tempo2;
if (a > b) {
t = b;
b = a;
a = t;
}
while ((a != b) && (a)) {
t = a;
a = b - a;
b = t;
if (a > b) {
t = b;
b = a;
a = t;
}
}
of.initspeed /= b;
of.inittempo = ms->deftempo * bpmlen / (4 * b);
}
} else {
of.initspeed = ms->tempo2;
of.inittempo = ms->deftempo ? ((UWORD)ms->deftempo * 125) / 33 : 128;
if ((ms->deftempo <= 10) && (ms->deftempo))
of.inittempo = (of.inittempo * 33) / 6;
of.flags |= UF_HIGHBPM;
}
MED_Version[12] = mh->id;
of.modtype = strdup(MED_Version);
of.numchn = 0; /* will be counted later */
of.numpat = ms->numblocks;
of.numpos = ms->songlen;
of.numins = ms->numsamples;
of.numsmp = of.numins;
of.reppos = 0;
if ((mh->MEDEXPP) && (me->songname) && (me->songnamelen)) {
char *name;
_mm_fseek(modreader, me->songname, SEEK_SET);
name = _mm_malloc(me->songnamelen);
_mm_read_UBYTES(name, me->songnamelen, modreader);
of.songname = DupStr(name, me->songnamelen, 1);
free(name);
} else
of.songname = DupStr(NULL, 0, 0);
if ((mh->MEDEXPP) && (me->annotxt) && (me->annolen)) {
_mm_fseek(modreader, me->annotxt, SEEK_SET);
ReadComment(me->annolen);
}
if (!AllocSamples())
return 0;
q = of.samples;
for (t = 0; t < of.numins; t++) {
q->flags = SF_SIGNED;
q->volume = 64;
if (sa[t]) {
_mm_fseek(modreader, sa[t], SEEK_SET);
s.length = _mm_read_M_ULONG(modreader);
s.type = _mm_read_M_SWORD(modreader);
if (s.type) {
#ifdef MIKMOD_DEBUG
fprintf(stderr, "\rNon-sample instruments not supported in MED loader yet\n");
#endif
if (!curious) {
_mm_errno = MMERR_MED_SYNTHSAMPLES;
return 0;
}
s.length = 0;
}
if (_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
}
q->length = s.length;
q->seekpos = _mm_ftell(modreader);
q->loopstart = ms->sample[t].rep << 1;
q->loopend = q->loopstart + (ms->sample[t].replen << 1);
if (ms->sample[t].replen > 1)
q->flags |= SF_LOOP;
/* don't load sample if length>='MMD0'...
such kluges make libmikmod's code unique !!! */
if (q->length >= MMD0_string)
q->length = 0;
} else
q->length = 0;
if ((mh->MEDEXPP) && (me->exp_smp) &&
(t < me->s_ext_entries) && (me->s_ext_entrsz >= 4)) {
MEDINSTEXT ie;
_mm_fseek(modreader, me->exp_smp + t * me->s_ext_entrsz,
SEEK_SET);
ie.hold = _mm_read_UBYTE(modreader);
ie.decay = _mm_read_UBYTE(modreader);
ie.suppress_midi_off = _mm_read_UBYTE(modreader);
ie.finetune = _mm_read_SBYTE(modreader);
q->speed = finetune[ie.finetune & 0xf];
} else
q->speed = 8363;
if ((mh->MEDEXPP) && (me->iinfo) &&
(t < me->i_ext_entries) && (me->i_ext_entrsz >= 40)) {
MEDINSTINFO ii;
_mm_fseek(modreader, me->iinfo + t * me->i_ext_entrsz, SEEK_SET);
_mm_read_UBYTES(ii.name, 40, modreader);
q->samplename = DupStr((char*)ii.name, 40, 1);
} else
q->samplename = NULL;
q++;
}
if (mh->id == MMD0_string) {
if (!LoadMEDPatterns()) {
_mm_errno = MMERR_LOADING_PATTERN;
return 0;
}
} else if (mh->id == MMD1_string) {
if (!LoadMMD1Patterns()) {
_mm_errno = MMERR_LOADING_PATTERN;
return 0;
}
} else {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
return 1;
}
CHAR *MED_LoadTitle(void)
{
ULONG posit, namelen;
CHAR *name, *retvalue = NULL;
_mm_fseek(modreader, 0x20, SEEK_SET);
posit = _mm_read_M_ULONG(modreader);
if (posit) {
_mm_fseek(modreader, posit + 0x2C, SEEK_SET);
posit = _mm_read_M_ULONG(modreader);
namelen = _mm_read_M_ULONG(modreader);
_mm_fseek(modreader, posit, SEEK_SET);
name = _mm_malloc(namelen);
_mm_read_UBYTES(name, namelen, modreader);
retvalue = DupStr(name, namelen, 1);
free(name);
}
return retvalue;
}
/*========== Loader information */
MIKMODAPI MLOADER load_med = {
NULL,
"MED",
"MED (OctaMED)",
MED_Init,
MED_Test,
MED_Load,
MED_Cleanup,
MED_LoadTitle
};
/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -