⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 load_xm.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 2 页
字号:
		ENVPT *prev;

		/* Some broken XM editing program will only save the low byte
		   of the position value. Try to compensate by adding the
		   missing high byte. */

		prev = cur++;
		old = prev->pos;

		for (u = 1; u < pts; u++, prev++, cur++) {
			if (cur->pos < prev->pos) {
				if (cur->pos < 0x100) {
					if (cur->pos > old)	/* same hex century */
							tmp = cur->pos + (prev->pos - old);
					else
							tmp = cur->pos | ((prev->pos + 0x100) & 0xff00);
					old = cur->pos;
					cur->pos = tmp;
#ifdef MIKMOD_DEBUG
					fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n",
					    u, pts, prev->pos, old, cur->pos);
#endif
				} else {
#ifdef MIKMOD_DEBUG
					/* different brokenness style... fix unknown */
					fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n",
					    u, pts, old, cur->pos);
#endif
					old = cur->pos;
				}
			} else
				old = cur->pos;
		}
}

static BOOL LoadInstruments(void)
{
	int t,u;
	INSTRUMENT *d;
	ULONG next=0;
	UWORD wavcnt=0;

	if(!AllocInstruments()) return 0;
	d=of.instruments;
	for(t=0;t<of.numins;t++,d++) {
		XMINSTHEADER ih;
		long headend;

		memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));

		/* read instrument header */
		headend     = _mm_ftell(modreader);
		ih.size     = _mm_read_I_ULONG(modreader);
		headend    += ih.size;
		_mm_read_string(ih.name, 22, modreader);
		ih.type     = _mm_read_UBYTE(modreader);
		ih.numsmp   = _mm_read_I_UWORD(modreader);

		d->insname  = DupStr(ih.name,22,1);

		if((SWORD)ih.size>29) {
			ih.ssize    = _mm_read_I_ULONG(modreader);
			if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
				XMPATCHHEADER pth;
				int p;

				_mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
				_mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
				_mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
				pth.volpts      =  _mm_read_UBYTE(modreader);
				pth.panpts      =  _mm_read_UBYTE(modreader);
				pth.volsus      =  _mm_read_UBYTE(modreader);
				pth.volbeg      =  _mm_read_UBYTE(modreader);
				pth.volend      =  _mm_read_UBYTE(modreader);
				pth.pansus      =  _mm_read_UBYTE(modreader);
				pth.panbeg      =  _mm_read_UBYTE(modreader);
				pth.panend      =  _mm_read_UBYTE(modreader);
				pth.volflg      =  _mm_read_UBYTE(modreader);
				pth.panflg      =  _mm_read_UBYTE(modreader);
				pth.vibflg      =  _mm_read_UBYTE(modreader);
				pth.vibsweep    =  _mm_read_UBYTE(modreader);
				pth.vibdepth    =  _mm_read_UBYTE(modreader);
				pth.vibrate     =  _mm_read_UBYTE(modreader);
				pth.volfade     =  _mm_read_I_UWORD(modreader);

				/* read the remainder of the header
				   (2 bytes for 1.03, 22 for 1.04) */
				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);

				/* we can't trust the envelope point count here, as some
				   modules have incorrect values (K_OSPACE.XM reports 32 volume
				   points, for example). */
				if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2;
				if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;

				if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
					if(nextwav) { free(nextwav);nextwav=NULL; }
					if(wh) { free(wh);wh=NULL; }
					_mm_errno = MMERR_LOADING_SAMPLEINFO;
					return 0;
				}

				for(u=0;u<XMNOTECNT;u++)
					d->samplenumber[u]=pth.what[u]+of.numsmp;
				d->volfade = pth.volfade;

#if defined __STDC__ || defined _MSC_VER || defined MPW_C
#define XM_ProcessEnvelope(name) 										\
				for (u = 0; u < (XMENVCNT >> 1); u++) {					\
					d-> name##env[u].pos = pth. name##env[u << 1];		\
					d-> name##env[u].val = pth. name##env[(u << 1)+ 1];	\
				}														\
				if (pth. name##flg&1) d-> name##flg|=EF_ON;				\
				if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN;		\
				if (pth. name##flg&4) d-> name##flg|=EF_LOOP;			\
				d-> name##susbeg=d-> name##susend=pth. name##sus;		\
				d-> name##beg=pth. name##beg;							\
				d-> name##end=pth. name##end;							\
				d-> name##pts=pth. name##pts;							\
																		\
				/* scale envelope */									\
				for (p=0;p<XMENVCNT/2;p++)								\
					d-> name##env[p].val<<=2;							\
																		\
				if ((d-> name##flg&EF_ON)&&(d-> name##pts<2))			\
					d-> name##flg&=~EF_ON
#else
#define XM_ProcessEnvelope(name) 											\
				for (u = 0; u < (XMENVCNT >> 1); u++) {						\
					d-> name/**/env[u].pos = pth. name/**/env[u << 1];		\
					d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1];	\
				}															\
				if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON;				\
				if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN;		\
				if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP;			\
				d-> name/**/susbeg=d-> name/**/susend=						\
				                      pth. name/**/sus;						\
				d-> name/**/beg=pth. name/**/beg;							\
				d-> name/**/end=pth. name/**/end;							\
				d-> name/**/pts=pth. name/**/pts;							\
																			\
				/* scale envelope */										\
				for (p=0;p<XMENVCNT/2;p++)									\
					d-> name/**/env[p].val<<=2;								\
																			\
				if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2))			\
					d-> name/**/flg&=~EF_ON
#endif			

				XM_ProcessEnvelope(vol);
				XM_ProcessEnvelope(pan);
#undef XM_ProcessEnvelope

				if (d->volflg & EF_ON)
					FixEnvelope(d->volenv, d->volpts);
				if (d->panflg & EF_ON)
					FixEnvelope(d->panenv, d->panpts);

				/* Samples are stored outside the instrument struct now, so we
				   have to load them all into a temp area, count the of.numsmp
				   along the way and then do an AllocSamples() and move
				   everything over */
				if(mh->version>0x0103) next = 0;
				for(u=0;u<ih.numsmp;u++,s++) {
					/* Allocate more room for sample information if necessary */
					if(of.numsmp+u==wavcnt) {
						wavcnt+=XM_SMPINCR;
						if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
							if(wh) { free(wh);wh=NULL; }
							_mm_errno = MMERR_OUT_OF_MEMORY;
							return 0;
						}
						if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
							free(nextwav);nextwav=NULL;
							_mm_errno = MMERR_OUT_OF_MEMORY;
							return 0;
						}
						s=wh+(wavcnt-XM_SMPINCR);
					}

					s->length       =_mm_read_I_ULONG (modreader);
					s->loopstart    =_mm_read_I_ULONG (modreader);
					s->looplength   =_mm_read_I_ULONG (modreader);
					s->volume       =_mm_read_UBYTE (modreader);
					s->finetune     =_mm_read_SBYTE (modreader);
					s->type         =_mm_read_UBYTE (modreader);
					s->panning      =_mm_read_UBYTE (modreader);
					s->relnote      =_mm_read_SBYTE (modreader);
					s->vibtype      = pth.vibflg;
					s->vibsweep     = pth.vibsweep;
					s->vibdepth     = pth.vibdepth*4;
					s->vibrate      = pth.vibrate;
					s->reserved     =_mm_read_UBYTE (modreader);
					_mm_read_string(s->samplename, 22, modreader);

					nextwav[of.numsmp+u]=next;
					next+=s->length;

					if(_mm_eof(modreader)) {
						free(nextwav);free(wh);
						nextwav=NULL;wh=NULL;
						_mm_errno = MMERR_LOADING_SAMPLEINFO;
						return 0;
					}
				}

				if(mh->version>0x0103) {
					for(u=0;u<ih.numsmp;u++)
						nextwav[of.numsmp++]+=_mm_ftell(modreader);
					_mm_fseek(modreader,next,SEEK_CUR);
				} else
					of.numsmp+=ih.numsmp;
			} else {
				/* read the remainder of the header */
				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);

				if(_mm_eof(modreader)) {
					free(nextwav);free(wh);
					nextwav=NULL;wh=NULL;
					_mm_errno = MMERR_LOADING_SAMPLEINFO;
					return 0;
				}
			}
		}
	}

	/* sanity check */
	if(!of.numsmp) {
		if(nextwav) { free(nextwav);nextwav=NULL; }
		if(wh) { free(wh);wh=NULL; }
		_mm_errno = MMERR_LOADING_SAMPLEINFO;
		return 0;
	}

	return 1;
}

BOOL XM_Load(BOOL curious)
{
	INSTRUMENT *d;
	SAMPLE *q;
	int t,u;
	BOOL dummypat=0;
	char tracker[21],modtype[60];

	/* try to read module header */
	_mm_read_string(mh->id,17,modreader);
	_mm_read_string(mh->songname,21,modreader);
	_mm_read_string(mh->trackername,20,modreader);
	mh->version     =_mm_read_I_UWORD(modreader);
	if((mh->version<0x102)||(mh->version>0x104)) {
		_mm_errno=MMERR_NOT_A_MODULE;
		return 0;
	}
	mh->headersize  =_mm_read_I_ULONG(modreader);
	mh->songlength  =_mm_read_I_UWORD(modreader);
	mh->restart     =_mm_read_I_UWORD(modreader);
	mh->numchn      =_mm_read_I_UWORD(modreader);
	mh->numpat      =_mm_read_I_UWORD(modreader);
	mh->numins      =_mm_read_I_UWORD(modreader);
	mh->flags       =_mm_read_I_UWORD(modreader);
	mh->tempo       =_mm_read_I_UWORD(modreader);
	mh->bpm         =_mm_read_I_UWORD(modreader);
	if(!mh->bpm) {
		_mm_errno=MMERR_NOT_A_MODULE;
		return 0;
	}
	_mm_read_UBYTES(mh->orders,256,modreader);

	if(_mm_eof(modreader)) {
		_mm_errno = MMERR_LOADING_HEADER;
		return 0;
	}

	/* set module variables */
	of.initspeed = mh->tempo;         
	of.inittempo = mh->bpm;
	strncpy(tracker,mh->trackername,20);tracker[20]=0;
	for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
	
	/* some modules have the tracker name empty */
	if (!tracker[0])
		strcpy(tracker,"Unknown tracker");

#ifdef HAVE_SNPRINTF
	snprintf(modtype,60,"%s (XM format %d.%02d)",
	                    tracker,mh->version>>8,mh->version&0xff);
#else
	sprintf(modtype,"%s (XM format %d.%02d)",
	                tracker,mh->version>>8,mh->version&0xff);
#endif
	of.modtype   = strdup(modtype);
	of.numchn    = mh->numchn;
	of.numpat    = mh->numpat;
	of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
	of.songname  = DupStr(mh->songname,20,1);
	of.numpos    = mh->songlength;               /* copy the songlength */
	of.reppos    = mh->restart<mh->songlength?mh->restart:0;
	of.numins    = mh->numins;
	of.flags    |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
				   UF_PANNING;
	if(mh->flags&1) of.flags |= UF_LINEAR;
	of.bpmlimit  = 32;

	memset(of.chanvol,64,of.numchn);             /* store channel volumes */

	if(!AllocPositions(of.numpos+1)) return 0;
	for(t=0;t<of.numpos;t++)
		of.positions[t]=mh->orders[t];

	/* We have to check for any pattern numbers in the order list greater than
	   the number of patterns total. If one or more is found, we set it equal to
	   the pattern total and make a dummy pattern to workaround the problem */
	for(t=0;t<of.numpos;t++) {
		if(of.positions[t]>=of.numpat) {
			of.positions[t]=of.numpat;
			dummypat=1;
		}
	}
	if(dummypat) {
		of.numpat++;of.numtrk+=of.numchn;
	}

	if(mh->version<0x0104) {
		if(!LoadInstruments()) return 0;
		if(!LoadPatterns(dummypat)) return 0;
		for(t=0;t<of.numsmp;t++)
			nextwav[t]+=_mm_ftell(modreader);
	} else {
		if(!LoadPatterns(dummypat)) return 0;
		if(!LoadInstruments()) return 0;
	}

	if(!AllocSamples()) {
		free(nextwav);free(wh);
		nextwav=NULL;wh=NULL;
		return 0;
	}
	q = of.samples;
	s = wh;
	for(u=0;u<of.numsmp;u++,q++,s++) {
		q->samplename   = DupStr(s->samplename,22,1);
		q->length       = s->length;
		q->loopstart    = s->loopstart;
		q->loopend      = s->loopstart+s->looplength;
		q->volume       = s->volume;
		q->speed        = s->finetune+128;
		q->panning      = s->panning;
		q->seekpos      = nextwav[u];
		q->vibtype      = s->vibtype;
		q->vibsweep     = s->vibsweep;
		q->vibdepth     = s->vibdepth;
		q->vibrate      = s->vibrate;

		if(s->type & 0x10) {
			q->length    >>= 1;
			q->loopstart >>= 1;
			q->loopend   >>= 1;
		}

		q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
		if(s->type&0x3) q->flags|=SF_LOOP;
		if(s->type&0x2) q->flags|=SF_BIDI;
		if(s->type&0x10) q->flags|=SF_16BITS;
	}

	d=of.instruments;
	s=wh;
	for(u=0;u<of.numins;u++,d++)
		for(t=0;t<XMNOTECNT;t++) {
			if (d->samplenumber[t]>=of.numsmp)
				d->samplenote[t]=255;
			else {
				int note=t+s[d->samplenumber[t]].relnote;
				d->samplenote[t]=(note<0)?0:note;
			}
		}

	free(wh);free(nextwav);
	wh=NULL;nextwav=NULL;
	return 1;
}

CHAR *XM_LoadTitle(void)
{
	CHAR s[21];

	_mm_fseek(modreader,17,SEEK_SET);
	if(!_mm_read_UBYTES(s,21,modreader)) return NULL;

	return(DupStr(s,21,1));
}

/*========== Loader information */

MIKMODAPI MLOADER load_xm={
	NULL,
	"XM",
	"XM (FastTracker 2)",
	XM_Init,
	XM_Test,
	XM_Load,
	XM_Cleanup,
	XM_LoadTitle
};

/* ex:set ts=4: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -