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

📄 load_s3m.c

📁 wince下著名的视频播放器源码
💻 C
字号:
/*	MikMod sound library	(c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file	AUTHORS for complete list.	This library is free software; you can redistribute it and/or modify	it under the terms of the GNU Library General Public License as	published by the Free Software Foundation; either version 2 of	the License, or (at your option) any later version. 	This program is distributed in the hope that it will be useful,	but WITHOUT ANY WARRANTY; without even the implied warranty of	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	GNU Library General Public License for more details. 	You should have received a copy of the GNU Library General Public	License along with this library; if not, write to the Free Software	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.*//*==============================================================================  $Id: load_s3m.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $  Screamtracker (S3M) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <string.h>#include "mikmod_internals.h"#ifdef SUNOSextern int fprintf(FILE *, const char *, ...);#endif/*========== Module structure *//* header */typedef struct S3MHEADER {	CHAR  songname[28];	UBYTE t1a;	UBYTE type;	UBYTE unused1[2];	UWORD ordnum;	UWORD insnum;	UWORD patnum;	UWORD flags;	UWORD tracker;	UWORD fileformat;	CHAR  scrm[4];	UBYTE mastervol;	UBYTE initspeed;	UBYTE inittempo;	UBYTE mastermult;	UBYTE ultraclick;	UBYTE pantable;	UBYTE unused2[8];	UWORD special;	UBYTE channels[32];} S3MHEADER;/* sample information */typedef struct S3MSAMPLE {	UBYTE type;	CHAR  filename[12];	UBYTE memsegh;	UWORD memsegl;	ULONG length;	ULONG loopbeg;	ULONG loopend;	UBYTE volume;	UBYTE dsk;	UBYTE pack;	UBYTE flags;	ULONG c2spd;	UBYTE unused[12];	CHAR  sampname[28];	CHAR  scrs[4];} S3MSAMPLE;typedef struct S3MNOTE {	UBYTE note,ins,vol,cmd,inf;} S3MNOTE;/*========== Loader variables */static S3MNOTE   *s3mbuf  = NULL; /* pointer to a complete S3M pattern */static S3MHEADER *mh      = NULL;static UWORD     *paraptr = NULL; /* parapointer array (see S3M docs) */static unsigned int tracker;	/* tracker id *//* tracker identifiers */#define NUMTRACKERS 4static CHAR* S3M_Version[] = {	"Screamtracker x.xx",	"Imago Orpheus x.xx (S3M format)",	"Impulse Tracker x.xx (S3M format)",	"Unknown tracker x.xx (S3M format)",	"Impulse Tracker 2.14p3 (S3M format)",	"Impulse Tracker 2.14p4 (S3M format)"};/* version number position in above array */static int numeric[NUMTRACKERS]={14,14,16,16};/*========== Loader code */BOOL S3M_Test(void){	UBYTE id[4];	_mm_fseek(modreader,0x2c,SEEK_SET);	if(!_mm_read_UBYTES(id,4,modreader)) return 0;	if(!memcmp(id,"SCRM",4)) return 1;	return 0;}BOOL S3M_Init(void){	if(!(s3mbuf=(S3MNOTE*)_mm_malloc(32*64*sizeof(S3MNOTE)))) return 0;	if(!(mh=(S3MHEADER*)_mm_malloc(sizeof(S3MHEADER)))) return 0;	if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;	memset(poslookup,-1,256);	return 1;}void S3M_Cleanup(void){	_mm_free(s3mbuf);	_mm_free(paraptr);	_mm_free(poslookup);	_mm_free(mh);	_mm_free(origpositions);}/* Because so many s3m files have 16 channels as the set number used, but really   only use far less (usually 8 to 12 still), I had to make this function, which   determines the number of channels that are actually USED by a pattern.   For every channel that's used, it sets the appropriate array entry of the   global variable 'remap'   NOTE: You must first seek to the file location of the pattern before calling         this procedure.   Returns 1 on fail.                                                         */static BOOL S3M_GetNumChannels(void){	int row=0,flag,ch;	while(row<64) {		flag=_mm_read_UBYTE(modreader);		if(_mm_eof(modreader)) {			_mm_errno = MMERR_LOADING_PATTERN;			return 1;		}		if(flag) {			ch=flag&31;			if(mh->channels[ch]<32) remap[ch] = 0;			if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}			if(flag&64) _mm_read_UBYTE(modreader);			if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}		} else row++;	}	return 0;}    static BOOL S3M_ReadPattern(void){	int row=0,flag,ch;	S3MNOTE *n,dummy;	/* clear pattern data */	memset(s3mbuf,255,32*64*sizeof(S3MNOTE));	while(row<64) {		flag=_mm_read_UBYTE(modreader);		if(_mm_eof(modreader)) {			_mm_errno = MMERR_LOADING_PATTERN;			return 0;		}		if(flag) {			ch=remap[flag&31];			if(ch!=-1)				n=&s3mbuf[(64U*ch)+row];			else				n=&dummy;			if(flag&32) {				n->note=_mm_read_UBYTE(modreader);				n->ins=_mm_read_UBYTE(modreader);			}			if(flag&64) {				n->vol=_mm_read_UBYTE(modreader);				if (n->vol>64) n->vol=64;			}			if(flag&128) {				n->cmd=_mm_read_UBYTE(modreader);				n->inf=_mm_read_UBYTE(modreader);			}		} else row++;	}	return 1;}static UBYTE* S3M_ConvertTrack(S3MNOTE* tr){	int t;	UniReset();	for(t=0;t<64;t++) {		UBYTE note,ins,vol;		note=tr[t].note;		ins=tr[t].ins;		vol=tr[t].vol;		if((ins)&&(ins!=255)) UniInstrument(ins-1);		if(note!=255) {			if(note==254) {				UniPTEffect(0xc,0);	/* note cut command */				vol=255;			} else				UniNote(((note>>4)*OCTAVE)+(note&0xf));	/* normal note */		}		if(vol<255) UniPTEffect(0xc,vol);		S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,			tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE);		UniNewline();	}	return UniDup();}BOOL S3M_Load(BOOL curious){	int t,u,track = 0;	SAMPLE *q;	UBYTE pan[32];	/* try to read module header */	_mm_read_string(mh->songname,28,modreader);	mh->t1a         =_mm_read_UBYTE(modreader);	mh->type        =_mm_read_UBYTE(modreader);	_mm_read_UBYTES(mh->unused1,2,modreader);	mh->ordnum      =_mm_read_I_UWORD(modreader);	mh->insnum      =_mm_read_I_UWORD(modreader);	mh->patnum      =_mm_read_I_UWORD(modreader);	mh->flags       =_mm_read_I_UWORD(modreader);	mh->tracker     =_mm_read_I_UWORD(modreader);	mh->fileformat  =_mm_read_I_UWORD(modreader);	_mm_read_string(mh->scrm,4,modreader);	mh->mastervol   =_mm_read_UBYTE(modreader);	mh->initspeed   =_mm_read_UBYTE(modreader);	mh->inittempo   =_mm_read_UBYTE(modreader);	mh->mastermult  =_mm_read_UBYTE(modreader);	mh->ultraclick  =_mm_read_UBYTE(modreader);	mh->pantable    =_mm_read_UBYTE(modreader);	_mm_read_UBYTES(mh->unused2,8,modreader);	mh->special     =_mm_read_I_UWORD(modreader);	_mm_read_UBYTES(mh->channels,32,modreader);	if(_mm_eof(modreader)) {		_mm_errno = MMERR_LOADING_HEADER;		return 0;	}	/* then we can decide the module type */	tracker=mh->tracker>>12;	if((!tracker)||(tracker>=NUMTRACKERS))		tracker=NUMTRACKERS-1; /* unknown tracker */	else {		if(mh->tracker>=0x3217)			tracker=NUMTRACKERS+1; /* IT 2.14p4 */		else if(mh->tracker>=0x3216)			tracker=NUMTRACKERS; /* IT 2.14p3 */		else tracker--;	}	of.modtype = strdup(S3M_Version[tracker]);	if(tracker<NUMTRACKERS) {		of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';		of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';		of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0';	}	/* set module variables */	of.songname    = DupStr(mh->songname,28,0);	of.numpat      = mh->patnum;	of.reppos      = 0;	of.numins      = of.numsmp = mh->insnum;	of.initspeed   = mh->initspeed;	of.inittempo   = mh->inittempo;	of.initvolume  = mh->mastervol<<1;	of.flags      |= UF_ARPMEM | UF_PANNING;	if((mh->tracker==0x1300)||(mh->flags&64))		of.flags|=UF_S3MSLIDES;	of.bpmlimit    = 32;	/* read the order data */	if(!AllocPositions(mh->ordnum)) return 0;	if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;	for(t=0;t<mh->ordnum;t++) {		origpositions[t]=_mm_read_UBYTE(modreader);		if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))			origpositions[t]=255/*mh->patnum-1*/;	}	if(_mm_eof(modreader)) {		_mm_errno = MMERR_LOADING_HEADER;		return 0;	}	poslookupcnt=mh->ordnum;	S3MIT_CreateOrders(curious);	if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))		return 0;	/* read the instrument+pattern parapointers */	_mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);	if(mh->pantable==252) {		/* read the panning table (ST 3.2 addition.  See below for further		   portions of channel panning [past reampper]). */		_mm_read_UBYTES(pan,32,modreader);	}	if(_mm_eof(modreader)) {		_mm_errno = MMERR_LOADING_HEADER;		return 0;	}	/* load samples */	if(!AllocSamples()) return 0;	q = of.samples;	for(t=0;t<of.numins;t++) {		S3MSAMPLE s;		/* seek to instrument position */		_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);		/* and load sample info */		s.type      =_mm_read_UBYTE(modreader);		_mm_read_string(s.filename,12,modreader);		s.memsegh   =_mm_read_UBYTE(modreader);		s.memsegl   =_mm_read_I_UWORD(modreader);		s.length    =_mm_read_I_ULONG(modreader);		s.loopbeg   =_mm_read_I_ULONG(modreader);		s.loopend   =_mm_read_I_ULONG(modreader);		s.volume    =_mm_read_UBYTE(modreader);		s.dsk       =_mm_read_UBYTE(modreader);		s.pack      =_mm_read_UBYTE(modreader);		s.flags     =_mm_read_UBYTE(modreader);		s.c2spd     =_mm_read_I_ULONG(modreader);		_mm_read_UBYTES(s.unused,12,modreader);		_mm_read_string(s.sampname,28,modreader);		_mm_read_string(s.scrs,4,modreader);		/* ScreamTracker imposes a 64000 bytes (not 64k !) limit */		if (s.length > 64000)			s.length = 64000;		if(_mm_eof(modreader)) {			_mm_errno = MMERR_LOADING_SAMPLEINFO;			return 0;		}		q->samplename = DupStr(s.sampname,28,0);		q->speed      = s.c2spd;		q->length     = s.length;		q->loopstart  = s.loopbeg;		q->loopend    = s.loopend;		q->volume     = s.volume;		q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;		if(s.flags&1) q->flags |= SF_LOOP;		if(s.flags&4) q->flags |= SF_16BITS;		if(mh->fileformat==1) q->flags |= SF_SIGNED;		/* don't load sample if it doesn't have the SCRS tag */		if(memcmp(s.scrs,"SCRS",4)) q->length = 0;		q++;	}	/* determine the number of channels actually used. */	of.numchn = 0;	memset(remap,-1,32*sizeof(UBYTE));	for(t=0;t<of.numpat;t++) {		/* seek to pattern position (+2 skip pattern length) */		_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);		if(S3M_GetNumChannels()) return 0;	}	/* build the remap array  */	for(t=0;t<32;t++)		if(!remap[t]) 			remap[t]=of.numchn++;	/* set panning positions after building remap chart! */	for(t=0;t<32;t++) 		if((mh->channels[t]<32)&&(remap[t]!=-1)) {			if(mh->channels[t]<8)				of.panning[remap[t]]=0x30;			else				of.panning[remap[t]]=0xc0;		}	if(mh->pantable==252)		/* set panning positions according to panning table (new for st3.2) */		for(t=0;t<32;t++)			if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))				of.panning[remap[t]]=(pan[t]&0xf)<<4;	/* load pattern info */	of.numtrk=of.numpat*of.numchn;	if(!AllocTracks()) return 0;	if(!AllocPatterns()) return 0;	for(t=0;t<of.numpat;t++) {		/* seek to pattern position (+2 skip pattern length) */		_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);		if(!S3M_ReadPattern()) return 0;		for(u=0;u<of.numchn;u++)			if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;	}	return 1;}CHAR *S3M_LoadTitle(void){	CHAR s[28];	_mm_fseek(modreader,0,SEEK_SET);	if(!_mm_read_UBYTES(s,28,modreader)) return NULL;	return(DupStr(s,28,0));}/*========== Loader information */MIKMODAPI MLOADER load_s3m={	NULL,	"S3M",	"S3M (Scream Tracker 3)",	S3M_Init,	S3M_Test,	S3M_Load,	S3M_Cleanup,	S3M_LoadTitle};/* ex:set ts=4: */

⌨️ 快捷键说明

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