1
0
Fork 0
forked from len0rd/rockbox

mikmod: Upgrade mikmod core from v3.2.0 to v3.3.11

* Get rid of the non-functional GT2 loader
 * Add the UMX loader
 * Add HQ mixer routines (and make it configurable)
 * Allow samplerate to be configured at run/playtime
 * Support >64KHz mixing/playback
 * Correctly restore non-boost status

(The diff to upstream is much smaller now too!)

Change-Id: Iaa4ac901ba9cd4123bb225656976e78271353a72
This commit is contained in:
Solomon Peachy 2020-08-08 21:56:15 -04:00
parent 8c7780bafc
commit b4e70422a3
43 changed files with 5072 additions and 2802 deletions

View file

@ -15351,6 +15351,46 @@
swcodec: "Surround" swcodec: "Surround"
</voice> </voice>
</phrase> </phrase>
<phrase>
id: LANG_MIKMOD_HQMIXER
desc: in mikmod settings menu
user: core
<source>
*: none
lowmem: none
swcodec: "HQ Mixer"
</source>
<dest>
*: none
lowmem: none
swcodec: "HQ Mixer"
</dest>
<voice>
*: none
lowmem: none
swcodec: "High Quality Mixer"
</voice>
</phrase>
<phrase>
id: LANG_MIKMOD_SAMPLERATE
desc: in mikmod settings menu
user: core
<source>
*: none
lowmem: none
swcodec: "Sample Rate"
</source>
<dest>
*: none
lowmem: none
swcodec: "Sample Rate"
</dest>
<voice>
*: none
lowmem: none
swcodec: "Sample Rate"
</voice>
</phrase>
<phrase> <phrase>
id: LANG_CPU_BOOST id: LANG_CPU_BOOST
desc: in mikmod settings menu desc: in mikmod settings menu

View file

@ -5,7 +5,6 @@ load_asy.c
load_dsm.c load_dsm.c
load_far.c load_far.c
load_gdm.c load_gdm.c
load_gt2.c
load_imf.c load_imf.c
load_it.c load_it.c
load_m15.c load_m15.c
@ -17,6 +16,7 @@ load_s3m.c
load_stm.c load_stm.c
load_stx.c load_stx.c
load_ult.c load_ult.c
load_umx.c
load_uni.c load_uni.c
load_xm.c load_xm.c
mdreg.c mdreg.c
@ -34,6 +34,7 @@ sloader.c
strdup.c strdup.c
strstr.c strstr.c
virtch.c virtch.c
virtch2.c
virtch_common.c virtch_common.c
mikmod.c mikmod.c

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_669.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id: $
Composer 669 module loader Composer 669 module loader
@ -53,7 +53,7 @@ typedef struct S69HEADER {
UBYTE marker[2]; UBYTE marker[2];
CHAR message[108]; CHAR message[108];
UBYTE nos; UBYTE nos;
UBYTE rbnop; UBYTE RBnop;
UBYTE looporder; UBYTE looporder;
UBYTE orders[0x80]; UBYTE orders[0x80];
UBYTE tempos[0x80]; UBYTE tempos[0x80];
@ -81,7 +81,7 @@ static S69NOTE* s69pat=NULL;
static S69HEADER* mh=NULL; static S69HEADER* mh=NULL;
/* file type identification */ /* file type identification */
static CHAR* S69_Version[]={ static const CHAR* S69_Version[]={
"Composer 669", "Composer 669",
"Extended 669" "Extended 669"
}; };
@ -134,6 +134,8 @@ static void S69_Cleanup(void)
{ {
MikMod_free(s69pat); MikMod_free(s69pat);
MikMod_free(mh); MikMod_free(mh);
mh=NULL;
s69pat=NULL;
} }
static int S69_LoadPatterns(void) static int S69_LoadPatterns(void)
@ -256,7 +258,7 @@ static int S69_Load(int curious)
_mm_read_UBYTES(mh->marker,2,modreader); _mm_read_UBYTES(mh->marker,2,modreader);
_mm_read_UBYTES(mh->message,108,modreader); _mm_read_UBYTES(mh->message,108,modreader);
mh->nos=_mm_read_UBYTE(modreader); mh->nos=_mm_read_UBYTE(modreader);
mh->rbnop=_mm_read_UBYTE(modreader); mh->RBnop=_mm_read_UBYTE(modreader);
mh->looporder=_mm_read_UBYTE(modreader); mh->looporder=_mm_read_UBYTE(modreader);
_mm_read_UBYTES(mh->orders,0x80,modreader); _mm_read_UBYTES(mh->orders,0x80,modreader);
for(i=0;i<0x80;i++) for(i=0;i<0x80;i++)
@ -281,9 +283,9 @@ static int S69_Load(int curious)
of.initspeed=4; of.initspeed=4;
of.inittempo=78; of.inittempo=78;
of.songname=DupStr(mh->message,36,1); of.songname=DupStr(mh->message,36,1);
of.modtype=StrDup(S69_Version[memcmp(mh->marker,"JN",2)==0]); of.modtype=MikMod_strdup(S69_Version[memcmp(mh->marker,"JN",2)==0]);
of.numchn=8; of.numchn=8;
of.numpat=mh->rbnop; of.numpat=mh->RBnop;
of.numins=of.numsmp=mh->nos; of.numins=of.numsmp=mh->nos;
of.numtrk=of.numchn*of.numpat; of.numtrk=of.numchn*of.numpat;
of.flags=UF_XMPERIODS|UF_LINEAR; of.flags=UF_XMPERIODS|UF_LINEAR;
@ -292,7 +294,7 @@ static int S69_Load(int curious)
for(i=36+35;(i>=36+0)&&(mh->message[i]==' ');i--) mh->message[i]=0; for(i=36+35;(i>=36+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
for(i=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0; for(i=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
if((mh->message[0])||(mh->message[36])||(mh->message[72])) if((mh->message[0])||(mh->message[36])||(mh->message[72]))
if((of.comment=(CHAR*)MikMod_malloc(3*(36+1)+1))) { if((of.comment=(CHAR*)MikMod_malloc(3*(36+1)+1)) != NULL) {
strncpy(of.comment,mh->message,36); strncpy(of.comment,mh->message,36);
strcat(of.comment,"\r"); strcat(of.comment,"\r");
if (mh->message[36]) strncat(of.comment,mh->message+36,36); if (mh->message[36]) strncat(of.comment,mh->message+36,36);
@ -304,7 +306,7 @@ static int S69_Load(int curious)
if(!AllocPositions(0x80)) return 0; if(!AllocPositions(0x80)) return 0;
for(i=0;i<0x80;i++) { for(i=0;i<0x80;i++) {
if(mh->orders[i]>=mh->rbnop) break; if(mh->orders[i]>=mh->RBnop) break;
of.positions[i]=mh->orders[i]; of.positions[i]=mh->orders[i];
} }
of.numpos=i; of.numpos=i;

View file

@ -20,8 +20,6 @@
/*============================================================================== /*==============================================================================
$Id: load_amf.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
DMP Advanced Module Format loader DMP Advanced Module Format loader
==============================================================================*/ ==============================================================================*/
@ -112,9 +110,11 @@ static void AMF_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(track); MikMod_free(track);
mh=NULL;
track=NULL;
} }
static int AMF_UnpackTrack(MREADER* modreader) static int AMF_UnpackTrack(MREADER* r)
{ {
ULONG tracksize; ULONG tracksize;
UBYTE row,cmd; UBYTE row,cmd;
@ -124,14 +124,14 @@ static int AMF_UnpackTrack(MREADER* modreader)
memset(track,0,64*sizeof(AMFNOTE)); memset(track,0,64*sizeof(AMFNOTE));
/* read packed track */ /* read packed track */
if (modreader) { if (r) {
tracksize=_mm_read_I_UWORD(modreader); tracksize=_mm_read_I_UWORD(r);
tracksize+=((ULONG)_mm_read_UBYTE(modreader))<<16; tracksize+=((ULONG)_mm_read_UBYTE(r))<<16;
if (tracksize) if (tracksize)
while(tracksize--) { while(tracksize--) {
row=_mm_read_UBYTE(modreader); row=_mm_read_UBYTE(r);
cmd=_mm_read_UBYTE(modreader); cmd=_mm_read_UBYTE(r);
arg=_mm_read_SBYTE(modreader); arg=_mm_read_SBYTE(r);
/* unexpected end of track */ /* unexpected end of track */
if(!tracksize) { if(!tracksize) {
if((row==0xff)&&(cmd==0xff)&&(arg==-1)) if((row==0xff)&&(cmd==0xff)&&(arg==-1))
@ -337,7 +337,7 @@ static int AMF_Load(int curious)
AMFSAMPLE s; AMFSAMPLE s;
SAMPLE *q; SAMPLE *q;
UWORD *track_remap; UWORD *track_remap;
ULONG samplepos; ULONG samplepos, fileend;
int channel_remap[16]; int channel_remap[16];
(void)curious; (void)curious;
@ -386,7 +386,7 @@ static int AMF_Load(int curious)
of.inittempo = mh->songbpm; of.inittempo = mh->songbpm;
AMF_Version[AMFTEXTLEN-3]='0'+(mh->version/10); AMF_Version[AMFTEXTLEN-3]='0'+(mh->version/10);
AMF_Version[AMFTEXTLEN-1]='0'+(mh->version%10); AMF_Version[AMFTEXTLEN-1]='0'+(mh->version%10);
of.modtype = StrDup(AMF_Version); of.modtype = MikMod_strdup(AMF_Version);
of.numchn = mh->numchannels; of.numchn = mh->numchannels;
of.numtrk = mh->numorders*mh->numchannels; of.numtrk = mh->numorders*mh->numchannels;
if (mh->numtracks>of.numtrk) if (mh->numtracks>of.numtrk)
@ -466,7 +466,10 @@ static int AMF_Load(int curious)
s.c2spd =_mm_read_I_UWORD(modreader); s.c2spd =_mm_read_I_UWORD(modreader);
if(s.c2spd==8368) s.c2spd=8363; if(s.c2spd==8368) s.c2spd=8363;
s.volume =_mm_read_UBYTE(modreader); s.volume =_mm_read_UBYTE(modreader);
if(mh->version>=11) { /* "the tribal zone.amf" and "the way its gonna b.amf" by Maelcum
* are the only version 10 files I can find, and they have 32 bit
* reppos and repend, not 16. */
if(mh->version>=10) {/* was 11 */
s.reppos =_mm_read_I_ULONG(modreader); s.reppos =_mm_read_I_ULONG(modreader);
s.repend =_mm_read_I_ULONG(modreader); s.repend =_mm_read_I_ULONG(modreader);
} else { } else {
@ -493,7 +496,7 @@ static int AMF_Load(int curious)
} }
/* read track table */ /* read track table */
if(!(track_remap=MikMod_calloc(mh->numtracks+1,sizeof(UWORD)))) if(!(track_remap=(UWORD*)MikMod_calloc(mh->numtracks+1,sizeof(UWORD))))
return 0; return 0;
_mm_read_I_UWORDS(track_remap+1,mh->numtracks,modreader); _mm_read_I_UWORDS(track_remap+1,mh->numtracks,modreader);
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {
@ -505,6 +508,11 @@ static int AMF_Load(int curious)
for(realtrackcnt=t=0;t<=mh->numtracks;t++) for(realtrackcnt=t=0;t<=mh->numtracks;t++)
if (realtrackcnt<track_remap[t]) if (realtrackcnt<track_remap[t])
realtrackcnt=track_remap[t]; realtrackcnt=track_remap[t];
if (realtrackcnt > (int)mh->numtracks) {
MikMod_free(track_remap);
_mm_errno=MMERR_NOT_A_MODULE;
return 0;
}
for(t=0;t<of.numpat*of.numchn;t++) for(t=0;t<of.numpat*of.numchn;t++)
of.patterns[t]=(of.patterns[t]<=mh->numtracks)? of.patterns[t]=(of.patterns[t]<=mh->numtracks)?
track_remap[of.patterns[t]]-1:(int)realtrackcnt; track_remap[of.patterns[t]]-1:(int)realtrackcnt;
@ -531,18 +539,32 @@ static int AMF_Load(int curious)
for(t=realtrackcnt;t<of.numtrk;t++) of.tracks[t]=NULL; for(t=realtrackcnt;t<of.numtrk;t++) of.tracks[t]=NULL;
/* compute sample offsets */ /* compute sample offsets */
if(_mm_eof(modreader)) goto fail;
samplepos=_mm_ftell(modreader); samplepos=_mm_ftell(modreader);
_mm_fseek(modreader,0,SEEK_END);
fileend=_mm_ftell(modreader);
_mm_fseek(modreader,samplepos,SEEK_SET);
for(realsmpcnt=t=0;t<of.numsmp;t++) for(realsmpcnt=t=0;t<of.numsmp;t++)
if(realsmpcnt<of.samples[t].seekpos) if(realsmpcnt<of.samples[t].seekpos)
realsmpcnt=of.samples[t].seekpos; realsmpcnt=of.samples[t].seekpos;
for(t=1;t<=realsmpcnt;t++) { for(t=1;t<=realsmpcnt;t++) {
q=of.samples; q=of.samples;
while(q->seekpos!=t) q++; u=0;
while(q->seekpos!=t) {
if(++u==of.numsmp)
goto fail;
q++;
}
q->seekpos=samplepos; q->seekpos=samplepos;
samplepos+=q->length; samplepos+=q->length;
} }
if(samplepos>fileend)
goto fail;
return 1; return 1;
fail:
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
} }
static CHAR *AMF_LoadTitle(void) static CHAR *AMF_LoadTitle(void)

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_asy.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
ASYLUM Music Format v1.0 (.amf) loader ASYLUM Music Format v1.0 (.amf) loader
adapted from load_mod.c by Raphael Assenat <raph@raphnet.net>, adapted from load_mod.c by Raphael Assenat <raph@raphnet.net>,
@ -77,7 +77,8 @@ typedef struct MODNOTE {
/* This table is taken from AMF2MOD.C /* This table is taken from AMF2MOD.C
* written in 1995 by Mr. P / Powersource * written in 1995 by Mr. P / Powersource
* mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */ * mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */
UWORD periodtable[]={6848,6464,6096,5760,5424,5120,4832,4560,4304, static const UWORD periodtable[] = {
6848,6464,6096,5760,5424,5120,4832,4560,4304,
4064,3840,3628,3424,3232,3048,2880,2712,2560, 4064,3840,3628,3424,3232,3048,2880,2712,2560,
2416,2280,2152,2032,1920,1814,1712,1616,1524, 2416,2280,2152,2032,1920,1814,1712,1616,1524,
1440,1356,1280,1208,1140,1076,1016, 960, 907, 1440,1356,1280,1208,1140,1076,1016, 960, 907,
@ -140,9 +141,11 @@ static void ASY_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(patbuf); MikMod_free(patbuf);
mh = NULL;
patbuf = NULL;
} }
static void ConvertNote(MODNOTE *n) static int ConvertNote(MODNOTE *n)
{ {
UBYTE instrument, effect, effdat, note; UBYTE instrument, effect, effdat, note;
UWORD period; UWORD period;
@ -218,7 +221,15 @@ static void ConvertNote(MODNOTE *n)
if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0)) if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
effdat &= 0xf0; effdat &= 0xf0;
if (effect == 0x1b) {
return 0; /* UniEffect(UNI_S3MEFFECTQ,dat) ? */
}
if (effect > 0xf) {
return 0; /* return -1 to fail? */
}
UniPTEffect(effect, effdat); UniPTEffect(effect, effdat);
return 0;
} }
static UBYTE *ConvertTrack(MODNOTE *n) static UBYTE *ConvertTrack(MODNOTE *n)
@ -227,7 +238,8 @@ static UBYTE *ConvertTrack(MODNOTE *n)
UniReset(); UniReset();
for (t = 0; t < 64; t++) { for (t = 0; t < 64; t++) {
ConvertNote(n); if (ConvertNote(n) < 0)
return NULL;
UniNewline(); UniNewline();
n += of.numchn; n += of.numchn;
} }
@ -237,8 +249,7 @@ static UBYTE *ConvertTrack(MODNOTE *n)
/* Loads all patterns of a modfile and converts them into the 3 byte format. */ /* Loads all patterns of a modfile and converts them into the 3 byte format. */
static int ML_LoadPatterns(void) static int ML_LoadPatterns(void)
{ {
int t, tracks = 0; unsigned int t, s, tracks = 0;
unsigned int s;
if (!AllocPatterns()) { if (!AllocPatterns()) {
return 0; return 0;
@ -280,15 +291,15 @@ static int ASY_Load(int curious)
ULONG seekpos; ULONG seekpos;
(void)curious; (void)curious;
// no title in asylum amf files :( /* no title in asylum amf files :( */
strcpy(mh->songname, ""); mh->songname[0] = '\0';
_mm_fseek(modreader, 0x23, SEEK_SET); _mm_fseek(modreader, 0x23, SEEK_SET);
mh->num_patterns = _mm_read_UBYTE(modreader); mh->num_patterns = _mm_read_UBYTE(modreader);
mh->num_orders = _mm_read_UBYTE(modreader); mh->num_orders = _mm_read_UBYTE(modreader);
// skip unknown byte /* skip unknown byte */
(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);
_mm_read_UBYTES(mh->positions, 256, modreader); _mm_read_UBYTES(mh->positions, 256, modreader);
/* read samples headers*/ /* read samples headers*/
@ -302,7 +313,7 @@ static int ASY_Load(int curious)
s->finetune = _mm_read_UBYTE(modreader); s->finetune = _mm_read_UBYTE(modreader);
s->volume = _mm_read_UBYTE(modreader); s->volume = _mm_read_UBYTE(modreader);
(void)_mm_read_UBYTE(modreader); // skip unknown byte _mm_skip_BYTE(modreader);/* skip unknown byte */
s->length = _mm_read_I_ULONG(modreader); s->length = _mm_read_I_ULONG(modreader);
s->reppos = _mm_read_I_ULONG(modreader); s->reppos = _mm_read_I_ULONG(modreader);
s->replen = _mm_read_I_ULONG(modreader); s->replen = _mm_read_I_ULONG(modreader);
@ -324,12 +335,16 @@ static int ASY_Load(int curious)
of.numpat = mh->num_patterns; of.numpat = mh->num_patterns;
of.numtrk = of.numpat * of.numchn; of.numtrk = of.numpat * of.numchn;
/* Copy positions (orders) */ /* Copy positions (orders) */
if (!AllocPositions(of.numpos)) if (!AllocPositions(of.numpos))
return 0; return 0;
for (t = 0; t < of.numpos; t++) { for (t = 0; t < of.numpos; t++) {
of.positions[t] = mh->positions[t]; of.positions[t] = mh->positions[t];
if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
} }
/* Finally, init the sampleinfo structures */ /* Finally, init the sampleinfo structures */
@ -369,7 +384,7 @@ static int ASY_Load(int curious)
q++; q++;
} }
of.modtype = StrDup(descr); of.modtype = MikMod_strdup(descr);
if (!ML_LoadPatterns()) if (!ML_LoadPatterns())
return 0; return 0;
@ -379,9 +394,7 @@ static int ASY_Load(int curious)
static CHAR *ASY_LoadTitle(void) static CHAR *ASY_LoadTitle(void)
{ {
CHAR *s = ""; // no titles return MikMod_strdup("");
return (DupStr(s, 21, 1));
} }
/*========== Loader information */ /*========== Loader information */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_dsm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
DSIK internal format (DSM) module loader DSIK internal format (DSM) module loader
@ -89,9 +89,9 @@ typedef struct DSMNOTE {
/*========== Loader variables */ /*========== Loader variables */
static CHAR* SONGID="SONG"; static const CHAR* SONGID="SONG";
static CHAR* INSTID="INST"; static const CHAR* INSTID="INST";
static CHAR* PATTID="PATT"; static const CHAR* PATTID="PATT";
static UBYTE blockid[4]; static UBYTE blockid[4];
static ULONG blockln; static ULONG blockln;
@ -101,7 +101,7 @@ static DSMNOTE* dsmbuf=NULL;
static CHAR DSM_Version[]="DSIK DSM-format"; static CHAR DSM_Version[]="DSIK DSM-format";
static unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'}; static const unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'};
/*========== Loader code */ /*========== Loader code */
@ -126,6 +126,8 @@ static void DSM_Cleanup(void)
{ {
MikMod_free(dsmbuf); MikMod_free(dsmbuf);
MikMod_free(mh); MikMod_free(mh);
dsmbuf = NULL;
mh = NULL;
} }
static int GetBlockHeader(void) static int GetBlockHeader(void)
@ -266,7 +268,7 @@ static int DSM_Load(int curious)
/* set module variables */ /* set module variables */
of.initspeed=mh->speed; of.initspeed=mh->speed;
of.inittempo=mh->bpm; of.inittempo=mh->bpm;
of.modtype=StrDup(DSM_Version); of.modtype=MikMod_strdup(DSM_Version);
of.numchn=mh->numtrk; of.numchn=mh->numtrk;
of.numpat=mh->numpat; of.numpat=mh->numpat;
of.numtrk=of.numchn*of.numpat; of.numtrk=of.numchn*of.numpat;
@ -286,6 +288,11 @@ static int DSM_Load(int curious)
for(t=0;t<mh->numord;t++) { for(t=0;t<mh->numord;t++) {
int order=mh->orders[t]; int order=mh->orders[t];
if(order==255) order=LAST_PATTERN; if(order==255) order=LAST_PATTERN;
else if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
of.positions[of.numpos]=order; of.positions[of.numpos]=order;
if(mh->orders[t]<254) of.numpos++; if(mh->orders[t]<254) of.numpos++;
} }

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_far.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Farandole (FAR) module loader Farandole (FAR) module loader
@ -92,7 +92,7 @@ static FARHEADER1 *mh1 = NULL;
static FARHEADER2 *mh2 = NULL; static FARHEADER2 *mh2 = NULL;
static FARNOTE *pat = NULL; static FARNOTE *pat = NULL;
static unsigned char FARSIG[4+3]={'F','A','R',0xfe,13,10,26}; static const unsigned char FARSIG[4+3]={'F','A','R',0xfe,13,10,26};
/*========== Loader code */ /*========== Loader code */
@ -119,6 +119,9 @@ static void FAR_Cleanup(void)
MikMod_free(mh1); MikMod_free(mh1);
MikMod_free(mh2); MikMod_free(mh2);
MikMod_free(pat); MikMod_free(pat);
mh1 = NULL;
mh2 = NULL;
pat = NULL;
} }
static UBYTE *FAR_ConvertTrack(FARNOTE* n,int rows) static UBYTE *FAR_ConvertTrack(FARNOTE* n,int rows)
@ -196,7 +199,7 @@ static int FAR_Load(int curious)
mh1->stlen = _mm_read_I_UWORD (modreader); mh1->stlen = _mm_read_I_UWORD (modreader);
/* init modfile data */ /* init modfile data */
of.modtype = StrDup(FAR_Version); of.modtype = MikMod_strdup(FAR_Version);
of.songname = DupStr(mh1->songname,40,1); of.songname = DupStr(mh1->songname,40,1);
of.numchn = 16; of.numchn = 16;
of.initspeed = mh1->speed; of.initspeed = mh1->speed;
@ -207,7 +210,12 @@ static int FAR_Load(int curious)
/* read songtext into comment field */ /* read songtext into comment field */
if(mh1->stlen) if(mh1->stlen)
if (!ReadLinedComment(mh1->stlen, 66)) return 0; if (!ReadLinedComment(mh1->stlen, 132)) return 0;
if(_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
/* try to read module header (second part) */ /* try to read module header (second part) */
_mm_read_UBYTES(mh2->orders,256,modreader); _mm_read_UBYTES(mh2->orders,256,modreader);
@ -238,12 +246,14 @@ static int FAR_Load(int curious)
if(!AllocPatterns()) return 0; if(!AllocPatterns()) return 0;
for(t=0;t<of.numpat;t++) { for(t=0;t<of.numpat;t++) {
UBYTE rows=0/* ,tempo */; UBYTE rows=0;
UBYTE tempo;
memset(pat,0,256*16*4*sizeof(FARNOTE)); memset(pat,0,256*16*4*sizeof(FARNOTE));
if(mh2->patsiz[t]) { if(mh2->patsiz[t]) {
rows = _mm_read_UBYTE(modreader); rows = _mm_read_UBYTE(modreader);
/* tempo = */ (void)_mm_read_UBYTE(modreader); tempo = _mm_read_UBYTE(modreader);
(void)tempo; /* unused */
crow = pat; crow = pat;
/* file often allocates 64 rows even if there are less in pattern */ /* file often allocates 64 rows even if there are less in pattern */
@ -315,7 +325,7 @@ static int FAR_Load(int curious)
q->seekpos = _mm_ftell(modreader); q->seekpos = _mm_ftell(modreader);
_mm_fseek(modreader,q->length,SEEK_CUR); _mm_fseek(modreader,q->length,SEEK_CUR);
} else } else
q->samplename = DupStr(NULL,0,0); q->samplename = MikMod_strdup("");
q++; q++;
} }
return 1; return 1;
@ -328,7 +338,7 @@ static CHAR *FAR_LoadTitle(void)
_mm_fseek(modreader,4,SEEK_SET); _mm_fseek(modreader,4,SEEK_SET);
if(!_mm_read_UBYTES(s,40,modreader)) return NULL; if(!_mm_read_UBYTES(s,40,modreader)) return NULL;
return(DupStr(s,40,1)); return (DupStr(s,40,1));
} }
/*========== Loader information */ /*========== Loader information */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_gdm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
General DigiMusic (GDM) module loader General DigiMusic (GDM) module loader
@ -114,7 +114,7 @@ typedef struct GDMSAMPLE {
static GDMHEADER *mh=NULL; /* pointer to GDM header */ static GDMHEADER *mh=NULL; /* pointer to GDM header */
static GDMNOTE *gdmbuf=NULL; /* pointer to a complete GDM pattern */ static GDMNOTE *gdmbuf=NULL; /* pointer to a complete GDM pattern */
CHAR GDM_Version[]="General DigiMusic 1.xx"; static CHAR GDM_Version[]="General DigiMusic 1.xx";
static int GDM_Test(void) static int GDM_Test(void)
{ {
@ -146,36 +146,45 @@ static void GDM_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(gdmbuf); MikMod_free(gdmbuf);
mh=NULL;
gdmbuf=NULL;
} }
static int GDM_ReadPattern(void) static int GDM_ReadPattern(void)
{ {
int pos,flag,ch,i,maxch; int pos,flag,ch,i;
GDMNOTE n; GDMNOTE n;
UWORD length,x=0; SLONG length,x=0;
/* get pattern length */ /* get pattern length */
length=_mm_read_I_UWORD(modreader)-2; length=(SLONG)_mm_read_I_UWORD(modreader);
length-=2;
/* clear pattern data */ /* clear pattern data */
memset(gdmbuf,255,32*64*sizeof(GDMNOTE)); memset(gdmbuf,255,32*64*sizeof(GDMNOTE));
pos=0; pos=0;
maxch=0;
while (x<length) { while (x<length) {
memset(&n,255,sizeof(GDMNOTE)); memset(&n,255,sizeof(GDMNOTE));
flag=_mm_read_UBYTE(modreader); flag=_mm_read_UBYTE(modreader);
x++; x++;
if (_mm_eof(modreader)) { if (_mm_eof(modreader))
_mm_errno=MMERR_LOADING_PATTERN;
return 0; return 0;
}
ch=flag&31; ch=flag&31;
if (ch>maxch) maxch=ch; if (ch > of.numchn)
return 0;
if (!flag) { if (!flag) {
pos++; pos++;
if (x==length) {
if (pos > 64)
return 0;
} else {
if (pos >= 64)
return 0;
}
continue; continue;
} }
if (flag&0x60) { if (flag&0x60) {
@ -390,7 +399,7 @@ static int GDM_Load(int curious)
} }
/* now we fill */ /* now we fill */
of.modtype=StrDup(GDM_Version); of.modtype=MikMod_strdup(GDM_Version);
of.modtype[18]=mh->majorver+'0'; of.modtype[18]=mh->majorver+'0';
of.modtype[20]=mh->minorver/10+'0'; of.modtype[20]=mh->minorver/10+'0';
of.modtype[21]=mh->minorver%10+'0'; of.modtype[21]=mh->minorver%10+'0';

View file

@ -1,375 +0,0 @@
/* MikMod sound library
(c) 2003-2004 Raphael Assenat 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_gt2.c,v 1.2 2005/03/30 19:09:35 realtech Exp $
Graoumf tracker format (.GT2)
==============================================================================*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <ctype.h>
#include <stdio.h>
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <string.h>
#include "mikmod_internals.h"
typedef struct GT_NOTE {
UBYTE note; /* 24-127, 48 is middle C-2. 0 for no note */
UBYTE inst; /* instrument, 1-255, 0 for none */
UWORD effect; /* 0 for no FX */
UBYTE vv; /* volume, 1-255, 0 for no volume */
} GT_NOTE;
/* general info chunk */
typedef struct GT2_CHUNK {
UBYTE magic[4]; /* must be 'GT2' */
UBYTE version; /* 01 = v0.7, 02=v0.726, 03=v0.731 */
ULONG chunk_size;
CHAR module_name[33]; /* 32 bytes in file */
CHAR comments_author[161]; /* 160 bytes in file */
UBYTE date_day;
UBYTE date_month;
UWORD date_year;
CHAR tracker_name[25]; /* 24 in file */
UWORD initial_speed;
UWORD initial_tempo;
UWORD initial_master_volume; /* 000 - fff */
UWORD num_voices; /* for the following panning section */
UWORD *voice_pannings; /* 000 - 800 - fff */
} GT2_CHUNK;
/* track volume chunk */
typedef struct TVOL_CHUNK {
UBYTE id[4]; /* must be TVOL */
ULONG chunk_size;
UWORD num_tracks; /* for the following array */
UWORD *track_volumes; /* 0000 - 1000 - FFFF */
} TVOL_CHUNK;
/* extra-comment chunk */
typedef struct XCOM_CHUNK {
UBYTE id[4]; /* must be XCOM */
ULONG chunk_size;
ULONG comment_len;
CHAR *comment; /* comment_len + 1 allocated */
} XCOM_CHUNK;
/* song chunk */
typedef struct SONG_CHUNK {
UBYTE id[4]; /* must be SONG */
ULONG chunk_size;
UWORD song_length;
UWORD song_repeat_point;
UWORD *patterns; /* pattern numbers */
} SONG_CHUNK;
/* pattern set chunk */
typedef struct PATS_CHUNK {
UBYTE id[4]; /* must be PATS */
ULONG chunk_size;
UWORD num_tracks; /* total number of tracks for the song */
UWORD num_patterns; /* number of patterns saved */
} PATS_CHUNK;
/* pattern chunk */
typedef struct PATD_CHUNK {
UBYTE id[4]; /* must be PATD */
ULONG chunk_size;
UWORD pattern_number;
CHAR pattern_name[17]; /* 16 in file */
UWORD codage_version; /* only 0 expected for now */
/* version 0 (full pattern) */
UWORD num_lines;
UWORD num_tracks;
GT_NOTE *notes; /* sizeof(GT_NOTE) * num_lines * num_tracks */
} PATD_CHUNK;
/* instrument set chunk */
typedef struct ORCH_CHUNK {
UBYTE id[4]; /* must be ORCH */
ULONG chunk_size;
UWORD num_instruments; /* number of instruments saved */
} ORCH_CHUNK;
typedef struct INST_NOTE {
UBYTE samp_number;/* sample number for midi note */
CHAR tranp; /* transposition for note */
} INST_NOTE;
/* instrument chunk */
typedef struct INST_CHUNK {
UBYTE id[4]; /* must be INST */
ULONG chunk_size;
UWORD instrument_number;
CHAR name[29]; /* 28 in file */
UWORD type; /* 0 = sample */
UWORD volume; /* volume, 0-255 */
UWORD auto_panning; /* autopanning, 000 - 800 - fff, -1 no autopanning */
UWORD volume_enveloppe_number;
UWORD tone_enveloppe_number;
UWORD pan_enveloppe_number;
UBYTE reserved[10];
INST_NOTE note[128];
} INST_CHUNK;
typedef struct SAMP_CHUNK {
UBYTE id[4]; /* must be SAMP */
ULONG chunk_size;
UWORD sample_number;
CHAR name[29]; /* 28 in file */
UWORD flags; /* bit0: 0 = mono, 1 = stereo bit1: 0 normal loop, bit2: ping pong loop */
UWORD autopanning; /* 000 - 800 - fff */
UWORD num_bits; /* 8 or 16 */
UWORD rate; /* between 2000 and 65000 */
ULONG length; /* bytes */
ULONG loop_start; /* bytes */
ULONG loop_len; /* bytes */
UWORD volume; /* 0 - 255 */
UWORD finetune; /* (-8..+7 -> -1..+7/8 halftone) */
UWORD codage; /* 0 */
UBYTE *data;
} SAMP_CHUNK;
typedef struct xENV_CHUNK {
UBYTE id[4]; /* must be VENV, TENV or PENV */
ULONG chunk_size;
UWORD envelope_number;
CHAR name[21]; /* 20 in file */
UWORD keyoff_offset;
UBYTE *data;
} xENV_CHUNK;
typedef struct ENDC_CHUNK {
UBYTE id[4]; /* must be ENDC */
ULONG chunk_size;
ULONG total_module_size;
} ENDC_CHUNK;
typedef union GT_CHUNK
{
UBYTE id[4]; /* must be TVOL */
GT2_CHUNK gt2;
TVOL_CHUNK tvol;
XCOM_CHUNK xcom;
SONG_CHUNK song;
PATS_CHUNK pats;
PATD_CHUNK patd;
ORCH_CHUNK orch;
INST_CHUNK inst;
SAMP_CHUNK samp;
xENV_CHUNK xenv;
ENDC_CHUNK endc;
} GT_CHUNK;
static GT_CHUNK *loadChunk(void)
{
GT_CHUNK *new_chunk = MikMod_malloc(sizeof(GT_CHUNK));
/* the file chunk id only use 3 bytes, others 4 */
_mm_read_UBYTES(new_chunk->id, 3, modreader);
if (! (new_chunk->id[0]=='G' &&
new_chunk->id[1]=='T' &&
new_chunk->id[2]=='2')
)
{
_mm_read_UBYTES(&new_chunk->id[3], 1, modreader);
}
else
{
new_chunk->id[3] = ' ';
}
printf(">> %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
if (!memcmp(new_chunk, "GT2", 3)) {
_mm_read_UBYTES(&new_chunk->gt2.version, 1, modreader);
_mm_read_M_ULONGS(&new_chunk->gt2.chunk_size, 1, modreader);
new_chunk->gt2.module_name[32] = 0;
_mm_read_UBYTES(&new_chunk->gt2.module_name, 32, modreader);
new_chunk->gt2.comments_author[160] = 0;
_mm_read_UBYTES(&new_chunk->gt2.comments_author, 160, modreader);
_mm_read_UBYTES(&new_chunk->gt2.date_day, 1, modreader);
_mm_read_UBYTES(&new_chunk->gt2.date_month, 1, modreader);
_mm_read_M_UWORDS(&new_chunk->gt2.date_year, 1, modreader);
new_chunk->gt2.tracker_name[24] = 0;
_mm_read_UBYTES(&new_chunk->gt2.tracker_name, 24, modreader);
_mm_read_M_UWORDS(&new_chunk->gt2.initial_speed, 1, modreader);
_mm_read_M_UWORDS(&new_chunk->gt2.initial_tempo, 1, modreader);
_mm_read_M_UWORDS(&new_chunk->gt2.initial_master_volume, 1, modreader);
_mm_read_M_UWORDS(&new_chunk->gt2.num_voices, 1, modreader);
new_chunk->gt2.voice_pannings = MikMod_malloc(2*new_chunk->gt2.num_voices);
_mm_read_M_UWORDS(new_chunk->gt2.voice_pannings, new_chunk->gt2.num_voices, modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "TVOL", 4)) {
new_chunk->tvol.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->tvol.num_tracks = _mm_read_M_UWORD(modreader);
new_chunk->tvol.track_volumes = MikMod_malloc(new_chunk->tvol.num_tracks * 2);
_mm_read_M_UWORDS(new_chunk->tvol.track_volumes, new_chunk->tvol.num_tracks, modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "XCOM", 4)) {
new_chunk->xcom.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->xcom.comment_len = _mm_read_M_ULONG(modreader);
new_chunk->xcom.comment = MikMod_malloc(new_chunk->xcom.comment_len + 1);
_mm_read_UBYTES(new_chunk->xcom.comment, new_chunk->xcom.comment_len, modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "SONG", 4)) {
new_chunk->song.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->song.song_length = _mm_read_M_UWORD(modreader);
new_chunk->song.song_repeat_point = _mm_read_M_UWORD(modreader);
new_chunk->song.patterns = MikMod_malloc(2*new_chunk->song.song_length);
_mm_read_M_UWORDS(new_chunk->song.patterns, new_chunk->song.song_length, modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "PATS", 4)) {
new_chunk->pats.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->pats.num_tracks = _mm_read_M_UWORD(modreader);
new_chunk->pats.num_patterns = _mm_read_M_UWORD(modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "PATD", 4)) {
new_chunk->patd.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->patd.pattern_number = _mm_read_M_UWORD(modreader);
new_chunk->patd.pattern_name[16] = 0;
_mm_read_UBYTES(new_chunk->patd.pattern_name, 16, modreader);
new_chunk->patd.codage_version = _mm_read_M_UWORD(modreader);
new_chunk->patd.num_lines = _mm_read_M_UWORD(modreader);
new_chunk->patd.num_tracks = _mm_read_M_UWORD(modreader);
new_chunk->patd.notes = MikMod_malloc(5 *
new_chunk->patd.num_lines *
new_chunk->patd.num_tracks);
_mm_read_UBYTES(new_chunk->patd.notes,
new_chunk->patd.num_lines * new_chunk->patd.num_tracks * 5,
modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "ORCH", 4)) {
new_chunk->orch.chunk_size = _mm_read_M_ULONG(modreader);
new_chunk->orch.num_instruments = _mm_read_M_UWORD(modreader);
return new_chunk;
}
if (!memcmp(new_chunk, "INST", 4)) {
return new_chunk;
}
if (!memcmp(new_chunk, "SAMP", 4)) {
return new_chunk;
}
if (!memcmp(new_chunk, "VENV", 4)) {
return new_chunk;
}
if (!memcmp(new_chunk, "TENV", 4)) {
return new_chunk;
}
if (!memcmp(new_chunk, "PENV", 4)) {
return new_chunk;
}
if (!memcmp(new_chunk, "ENDC", 4)) {
return new_chunk;
}
printf("?? %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
MikMod_free(new_chunk);
return NULL; // unknown chunk
}
static int GT2_Init(void)
{
return 1;
}
static int GT2_Test(void)
{
UBYTE magic[3];
_mm_fseek(modreader, 0, SEEK_SET);
_mm_read_UBYTES(magic, 3, modreader);
if (magic[0] == 'G' && magic[1] == 'T' && magic[2] == '2') { return 1; }
return 0;
}
static int GT2_Load(int curious)
{
GT_CHUNK *tmp;
(void)curious;
_mm_fseek(modreader, 0, SEEK_SET);
while ( (tmp = loadChunk() ))
{
printf("%c%c%c%c\n", tmp->id[0], tmp->id[1], tmp->id[2], tmp->id[3]);
}
return 0;
}
static void GT2_Cleanup(void)
{
}
static CHAR *GT2_LoadTitle(void)
{
CHAR title[33];
_mm_fseek(modreader, 8, SEEK_SET);
_mm_read_UBYTES(title, 32, modreader);
title[32]=0;
return (DupStr(title, 32, 1));
}
MIKMODAPI MLOADER load_gt2 = {
NULL,
"Graoumf Tracker 2 module",
"Graoumf Tracker 2",
GT2_Init,
GT2_Test,
GT2_Load,
GT2_Cleanup,
GT2_LoadTitle
};

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_imf.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Imago Orpheus (IMF) module loader Imago Orpheus (IMF) module loader
@ -127,12 +127,36 @@ static IMFHEADER *mh=NULL;
static int IMF_Test(void) static int IMF_Test(void)
{ {
UBYTE id[4]; UBYTE buf[512], *p;
int t, chn;
_mm_fseek(modreader,0x3c,SEEK_SET); _mm_fseek(modreader,0x3c,SEEK_SET);
if(!_mm_read_UBYTES(id,4,modreader)) return 0; if (!_mm_read_UBYTES(buf,4,modreader)) return 0;
if(!memcmp(id,"IM10",4)) return 1; if (memcmp(buf,"IM10",4) != 0) return 0; /* no magic */
_mm_fseek(modreader,32,SEEK_SET);
if (_mm_read_I_UWORD(modreader) > 256) return 0;/* bad ordnum */
if (_mm_read_I_UWORD(modreader) > 256) return 0;/* bad patnum */
if (_mm_read_I_UWORD(modreader) > 256) return 0;/* bad insnum */
_mm_fseek(modreader,64,SEEK_SET);
if(!_mm_read_UBYTES(buf,512,modreader)) return 0;
/* verify channel status */
for (t = 0, chn = 0, p = &buf[15]; t < 512; t += 16, p += 16) {
switch (*p) {
case 0: /* channel enabled */
case 1: /* channel muted */
chn++;
break;
case 2: /* channel disabled */
break;
default: /* bad status value */
return 0; return 0;
}
}
if(!chn) return 0; /* no channels found */
return 1;
} }
static int IMF_Init(void) static int IMF_Init(void)
@ -149,6 +173,8 @@ static void IMF_Cleanup(void)
MikMod_free(imfpat); MikMod_free(imfpat);
MikMod_free(mh); MikMod_free(mh);
imfpat=NULL;
mh=NULL;
} }
static int IMF_ReadPattern(SLONG size,UWORD rows) static int IMF_ReadPattern(SLONG size,UWORD rows)
@ -410,7 +436,7 @@ static int IMF_Load(int curious)
/* set module variables */ /* set module variables */
of.songname=DupStr(mh->songname,31,1); of.songname=DupStr(mh->songname,31,1);
of.modtype=StrDup(IMF_Version); of.modtype=MikMod_strdup(IMF_Version);
of.numpat=mh->patnum; of.numpat=mh->patnum;
of.numins=mh->insnum; of.numins=mh->insnum;
of.reppos=0; of.reppos=0;
@ -467,6 +493,13 @@ static int IMF_Load(int curious)
if(!AllocPositions(of.numpos)) return 0; if(!AllocPositions(of.numpos)) return 0;
for(t=u=0;t<mh->ordnum;t++) for(t=u=0;t<mh->ordnum;t++)
if(mh->orders[t]!=0xff) of.positions[u++]=mh->orders[t]; if(mh->orders[t]!=0xff) of.positions[u++]=mh->orders[t];
for(t=0;t<of.numpos;t++) {
if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"position[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
}
/* load pattern info */ /* load pattern info */
of.numtrk=of.numpat*of.numchn; of.numtrk=of.numpat*of.numchn;
@ -509,16 +542,16 @@ static int IMF_Load(int curious)
_mm_read_I_UWORDS(ih.panenv,IMFENVCNT,modreader); _mm_read_I_UWORDS(ih.panenv,IMFENVCNT,modreader);
_mm_read_I_UWORDS(ih.pitenv,IMFENVCNT,modreader); _mm_read_I_UWORDS(ih.pitenv,IMFENVCNT,modreader);
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define IMF_FinishLoadingEnvelope(name) \ #define IMF_FinishLoadingEnvelope(name) \
ih. name##pts=_mm_read_UBYTE(modreader); \ ih. name##pts=_mm_read_UBYTE(modreader); \
ih. name##sus=_mm_read_UBYTE(modreader); \ ih. name##sus=_mm_read_UBYTE(modreader); \
ih. name##beg=_mm_read_UBYTE(modreader); \ ih. name##beg=_mm_read_UBYTE(modreader); \
ih. name##end=_mm_read_UBYTE(modreader); \ ih. name##end=_mm_read_UBYTE(modreader); \
ih. name##flg=_mm_read_UBYTE(modreader); \ ih. name##flg=_mm_read_UBYTE(modreader); \
(void)_mm_read_UBYTE(modreader); \ _mm_skip_BYTE(modreader); \
(void)_mm_read_UBYTE(modreader); \ _mm_skip_BYTE(modreader); \
(void)_mm_read_UBYTE(modreader) _mm_skip_BYTE(modreader)
#else #else
#define IMF_FinishLoadingEnvelope(name) \ #define IMF_FinishLoadingEnvelope(name) \
ih. name/**/pts=_mm_read_UBYTE(modreader); \ ih. name/**/pts=_mm_read_UBYTE(modreader); \
@ -526,9 +559,9 @@ static int IMF_Load(int curious)
ih. name/**/beg=_mm_read_UBYTE(modreader); \ ih. name/**/beg=_mm_read_UBYTE(modreader); \
ih. name/**/end=_mm_read_UBYTE(modreader); \ ih. name/**/end=_mm_read_UBYTE(modreader); \
ih. name/**/flg=_mm_read_UBYTE(modreader); \ ih. name/**/flg=_mm_read_UBYTE(modreader); \
(void)_mm_read_UBYTE(modreader); \ _mm_skip_BYTE(modreader); \
(void)_mm_read_UBYTE(modreader); \ _mm_skip_BYTE(modreader); \
(void)_mm_read_UBYTE(modreader) _mm_skip_BYTE(modreader)
#endif #endif
IMF_FinishLoadingEnvelope(vol); IMF_FinishLoadingEnvelope(vol);
@ -562,7 +595,7 @@ static int IMF_Load(int curious)
d->samplenumber[u]=ih.what[u]>ih.numsmp?0xffff:ih.what[u]+of.numsmp; d->samplenumber[u]=ih.what[u]>ih.numsmp?0xffff:ih.what[u]+of.numsmp;
d->volfade=ih.volfade; d->volfade=ih.volfade;
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define IMF_ProcessEnvelope(name) \ #define IMF_ProcessEnvelope(name) \
for (u = 0; u < (IMFENVCNT >> 1); u++) { \ for (u = 0; u < (IMFENVCNT >> 1); u++) { \
d-> name##env[u].pos = ih. name##env[u << 1]; \ d-> name##env[u].pos = ih. name##env[u << 1]; \
@ -613,12 +646,12 @@ static int IMF_Load(int curious)
/* allocate more room for sample information if necessary */ /* allocate more room for sample information if necessary */
if(of.numsmp+u==wavcnt) { if(of.numsmp+u==wavcnt) {
wavcnt+=IMF_SMPINCR; wavcnt+=IMF_SMPINCR;
if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))) { if(!(nextwav=(ULONG*)MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))) {
if(wh) MikMod_free(wh); if(wh) MikMod_free(wh);
_mm_errno=MMERR_OUT_OF_MEMORY; _mm_errno=MMERR_OUT_OF_MEMORY;
return 0; return 0;
} }
if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) { if(!(wh=(IMFWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) {
MikMod_free(nextwav); MikMod_free(nextwav);
_mm_errno=MMERR_OUT_OF_MEMORY; _mm_errno=MMERR_OUT_OF_MEMORY;
return 0; return 0;
@ -627,7 +660,7 @@ static int IMF_Load(int curious)
} }
_mm_read_string(s->samplename,13,modreader); _mm_read_string(s->samplename,13,modreader);
(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);
s->length =_mm_read_I_ULONG(modreader); s->length =_mm_read_I_ULONG(modreader);
s->loopstart =_mm_read_I_ULONG(modreader); s->loopstart =_mm_read_I_ULONG(modreader);
s->loopend =_mm_read_I_ULONG(modreader); s->loopend =_mm_read_I_ULONG(modreader);

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_it.c,v 1.4 2010/01/12 03:30:32 realtech Exp $ $Id$
Impulse tracker (IT) module loader Impulse tracker (IT) module loader
@ -45,7 +45,6 @@
#ifdef SUNOS #ifdef SUNOS
extern int fprintf(FILE *, const char *, ...); extern int fprintf(FILE *, const char *, ...);
extern int toupper(int);
#endif #endif
/*========== Module structure */ /*========== Module structure */
@ -167,7 +166,7 @@ static ITNOTE *last=NULL; /* uncompressing IT's pattern information */
static int numtrk=0; static int numtrk=0;
static unsigned int old_effect; /* if set, use S3M old-effects stuffs */ static unsigned int old_effect; /* if set, use S3M old-effects stuffs */
static CHAR* IT_Version[]={ static const CHAR* IT_Version[]={
"ImpulseTracker . ", "ImpulseTracker . ",
"Compressed ImpulseTracker . ", "Compressed ImpulseTracker . ",
"ImpulseTracker 2.14p3", "ImpulseTracker 2.14p3",
@ -177,7 +176,7 @@ static CHAR* IT_Version[]={
}; };
/* table for porta-to-note command within volume/panning column */ /* table for porta-to-note command within volume/panning column */
static UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255}; static const UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255};
/*========== Loader code */ /*========== Loader code */
@ -212,6 +211,13 @@ static void IT_Cleanup(void)
MikMod_free(last); MikMod_free(last);
MikMod_free(paraptr); MikMod_free(paraptr);
MikMod_free(origpositions); MikMod_free(origpositions);
mh=NULL;
poslookup=NULL;
itpat=NULL;
mask=NULL;
last=NULL;
paraptr=NULL;
origpositions=NULL;
} }
/* Because so many IT files have 64 channels as the set number used, but really /* Because so many IT files have 64 channels as the set number used, but really
@ -221,31 +227,32 @@ static void IT_Cleanup(void)
NOTE: You must first seek to the file location of the pattern before calling NOTE: You must first seek to the file location of the pattern before calling
this procedure. this procedure.
Returns 1 on error Returns 0 on error
*/ */
static int IT_GetNumChannels(UWORD patrows) static int IT_GetNumChannels(UWORD patrows)
{ {
int row=0,flag,ch; int row=0,flag,ch;
do { do {
if((flag=_mm_read_UBYTE(modreader))==EOF) { if(_mm_eof(modreader)) {
_mm_errno=MMERR_LOADING_PATTERN; _mm_errno=MMERR_LOADING_PATTERN;
return 1; return 0;
} }
flag=_mm_read_UBYTE(modreader);
if(!flag) if(!flag)
row++; row++;
else { else {
ch=(flag-1)&63; ch=(flag-1)&63;
remap[ch]=0; remap[ch]=0;
if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader); if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader);
if(mask[ch]&1) (void)_mm_read_UBYTE(modreader); if(mask[ch]&1) _mm_skip_BYTE(modreader);
if(mask[ch]&2) (void)_mm_read_UBYTE(modreader); if(mask[ch]&2) _mm_skip_BYTE(modreader);
if(mask[ch]&4) (void)_mm_read_UBYTE(modreader); if(mask[ch]&4) _mm_skip_BYTE(modreader);
if(mask[ch]&8) { (void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader); } if(mask[ch]&8) { _mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader); }
} }
} while(row<patrows); } while(row<patrows);
return 0; return 1;
} }
static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows) static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows)
@ -324,16 +331,20 @@ static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows)
static int IT_ReadPattern(UWORD patrows) static int IT_ReadPattern(UWORD patrows)
{ {
int row=0,flag,ch,blah; int row=0,flag,ch;
unsigned int blah;
ITNOTE *itt=itpat,dummy,*n,*l; ITNOTE *itt=itpat,dummy,*n,*l;
ITNOTE *ite=&itpat[200*64 -1];
UBYTE *m;
memset(itt,255,200*64*sizeof(ITNOTE)); memset(itt,255,200*64*sizeof(ITNOTE));
do { do {
if((flag=_mm_read_UBYTE(modreader))==EOF) { if(_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_PATTERN; _mm_errno = MMERR_LOADING_PATTERN;
return 0; return 0;
} }
flag=_mm_read_UBYTE(modreader);
if(!flag) { if(!flag) {
itt=&itt[of.numchn]; itt=&itt[of.numchn];
row++; row++;
@ -342,29 +353,38 @@ static int IT_ReadPattern(UWORD patrows)
if(ch!=-1) { if(ch!=-1) {
n=&itt[ch]; n=&itt[ch];
l=&last[ch]; l=&last[ch];
m=&mask[ch];
if(n > ite) { /* malformed file */
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
} else } else
{
n=l=&dummy; n=l=&dummy;
blah = 0;
m=(UBYTE*)&blah;
}
if(flag&128) mask[ch]=_mm_read_UBYTE(modreader); if(flag&128) *m=_mm_read_UBYTE(modreader);
if(mask[ch]&1) if(*m&1)
/* convert IT note off to internal note off */ /* convert IT note off to internal note off */
if((l->note=n->note=_mm_read_UBYTE(modreader))==255) if((l->note=n->note=_mm_read_UBYTE(modreader))==255)
l->note=n->note=253; l->note=n->note=253;
if(mask[ch]&2) if(*m&2)
l->ins=n->ins=_mm_read_UBYTE(modreader); l->ins=n->ins=_mm_read_UBYTE(modreader);
if(mask[ch]&4) if(*m&4)
l->volpan=n->volpan=_mm_read_UBYTE(modreader); l->volpan=n->volpan=_mm_read_UBYTE(modreader);
if(mask[ch]&8) { if(*m&8) {
l->cmd=n->cmd=_mm_read_UBYTE(modreader); l->cmd=n->cmd=_mm_read_UBYTE(modreader);
l->inf=n->inf=_mm_read_UBYTE(modreader); l->inf=n->inf=_mm_read_UBYTE(modreader);
} }
if(mask[ch]&16) if(*m&16)
n->note=l->note; n->note=l->note;
if(mask[ch]&32) if(*m&32)
n->ins=l->ins; n->ins=l->ins;
if(mask[ch]&64) if(*m&64)
n->volpan=l->volpan; n->volpan=l->volpan;
if(mask[ch]&128) { if(*m&128) {
n->cmd=l->cmd; n->cmd=l->cmd;
n->inf=l->inf; n->inf=l->inf;
} }
@ -379,38 +399,39 @@ static int IT_ReadPattern(UWORD patrows)
return 1; return 1;
} }
static void LoadMidiString(MREADER* modreader,CHAR* dest) static void LoadMidiString(MREADER* r,CHAR* dest)
{ {
CHAR *cur,*last; CHAR *curp,*lastp;
_mm_read_UBYTES(dest,32,modreader); memset(dest,0,33*sizeof(CHAR));/* caller sends midiline[33] */
cur=last=dest; _mm_read_UBYTES(dest,32,r);
curp=lastp=dest;
/* remove blanks and uppercase all */ /* remove blanks and uppercase all */
while(*last) { while(*lastp) {
if(isalnum((int)*last)) *(cur++)=toupper((int)*last); if(isalnum((int)*lastp)) *(curp++)=toupper((int)*lastp);
last++; lastp++;
} }
*cur=0; *curp=0;
} }
/* Load embedded midi information for resonant filters */ /* Load embedded midi information for resonant filters */
static void IT_LoadMidiConfiguration(MREADER* modreader) static void IT_LoadMidiConfiguration(MREADER* r)
{ {
int i; int i;
memset(filtermacros,0,sizeof(filtermacros)); memset(filtermacros,0,sizeof(filtermacros));
memset(filtersettings,0,sizeof(filtersettings)); memset(filtersettings,0,sizeof(filtersettings));
if (modreader) { /* information is embedded in file */ if (r) { /* information is embedded in file */
UWORD dat; UWORD dat;
CHAR midiline[33]; CHAR midiline[33];
dat=_mm_read_I_UWORD(modreader); dat=_mm_read_I_UWORD(r);
_mm_fseek(modreader,8*dat+0x120,SEEK_CUR); _mm_fseek(r,8*dat+0x120,SEEK_CUR);
/* read midi macros */ /* read midi macros */
for(i=0;i<UF_MAXMACRO;i++) { for(i=0;i<UF_MAXMACRO;i++) {
LoadMidiString(modreader,midiline); LoadMidiString(r,midiline);
if((!strncmp(midiline,"F0F00",5))&& if((!strncmp(midiline,"F0F00",5))&&
((midiline[5]=='0')||(midiline[5]=='1'))) ((midiline[5]=='0')||(midiline[5]=='1')))
filtermacros[i]=(midiline[5]-'0')|0x80; filtermacros[i]=(midiline[5]-'0')|0x80;
@ -418,7 +439,7 @@ static void IT_LoadMidiConfiguration(MREADER* modreader)
/* read standalone filters */ /* read standalone filters */
for(i=0x80;i<0x100;i++) { for(i=0x80;i<0x100;i++) {
LoadMidiString(modreader,midiline); LoadMidiString(r,midiline);
if((!strncmp(midiline,"F0F00",5))&& if((!strncmp(midiline,"F0F00",5))&&
((midiline[5]=='0')||(midiline[5]=='1'))) { ((midiline[5]=='0')||(midiline[5]=='1'))) {
filtersettings[i].filter=(midiline[5]-'0')|0x80; filtersettings[i].filter=(midiline[5]-'0')|0x80;
@ -446,7 +467,7 @@ static int IT_Load(int curious)
int t,u,lp; int t,u,lp;
INSTRUMENT *d; INSTRUMENT *d;
SAMPLE *q; SAMPLE *q;
/* int compressed=0; */ /*int compressed=0;*/
numtrk=0; numtrk=0;
filters=0; filters=0;
@ -479,6 +500,10 @@ static int IT_Load(int curious)
_mm_errno=MMERR_LOADING_HEADER; _mm_errno=MMERR_LOADING_HEADER;
return 0; return 0;
} }
if(mh->ordnum > 256 || mh->insnum > 255 || mh->smpnum > 255 || mh->patnum > 255) {
_mm_errno=MMERR_NOT_A_MODULE;
return 0;
}
/* set module variables */ /* set module variables */
of.songname = DupStr(mh->songname,26,0); /* make a cstr of songname */ of.songname = DupStr(mh->songname,26,0); /* make a cstr of songname */
@ -506,11 +531,11 @@ static int IT_Load(int curious)
/* 2.16 : IT 2.14p3 with resonant filters */ /* 2.16 : IT 2.14p3 with resonant filters */
/* 2.15 : IT 2.14p3 (improved compression) */ /* 2.15 : IT 2.14p3 (improved compression) */
if((mh->cwt<=0x219)&&(mh->cwt>=0x217)) if((mh->cwt<=0x219)&&(mh->cwt>=0x217))
of.modtype=StrDup(IT_Version[mh->cmwt<0x214?4:5]); of.modtype=MikMod_strdup(IT_Version[mh->cmwt<0x214?4:5]);
else if (mh->cwt>=0x215) else if (mh->cwt>=0x215)
of.modtype=StrDup(IT_Version[mh->cmwt<0x214?2:3]); of.modtype=MikMod_strdup(IT_Version[mh->cmwt<0x214?2:3]);
else { else {
of.modtype = StrDup(IT_Version[mh->cmwt<0x214?0:1]); of.modtype = MikMod_strdup(IT_Version[mh->cmwt<0x214?0:1]);
of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0'; of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0';
of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0'; of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0';
of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0'; of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0';
@ -550,7 +575,7 @@ static int IT_Load(int curious)
/* read the order data */ /* read the order data */
if(!AllocPositions(mh->ordnum)) return 0; if(!AllocPositions(mh->ordnum)) return 0;
if(!(origpositions=MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0; if(!(origpositions=(UWORD*)MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
for(t=0;t<mh->ordnum;t++) { for(t=0;t<mh->ordnum;t++) {
origpositions[t]=_mm_read_UBYTE(modreader); origpositions[t]=_mm_read_UBYTE(modreader);
@ -672,7 +697,7 @@ static int IT_Load(int curious)
if(s.flag&2) q->flags|=SF_16BITS; if(s.flag&2) q->flags|=SF_16BITS;
if((s.flag&8)&&(mh->cwt>=0x214)) { if((s.flag&8)&&(mh->cwt>=0x214)) {
q->flags|=SF_ITPACKED; q->flags|=SF_ITPACKED;
/* compressed=1; */ /*compressed=1;*/
} }
if(s.flag&16) q->flags|=SF_LOOP; if(s.flag&16) q->flags|=SF_LOOP;
if(s.flag&64) q->flags|=SF_BIDI; if(s.flag&64) q->flags|=SF_BIDI;
@ -726,7 +751,7 @@ static int IT_Load(int curious)
ih.trkvers = _mm_read_I_UWORD(modreader); ih.trkvers = _mm_read_I_UWORD(modreader);
ih.numsmp = _mm_read_UBYTE(modreader); ih.numsmp = _mm_read_UBYTE(modreader);
(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);
_mm_read_string(ih.name,26,modreader); _mm_read_string(ih.name,26,modreader);
_mm_read_UBYTES(ih.blank01,6,modreader); _mm_read_UBYTES(ih.blank01,6,modreader);
_mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader); _mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader);
@ -739,10 +764,12 @@ static int IT_Load(int curious)
} }
} else { } else {
/* load IT 2xx volume, pan and pitch envelopes */ /* load IT 2xx volume, pan and pitch envelopes */
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define IT_LoadEnvelope(name,type) \ #define IT_LoadEnvelope(name,type) \
ih. name##flg =_mm_read_UBYTE(modreader); \ ih. name##flg =_mm_read_UBYTE(modreader); \
ih. name##pts =_mm_read_UBYTE(modreader); \ ih. name##pts =_mm_read_UBYTE(modreader); \
if (ih. name##pts > ITENVCNT) \
ih. name##pts = ITENVCNT; \
ih. name##beg =_mm_read_UBYTE(modreader); \ ih. name##beg =_mm_read_UBYTE(modreader); \
ih. name##end =_mm_read_UBYTE(modreader); \ ih. name##end =_mm_read_UBYTE(modreader); \
ih. name##susbeg=_mm_read_UBYTE(modreader); \ ih. name##susbeg=_mm_read_UBYTE(modreader); \
@ -751,11 +778,13 @@ static int IT_Load(int curious)
ih. name##node[lp]=_mm_read_##type (modreader); \ ih. name##node[lp]=_mm_read_##type (modreader); \
ih. name##tick[lp]=_mm_read_I_UWORD(modreader); \ ih. name##tick[lp]=_mm_read_I_UWORD(modreader); \
} \ } \
(void)_mm_read_UBYTE(modreader) _mm_skip_BYTE(modreader)
#else #else
#define IT_LoadEnvelope(name,type) \ #define IT_LoadEnvelope(name,type) \
ih. name/**/flg =_mm_read_UBYTE(modreader); \ ih. name/**/flg =_mm_read_UBYTE(modreader); \
ih. name/**/pts =_mm_read_UBYTE(modreader); \ ih. name/**/pts =_mm_read_UBYTE(modreader); \
if (ih. name/**/pts > ITENVCNT) \
ih. name/**/pts = ITENVCNT; \
ih. name/**/beg =_mm_read_UBYTE(modreader); \ ih. name/**/beg =_mm_read_UBYTE(modreader); \
ih. name/**/end =_mm_read_UBYTE(modreader); \ ih. name/**/end =_mm_read_UBYTE(modreader); \
ih. name/**/susbeg=_mm_read_UBYTE(modreader); \ ih. name/**/susbeg=_mm_read_UBYTE(modreader); \
@ -764,7 +793,7 @@ static int IT_Load(int curious)
ih. name/**/node[lp]=_mm_read_/**/type (modreader); \ ih. name/**/node[lp]=_mm_read_/**/type (modreader); \
ih. name/**/tick[lp]=_mm_read_I_UWORD(modreader); \ ih. name/**/tick[lp]=_mm_read_I_UWORD(modreader); \
} \ } \
(void)_mm_read_UBYTE(modreader) _mm_skip_BYTE(modreader)
#endif #endif
IT_LoadEnvelope(vol,UBYTE); IT_LoadEnvelope(vol,UBYTE);
@ -827,7 +856,7 @@ static int IT_Load(int curious)
d->rpanvar = ih.rpanvar; d->rpanvar = ih.rpanvar;
} }
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define IT_ProcessEnvelope(name) \ #define IT_ProcessEnvelope(name) \
if(ih. name##flg&1) d-> name##flg|=EF_ON; \ if(ih. name##flg&1) d-> name##flg|=EF_ON; \
if(ih. name##flg&2) d-> name##flg|=EF_LOOP; \ if(ih. name##flg&2) d-> name##flg|=EF_LOOP; \
@ -863,10 +892,6 @@ static int IT_Load(int curious)
IT_ProcessEnvelope(vol); IT_ProcessEnvelope(vol);
// Secunia SA37775
if (ih.volpts>= ENVPOINTS)
ih.volpts = ENVPOINTS-1;
for(u=0;u<ih.volpts;u++) for(u=0;u<ih.volpts;u++)
d->volenv[u].val=(ih.volnode[u]<<2); d->volenv[u].val=(ih.volnode[u]<<2);
@ -946,7 +971,7 @@ static int IT_Load(int curious)
return 0; return 0;
} }
_mm_read_I_ULONG(modreader); _mm_read_I_ULONG(modreader);
if(IT_GetNumChannels(packlen)) return 0; if(!IT_GetNumChannels(packlen)) return 0;
} }
} }
@ -963,6 +988,8 @@ static int IT_Load(int curious)
if(!AllocTracks()) return 0; if(!AllocTracks()) return 0;
for(t=0;t<of.numpat;t++) { for(t=0;t<of.numpat;t++) {
UWORD packlen;
/* seek to pattern position */ /* seek to pattern position */
if(!paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */ if(!paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */
of.pattrows[t]=64; of.pattrows[t]=64;
@ -975,7 +1002,8 @@ static int IT_Load(int curious)
} }
} else { } else {
_mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET); _mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);
(void)_mm_read_I_UWORD(modreader); packlen=_mm_read_I_UWORD(modreader);
(void)packlen; /* unused */
of.pattrows[t]=_mm_read_I_UWORD(modreader); of.pattrows[t]=_mm_read_I_UWORD(modreader);
_mm_read_I_ULONG(modreader); _mm_read_I_ULONG(modreader);
if(!IT_ReadPattern(of.pattrows[t])) return 0; if(!IT_ReadPattern(of.pattrows[t])) return 0;

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_m15.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
15 instrument MOD loader 15 instrument MOD loader
Also supports Ultimate Sound Tracker (old M15 format) Also supports Ultimate Sound Tracker (old M15 format)
@ -79,33 +79,31 @@ static int ust_loader = 0; /* if TRUE, load as an ust module. */
/* known file formats which can confuse the loader */ /* known file formats which can confuse the loader */
#define REJECT 2 #define REJECT 2
static char *signatures[REJECT]={ static const char *signatures[REJECT]={
"CAKEWALK", /* cakewalk midi files */ "CAKEWALK", /* cakewalk midi files */
"SZDD" /* Microsoft compressed files */ "SZDD" /* Microsoft compressed files */
}; };
static int siglen[REJECT]={8,4}; static const int siglen[REJECT]={8,4};
/*========== Loader code */ /*========== Loader code */
static int LoadModuleHeader(MODULEHEADER *mh) static int LoadModuleHeader(MODULEHEADER *h)
{ {
int t,u; int t,u;
_mm_read_string(mh->songname,20,modreader); _mm_read_string(h->songname,20,modreader);
mh->songname[20]=0; /* just in case */
/* sanity check : title should contain printable characters and a bunch /* sanity check : title should contain printable characters and a bunch
of null chars */ of null chars */
for(t=0;t<20;t++) for(t=0;t<20;t++)
if((mh->songname[t])&&(mh->songname[t]<32)) return 0; if((h->songname[t])&&(h->songname[t]<32)) return 0;
for(t=0;(mh->songname[t])&&(t<20);t++); for(t=0;(h->songname[t])&&(t<20);t++);
if(t<20) for(;t<20;t++) if(mh->songname[t]) return 0; if(t<20) for(;t<20;t++) if(h->songname[t]) return 0;
for(t=0;t<15;t++) { for(t=0;t<15;t++) {
MSAMPINFO *s=&mh->samples[t]; MSAMPINFO *s=&h->samples[t];
_mm_read_string(s->samplename,22,modreader); _mm_read_string(s->samplename,22,modreader);
s->samplename[22]=0; /* just in case */
s->length =_mm_read_M_UWORD(modreader); s->length =_mm_read_M_UWORD(modreader);
s->finetune =_mm_read_UBYTE(modreader); s->finetune =_mm_read_UBYTE(modreader);
s->volume =_mm_read_UBYTE(modreader); s->volume =_mm_read_UBYTE(modreader);
@ -123,19 +121,19 @@ static int LoadModuleHeader(MODULEHEADER *mh)
if(s->finetune>>4) return 0; if(s->finetune>>4) return 0;
} }
mh->songlength =_mm_read_UBYTE(modreader); h->songlength =_mm_read_UBYTE(modreader);
mh->magic1 =_mm_read_UBYTE(modreader); /* should be 127 */ h->magic1 =_mm_read_UBYTE(modreader); /* should be 127 */
/* sanity check : no more than 128 positions, restart position in range */ /* sanity check : no more than 128 positions, restart position in range */
if((!mh->songlength)||(mh->songlength>128)) return 0; if((!h->songlength)||(h->songlength>128)) return 0;
/* values encountered so far are 0x6a and 0x78 */ /* values encountered so far are 0x6a and 0x78 */
if(((mh->magic1&0xf8)!=0x78)&&(mh->magic1!=0x6a)&&(mh->magic1>mh->songlength)) return 0; if(((h->magic1&0xf8)!=0x78)&&(h->magic1!=0x6a)&&(h->magic1>h->songlength)) return 0;
_mm_read_UBYTES(mh->positions,128,modreader); _mm_read_UBYTES(h->positions,128,modreader);
/* sanity check : pattern range is 0..63 */ /* sanity check : pattern range is 0..63 */
for(t=0;t<128;t++) for(t=0;t<128;t++)
if(mh->positions[t]>63) return 0; if(h->positions[t]>63) return 0;
return(!_mm_eof(modreader)); return(!_mm_eof(modreader));
} }
@ -152,7 +150,7 @@ static int CheckPatternType(int numpat)
for(t=0;t<numpat*(64U*4);t++) { for(t=0;t<numpat*(64U*4);t++) {
/* Load the pattern into the temp buffer and scan it */ /* Load the pattern into the temp buffer and scan it */
(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);
eff = _mm_read_UBYTE(modreader); eff = _mm_read_UBYTE(modreader);
dat = _mm_read_UBYTE(modreader); dat = _mm_read_UBYTE(modreader);
@ -177,45 +175,46 @@ static int CheckPatternType(int numpat)
static int M15_Test(void) static int M15_Test(void)
{ {
int t, numpat; int t, numpat;
MODULEHEADER mh; MODULEHEADER h;
ust_loader = 0; ust_loader = 0;
if(!LoadModuleHeader(&mh)) return 0; memset(&h, 0, sizeof(MODULEHEADER));
if(!LoadModuleHeader(&h)) return 0;
/* reject other file types */ /* reject other file types */
for(t=0;t<REJECT;t++) for(t=0;t<REJECT;t++)
if(!memcmp(mh.songname,signatures[t],siglen[t])) return 0; if(!memcmp(h.songname,signatures[t],siglen[t])) return 0;
if(mh.magic1>127) return 0; if(h.magic1>127) return 0;
if((!mh.songlength)||(mh.songlength>mh.magic1)) return 0; if((!h.songlength)||(h.songlength>h.magic1)) return 0;
for(t=0;t<15;t++) { for(t=0;t<15;t++) {
/* all finetunes should be zero */ /* all finetunes should be zero */
if(mh.samples[t].finetune) return 0; if(h.samples[t].finetune) return 0;
/* all volumes should be <= 64 */ /* all volumes should be <= 64 */
if(mh.samples[t].volume>64) return 0; if(h.samples[t].volume>64) return 0;
/* all instrument names should begin with s, st-, or a number */ /* all instrument names should begin with s, st-, or a number */
if((mh.samples[t].samplename[0]=='s')|| if((h.samples[t].samplename[0]=='s')||
(mh.samples[t].samplename[0]=='S')) { (h.samples[t].samplename[0]=='S')) {
if((memcmp(mh.samples[t].samplename,"st-",3)) && if((memcmp(h.samples[t].samplename,"st-",3)) &&
(memcmp(mh.samples[t].samplename,"ST-",3)) && (memcmp(h.samples[t].samplename,"ST-",3)) &&
(*mh.samples[t].samplename)) (*h.samples[t].samplename))
ust_loader = 1; ust_loader = 1;
} else } else
if(!isdigit((int)mh.samples[t].samplename[0])) if(!isdigit((int)h.samples[t].samplename[0]))
ust_loader = 1; ust_loader = 1;
if(mh.samples[t].length>4999||mh.samples[t].reppos>9999) { if(h.samples[t].length>4999||h.samples[t].reppos>9999) {
ust_loader = 0; ust_loader = 0;
if(mh.samples[t].length>32768) return 0; if(h.samples[t].length>32768) return 0;
} }
/* if loop information is incorrect as words, but correct as bytes, /* if loop information is incorrect as words, but correct as bytes,
this is likely to be an ust-style module */ this is likely to be an ust-style module */
if((mh.samples[t].reppos+mh.samples[t].replen>mh.samples[t].length)&& if((h.samples[t].reppos+h.samples[t].replen>h.samples[t].length)&&
(mh.samples[t].reppos+mh.samples[t].replen<(mh.samples[t].length<<1))){ (h.samples[t].reppos+h.samples[t].replen<(h.samples[t].length<<1))) {
ust_loader = 1; ust_loader = 1;
return 1; return 1;
} }
@ -223,9 +222,9 @@ static int M15_Test(void)
if(!ust_loader) return 1; if(!ust_loader) return 1;
} }
for(numpat=0,t=0;t<mh.songlength;t++) for(numpat=0,t=0;t<h.songlength;t++)
if(mh.positions[t]>numpat) if(h.positions[t]>numpat)
numpat = mh.positions[t]; numpat = h.positions[t];
numpat++; numpat++;
switch(CheckPatternType(numpat)) { switch(CheckPatternType(numpat)) {
case 0: /* indecisive, so check more clues... */ case 0: /* indecisive, so check more clues... */
@ -242,7 +241,7 @@ static int M15_Test(void)
static int M15_Init(void) static int M15_Init(void)
{ {
if(!(mh=(MODULEHEADER*)MikMod_malloc(sizeof(MODULEHEADER)))) return 0; if(!(mh=(MODULEHEADER*)MikMod_calloc(1,sizeof(MODULEHEADER)))) return 0;
return 1; return 1;
} }
@ -250,6 +249,8 @@ static void M15_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(patbuf); MikMod_free(patbuf);
mh=NULL;
patbuf=NULL;
} }
/* /*
@ -372,8 +373,7 @@ static UBYTE *M15_ConvertTrack(MODNOTE* n)
/* Loads all patterns of a modfile and converts them into the 3 byte format. */ /* Loads all patterns of a modfile and converts them into the 3 byte format. */
static int M15_LoadPatterns(void) static int M15_LoadPatterns(void)
{ {
int t,tracks=0; unsigned int t,s,tracks=0;
unsigned int s;
if(!AllocPatterns()) return 0; if(!AllocPatterns()) return 0;
if(!AllocTracks()) return 0; if(!AllocTracks()) return 0;
@ -398,9 +398,10 @@ static int M15_LoadPatterns(void)
static int M15_Load(int curious) static int M15_Load(int curious)
{ {
int t,scan; unsigned int t,scan;
SAMPLE *q; SAMPLE *q;
MSAMPINFO *s; MSAMPINFO *s;
(void)curious;
/* try to read module header */ /* try to read module header */
if(!LoadModuleHeader(mh)) { if(!LoadModuleHeader(mh)) {
@ -409,9 +410,9 @@ static int M15_Load(int curious)
} }
if(ust_loader) if(ust_loader)
of.modtype = StrDup("Ultimate Soundtracker"); of.modtype = MikMod_strdup("Ultimate Soundtracker");
else else
of.modtype = StrDup("Soundtracker"); of.modtype = MikMod_strdup("Soundtracker");
/* set module variables */ /* set module variables */
of.initspeed = 6; of.initspeed = 6;

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_med.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Amiga MED module loader Amiga MED module loader
@ -189,6 +189,12 @@ static void MED_Cleanup(void)
MikMod_free(ba); MikMod_free(ba);
MikMod_free(mmd0pat); MikMod_free(mmd0pat);
MikMod_free(mmd1pat); MikMod_free(mmd1pat);
me = NULL;
mh = NULL;
ms = NULL;
ba = NULL;
mmd0pat = NULL;
mmd1pat = NULL;
} }
static void EffectCvt(UBYTE eff, UBYTE dat) static void EffectCvt(UBYTE eff, UBYTE dat)
@ -338,7 +344,13 @@ static int LoadMEDPatterns(void)
of.numchn = numtracks; of.numchn = numtracks;
if (numlines > maxlines) if (numlines > maxlines)
maxlines = numlines; maxlines = numlines;
/* sanity check */
if (numtracks > 64)
return 0;
} }
/* sanity check */
if (! of.numchn) /* docs say 4, 8, 12 or 16 */
return 0;
of.numtrk = of.numpat * of.numchn; of.numtrk = of.numpat * of.numchn;
if (!AllocTracks()) if (!AllocTracks())
@ -346,10 +358,8 @@ static int LoadMEDPatterns(void)
if (!AllocPatterns()) if (!AllocPatterns())
return 0; return 0;
if (! if (!(mmd0pat = (MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD0NOTE))))
(mmd0pat = return 0;
(MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1),
sizeof(MMD0NOTE)))) return 0;
/* second read: read and convert patterns */ /* second read: read and convert patterns */
for (t = 0; t < of.numpat; t++) { for (t = 0; t < of.numpat; t++) {
@ -388,7 +398,15 @@ static int LoadMMD1Patterns(void)
of.numchn = numtracks; of.numchn = numtracks;
if (numlines > maxlines) if (numlines > maxlines)
maxlines = numlines; maxlines = numlines;
/* sanity check */
if (numtracks > 64)
return 0;
if (numlines >= 3200) /* per docs */
return 0;
} }
/* sanity check */
if (! of.numchn) /* docs say 4, 8, 12 or 16 */
return 0;
of.numtrk = of.numpat * of.numchn; of.numtrk = of.numpat * of.numchn;
if (!AllocTracks()) if (!AllocTracks())
@ -396,10 +414,8 @@ static int LoadMMD1Patterns(void)
if (!AllocPatterns()) if (!AllocPatterns())
return 0; return 0;
if (! if (!(mmd1pat = (MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD1NOTE))))
(mmd1pat = return 0;
(MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1),
sizeof(MMD1NOTE)))) return 0;
/* second read: really read and convert patterns */ /* second read: really read and convert patterns */
for (t = 0; t < of.numpat; t++) { for (t = 0; t < of.numpat; t++) {
@ -471,6 +487,11 @@ static int MED_Load(int curious)
ms->numblocks = _mm_read_M_UWORD(modreader); ms->numblocks = _mm_read_M_UWORD(modreader);
ms->songlen = _mm_read_M_UWORD(modreader); ms->songlen = _mm_read_M_UWORD(modreader);
_mm_read_UBYTES(ms->playseq, 256, modreader); _mm_read_UBYTES(ms->playseq, 256, modreader);
/* sanity check */
if (ms->numblocks > 255 || ms->songlen > 256) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
ms->deftempo = _mm_read_M_UWORD(modreader); ms->deftempo = _mm_read_M_UWORD(modreader);
ms->playtransp = _mm_read_SBYTE(modreader); ms->playtransp = _mm_read_SBYTE(modreader);
ms->flags = _mm_read_UBYTE(modreader); ms->flags = _mm_read_UBYTE(modreader);
@ -479,6 +500,11 @@ static int MED_Load(int curious)
_mm_read_UBYTES(ms->trkvol, 16, modreader); _mm_read_UBYTES(ms->trkvol, 16, modreader);
ms->mastervol = _mm_read_UBYTE(modreader); ms->mastervol = _mm_read_UBYTE(modreader);
ms->numsamples = _mm_read_UBYTE(modreader); ms->numsamples = _mm_read_UBYTE(modreader);
/* sanity check */
if (ms->numsamples > 64) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
/* check for a bad header */ /* check for a bad header */
if (_mm_eof(modreader)) { if (_mm_eof(modreader)) {
@ -505,6 +531,14 @@ static int MED_Load(int curious)
me->songname = _mm_read_M_ULONG(modreader); me->songname = _mm_read_M_ULONG(modreader);
me->songnamelen = _mm_read_M_ULONG(modreader); me->songnamelen = _mm_read_M_ULONG(modreader);
me->dumps = _mm_read_M_ULONG(modreader); me->dumps = _mm_read_M_ULONG(modreader);
/* sanity check */
if (me->annolen > 0xffff) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
/* truncate insane songnamelen (fail instead??) */
if (me->songnamelen > 256)
me->songnamelen = 256;
} }
/* seek to and read the samplepointer array */ /* seek to and read the samplepointer array */
@ -526,8 +560,14 @@ static int MED_Load(int curious)
/* copy song positions */ /* copy song positions */
if (!AllocPositions(ms->songlen)) if (!AllocPositions(ms->songlen))
return 0; return 0;
for (t = 0; t < ms->songlen; t++) for (t = 0; t < ms->songlen; t++) {
of.positions[t] = ms->playseq[t]; of.positions[t] = ms->playseq[t];
if (of.positions[t]>ms->numblocks) { /* SANITIY CHECK */
/* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],ms->numblocks);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
}
decimalvolumes = (ms->flags & 0x10) ? 0 : 1; decimalvolumes = (ms->flags & 0x10) ? 0 : 1;
bpmtempos = (ms->flags2 & 0x20) ? 1 : 0; bpmtempos = (ms->flags2 & 0x20) ? 1 : 0;
@ -571,7 +611,7 @@ static int MED_Load(int curious)
of.flags |= UF_HIGHBPM; of.flags |= UF_HIGHBPM;
} }
MED_Version[12] = mh->id; MED_Version[12] = mh->id;
of.modtype = StrDup(MED_Version); of.modtype = MikMod_strdup(MED_Version);
of.numchn = 0; /* will be counted later */ of.numchn = 0; /* will be counted later */
of.numpat = ms->numblocks; of.numpat = ms->numblocks;
of.numpos = ms->songlen; of.numpos = ms->songlen;
@ -582,7 +622,7 @@ static int MED_Load(int curious)
char *name; char *name;
_mm_fseek(modreader, me->songname, SEEK_SET); _mm_fseek(modreader, me->songname, SEEK_SET);
name = MikMod_malloc(me->songnamelen); name = (char *) MikMod_malloc(me->songnamelen);
_mm_read_UBYTES(name, me->songnamelen, modreader); _mm_read_UBYTES(name, me->songnamelen, modreader);
of.songname = DupStr(name, me->songnamelen, 1); of.songname = DupStr(name, me->songnamelen, 1);
MikMod_free(name); MikMod_free(name);
@ -694,7 +734,7 @@ static CHAR *MED_LoadTitle(void)
namelen = _mm_read_M_ULONG(modreader); namelen = _mm_read_M_ULONG(modreader);
_mm_fseek(modreader, posit, SEEK_SET); _mm_fseek(modreader, posit, SEEK_SET);
name = MikMod_malloc(namelen); name = (CHAR*) MikMod_malloc(namelen);
_mm_read_UBYTES(name, namelen, modreader); _mm_read_UBYTES(name, namelen, modreader);
retvalue = DupStr(name, namelen, 1); retvalue = DupStr(name, namelen, 1);
MikMod_free(name); MikMod_free(name);

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_mod.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Generic MOD loader (Protracker, StarTracker, FastTracker, etc) Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
@ -190,6 +190,8 @@ static void MOD_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(patbuf); MikMod_free(patbuf);
mh=NULL;
patbuf=NULL;
} }
/* /*
@ -309,8 +311,7 @@ static UBYTE *ConvertTrack(MODNOTE *n, int numchn)
/* Loads all patterns of a modfile and converts them into the 3 byte format. */ /* Loads all patterns of a modfile and converts them into the 3 byte format. */
static int ML_LoadPatterns(void) static int ML_LoadPatterns(void)
{ {
int t, tracks = 0; unsigned int t, s, tracks = 0;
unsigned int s;
if (!AllocPatterns()) if (!AllocPatterns())
return 0; return 0;
@ -477,7 +478,7 @@ static int MOD_Load(int curious)
q++; q++;
} }
of.modtype = StrDup(descr); of.modtype = MikMod_strdup(descr);
if (!ML_LoadPatterns()) if (!ML_LoadPatterns())
return 0; return 0;

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_mtm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
MTM module loader MTM module loader
@ -108,6 +108,8 @@ static void MTM_Cleanup(void)
{ {
MikMod_free(mtmtrk); MikMod_free(mtmtrk);
MikMod_free(mh); MikMod_free(mh);
mtmtrk=NULL;
mh=NULL;
} }
static UBYTE* MTM_Convert(void) static UBYTE* MTM_Convert(void)
@ -169,7 +171,7 @@ static int MTM_Load(int curious)
/* set module variables */ /* set module variables */
of.initspeed = 6; of.initspeed = 6;
of.inittempo = 125; of.inittempo = 125;
of.modtype = StrDup(MTM_Version); of.modtype = MikMod_strdup(MTM_Version);
of.numchn = mh->numchannels; of.numchn = mh->numchannels;
of.numtrk = mh->numtracks+1; /* get number of channels */ of.numtrk = mh->numtracks+1; /* get number of channels */
of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
@ -218,9 +220,15 @@ static int MTM_Load(int curious)
} }
if(!AllocPositions(of.numpos)) return 0; if(!AllocPositions(of.numpos)) return 0;
for(t=0;t<of.numpos;t++) for(t=0;t<of.numpos;t++) {
of.positions[t]=_mm_read_UBYTE(modreader); of.positions[t]=_mm_read_UBYTE(modreader);
for(;t<128;t++) (void)_mm_read_UBYTE(modreader); if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
}
for(;t<128;t++) _mm_skip_BYTE(modreader);
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_HEADER; _mm_errno = MMERR_LOADING_HEADER;
return 0; return 0;
@ -231,12 +239,12 @@ static int MTM_Load(int curious)
of.tracks[0]=MTM_Convert(); /* track 0 is empty */ of.tracks[0]=MTM_Convert(); /* track 0 is empty */
for(t=1;t<of.numtrk;t++) { for(t=1;t<of.numtrk;t++) {
int s; int s_idx;
for(s=0;s<64;s++) { for(s_idx=0;s_idx<64;s_idx++) {
mtmtrk[s].a=_mm_read_UBYTE(modreader); mtmtrk[s_idx].a=_mm_read_UBYTE(modreader);
mtmtrk[s].b=_mm_read_UBYTE(modreader); mtmtrk[s_idx].b=_mm_read_UBYTE(modreader);
mtmtrk[s].c=_mm_read_UBYTE(modreader); mtmtrk[s_idx].c=_mm_read_UBYTE(modreader);
} }
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_okt.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Oktalyzer (OKT) module loader Oktalyzer (OKT) module loader
@ -203,7 +203,7 @@ static int OKT_doSAMP(int len)
s.len = _mm_read_M_ULONG(modreader); s.len = _mm_read_M_ULONG(modreader);
s.loopbeg = _mm_read_M_UWORD(modreader) * 2; s.loopbeg = _mm_read_M_UWORD(modreader) * 2;
s.looplen = _mm_read_M_UWORD(modreader) * 2; s.looplen = _mm_read_M_UWORD(modreader) * 2;
(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);
s.volume = _mm_read_UBYTE(modreader); s.volume = _mm_read_UBYTE(modreader);
_mm_read_M_UWORD(modreader); _mm_read_M_UWORD(modreader);
@ -314,6 +314,7 @@ static int OKT_doPBOD(int patnum)
} }
MikMod_free(patbuf); MikMod_free(patbuf);
MikMod_free(okttrk); MikMod_free(okttrk);
okttrk = NULL;
return 1; return 1;
} }
@ -334,9 +335,9 @@ static int OKT_Load(int curious)
/* skip OKTALYZER header */ /* skip OKTALYZER header */
_mm_fseek(modreader, 8, SEEK_SET); _mm_fseek(modreader, 8, SEEK_SET);
of.songname = StrDup(""); of.songname = MikMod_strdup("");
of.modtype = StrDup("Amiga Oktalyzer"); of.modtype = MikMod_strdup("Amiga Oktalyzer");
of.numpos = of.reppos = 0; of.numpos = of.reppos = 0;
/* default values */ /* default values */
@ -442,7 +443,7 @@ static int OKT_Load(int curious)
static CHAR *OKT_LoadTitle(void) static CHAR *OKT_LoadTitle(void)
{ {
return StrDup(""); return MikMod_strdup("");
} }
/*========== Loader information */ /*========== Loader information */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_s3m.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Screamtracker (S3M) module loader Screamtracker (S3M) module loader
@ -104,7 +104,7 @@ static unsigned int tracker; /* tracker id */
/* tracker identifiers */ /* tracker identifiers */
#define NUMTRACKERS 4 #define NUMTRACKERS 4
static CHAR* S3M_Version[] = { static const CHAR * S3M_Version[] = {
"Screamtracker x.xx", "Screamtracker x.xx",
"Imago Orpheus x.xx (S3M format)", "Imago Orpheus x.xx (S3M format)",
"Impulse Tracker x.xx (S3M format)", "Impulse Tracker x.xx (S3M format)",
@ -113,7 +113,7 @@ static CHAR* S3M_Version[] = {
"Impulse Tracker 2.14p4 (S3M format)" "Impulse Tracker 2.14p4 (S3M format)"
}; };
/* version number position in above array */ /* version number position in above array */
static int numeric[NUMTRACKERS]={14,14,16,16}; static const int numeric[NUMTRACKERS]={14,14,16,16};
/*========== Loader code */ /*========== Loader code */
@ -144,6 +144,11 @@ static void S3M_Cleanup(void)
MikMod_free(poslookup); MikMod_free(poslookup);
MikMod_free(mh); MikMod_free(mh);
MikMod_free(origpositions); MikMod_free(origpositions);
s3mbuf=NULL;
paraptr=NULL;
poslookup=NULL;
mh=NULL;
origpositions=NULL;
} }
/* Because so many s3m files have 16 channels as the set number used, but really /* Because so many s3m files have 16 channels as the set number used, but really
@ -156,7 +161,7 @@ static void S3M_Cleanup(void)
NOTE: You must first seek to the file location of the pattern before calling NOTE: You must first seek to the file location of the pattern before calling
this procedure. this procedure.
Returns 1 on fail. */ Returns 0 on fail. */
static int S3M_GetNumChannels(void) static int S3M_GetNumChannels(void)
{ {
int row=0,flag,ch; int row=0,flag,ch;
@ -166,18 +171,18 @@ static int S3M_GetNumChannels(void)
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_PATTERN; _mm_errno = MMERR_LOADING_PATTERN;
return 1; return 0;
} }
if(flag) { if(flag) {
ch=flag&31; ch=flag&31;
if(mh->channels[ch]<32) remap[ch] = 0; if(mh->channels[ch]<32) remap[ch] = 0;
if(flag&32) {(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader);} if(flag&32) {_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);}
if(flag&64) (void)_mm_read_UBYTE(modreader); if(flag&64) _mm_skip_BYTE(modreader);
if(flag&128){(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader);} if(flag&128){_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);}
} else row++; } else row++;
} }
return 0; return 1;
} }
static int S3M_ReadPattern(void) static int S3M_ReadPattern(void)
@ -282,6 +287,10 @@ static int S3M_Load(int curious)
_mm_errno = MMERR_LOADING_HEADER; _mm_errno = MMERR_LOADING_HEADER;
return 0; return 0;
} }
if(mh->ordnum > 255 || mh->insnum > 255 || mh->patnum > 255) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
/* then we can decide the module type */ /* then we can decide the module type */
tracker=mh->tracker>>12; tracker=mh->tracker>>12;
@ -294,7 +303,7 @@ static int S3M_Load(int curious)
tracker=NUMTRACKERS; /* IT 2.14p3 */ tracker=NUMTRACKERS; /* IT 2.14p3 */
else tracker--; else tracker--;
} }
of.modtype = StrDup(S3M_Version[tracker]); of.modtype = MikMod_strdup(S3M_Version[tracker]);
if(tracker<NUMTRACKERS) { if(tracker<NUMTRACKERS) {
of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0'; of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';
of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0'; of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';
@ -315,7 +324,7 @@ static int S3M_Load(int curious)
/* read the order data */ /* read the order data */
if(!AllocPositions(mh->ordnum)) return 0; if(!AllocPositions(mh->ordnum)) return 0;
if(!(origpositions=MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0; if(!(origpositions=(UWORD*)MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
for(t=0;t<mh->ordnum;t++) { for(t=0;t<mh->ordnum;t++) {
origpositions[t]=_mm_read_UBYTE(modreader); origpositions[t]=_mm_read_UBYTE(modreader);
@ -374,7 +383,8 @@ static int S3M_Load(int curious)
_mm_read_string(s.scrs,4,modreader); _mm_read_string(s.scrs,4,modreader);
/* ScreamTracker imposes a 64000 bytes (not 64k !) limit */ /* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
if (s.length > 64000) /* enforce it, if we'll use S3MIT_SCREAM in S3M_ConvertTrack() */
if (s.length > 64000 && tracker == 1)
s.length = 64000; s.length = 64000;
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {
@ -388,7 +398,7 @@ static int S3M_Load(int curious)
q->loopstart = s.loopbeg; q->loopstart = s.loopbeg;
q->loopend = s.loopend; q->loopend = s.loopend;
q->volume = s.volume; q->volume = s.volume;
q->seekpos = (((long)s.memsegh)<<16|s.memsegl)<<4; q->seekpos = (((ULONG)s.memsegh)<<16|s.memsegl)<<4;
if(s.flags&1) q->flags |= SF_LOOP; if(s.flags&1) q->flags |= SF_LOOP;
if(s.flags&4) q->flags |= SF_16BITS; if(s.flags&4) q->flags |= SF_16BITS;
@ -406,7 +416,7 @@ static int S3M_Load(int curious)
for(t=0;t<of.numpat;t++) { for(t=0;t<of.numpat;t++) {
/* seek to pattern position (+2 skip pattern length) */ /* seek to pattern position (+2 skip pattern length) */
_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET); _mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
if(S3M_GetNumChannels()) return 0; if(!S3M_GetNumChannels()) return 0;
} }
/* build the remap array */ /* build the remap array */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_stm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
Screamtracker 2 (STM) module loader Screamtracker 2 (STM) module loader
@ -90,7 +90,7 @@ static STMNOTE *stmbuf = NULL;
static STMHEADER *mh = NULL; static STMHEADER *mh = NULL;
/* tracker identifiers */ /* tracker identifiers */
static CHAR* STM_Version[STM_NTRACKERS] = { static const CHAR * STM_Version[STM_NTRACKERS] = {
"Screamtracker 2", "Screamtracker 2",
"Converted by MOD2STM (STM format)", "Converted by MOD2STM (STM format)",
"Wuzamod (STM format)" "Wuzamod (STM format)"
@ -103,6 +103,7 @@ static int STM_Test(void)
UBYTE str[44]; UBYTE str[44];
int t; int t;
memset(str,0,44);
_mm_fseek(modreader,20,SEEK_SET); _mm_fseek(modreader,20,SEEK_SET);
_mm_read_UBYTES(str,44,modreader); _mm_read_UBYTES(str,44,modreader);
if(str[9]!=2) return 0; /* STM Module = filetype 2 */ if(str[9]!=2) return 0; /* STM Module = filetype 2 */
@ -130,6 +131,8 @@ static void STM_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
MikMod_free(stmbuf); MikMod_free(stmbuf);
mh=NULL;
stmbuf=NULL;
} }
static void STM_ConvertNote(STMNOTE *n) static void STM_ConvertNote(STMNOTE *n)
@ -224,8 +227,7 @@ static UBYTE *STM_ConvertTrack(STMNOTE *n)
static int STM_LoadPatterns(void) static int STM_LoadPatterns(void)
{ {
int t,tracks=0; unsigned int t,s,tracks=0;
unsigned int s;
if(!AllocPatterns()) return 0; if(!AllocPatterns()) return 0;
if(!AllocTracks()) return 0; if(!AllocTracks()) return 0;
@ -272,6 +274,10 @@ static int STM_Load(int curious)
mh->numpat =_mm_read_UBYTE(modreader); mh->numpat =_mm_read_UBYTE(modreader);
mh->globalvol =_mm_read_UBYTE(modreader); mh->globalvol =_mm_read_UBYTE(modreader);
_mm_read_UBYTES(mh->reserved,13,modreader); _mm_read_UBYTES(mh->reserved,13,modreader);
if(mh->numpat > 128) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
for(t=0;t<31;t++) { for(t=0;t<31;t++) {
STMSAMPLE *s=&mh->sample[t]; /* STM sample data */ STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
@ -299,9 +305,7 @@ static int STM_Load(int curious)
/* set module variables */ /* set module variables */
for(t=0;t<STM_NTRACKERS;t++) for(t=0;t<STM_NTRACKERS;t++)
if(!memcmp(mh->trackername,STM_Signatures[t],8)) break; if(!memcmp(mh->trackername,STM_Signatures[t],8)) break;
if(t == STM_NTRACKERS) of.modtype = MikMod_strdup(STM_Version[t]);
return 0;
of.modtype = StrDup(STM_Version[t]);
of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
of.numpat = mh->numpat; of.numpat = mh->numpat;
of.inittempo = 125; /* mh->inittempo+0x1c; */ of.inittempo = 125; /* mh->inittempo+0x1c; */
@ -316,7 +320,10 @@ static int STM_Load(int curious)
/* 99 terminates the patorder list */ /* 99 terminates the patorder list */
while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) { while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) {
of.positions[t]=mh->patorder[t]; of.positions[t]=mh->patorder[t];
t++; if(++t == 0x80) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
} }
if(mh->patorder[t]<=99) t++; if(mh->patorder[t]<=99) t++;
of.numpos=t; of.numpos=t;
@ -334,7 +341,7 @@ static int STM_Load(int curious)
q->speed = (mh->sample[t].c2spd * 8363) / 8448; q->speed = (mh->sample[t].c2spd * 8363) / 8448;
q->volume = mh->sample[t].volume; q->volume = mh->sample[t].volume;
q->length = mh->sample[t].length; q->length = mh->sample[t].length;
if (/*(!mh->sample[t].volume)||*/(q->length==1)) q->length=0; if (/*!mh->sample[t].volume || */q->length==1) q->length=0;
q->loopstart = mh->sample[t].loopbeg; q->loopstart = mh->sample[t].loopbeg;
q->loopend = mh->sample[t].loopend; q->loopend = mh->sample[t].loopend;
q->seekpos = MikMod_ISA; q->seekpos = MikMod_ISA;
@ -374,5 +381,4 @@ MIKMODAPI MLOADER load_stm={
STM_LoadTitle STM_LoadTitle
}; };
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_stx.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
STMIK 0.2 (STX) module loader STMIK 0.2 (STX) module loader
@ -114,6 +114,7 @@ static int STX_Test(void)
UBYTE id[8]; UBYTE id[8];
int t; int t;
memset(id,0,8);
_mm_fseek(modreader,0x3C,SEEK_SET); _mm_fseek(modreader,0x3C,SEEK_SET);
if(!_mm_read_UBYTES(id,4,modreader)) return 0; if(!_mm_read_UBYTES(id,4,modreader)) return 0;
if(memcmp(id,"SCRM",4)) return 0; if(memcmp(id,"SCRM",4)) return 0;
@ -143,6 +144,10 @@ static void STX_Cleanup(void)
MikMod_free(paraptr); MikMod_free(paraptr);
MikMod_free(poslookup); MikMod_free(poslookup);
MikMod_free(mh); MikMod_free(mh);
stxbuf=NULL;
paraptr=NULL;
poslookup=NULL;
mh=NULL;
} }
static int STX_ReadPattern(void) static int STX_ReadPattern(void)
@ -297,6 +302,11 @@ static int STX_Load(int curious)
_mm_errno = MMERR_LOADING_HEADER; _mm_errno = MMERR_LOADING_HEADER;
return 0; return 0;
} }
if(mh->ordnum > 256 || !mh->insnum || mh->insnum > 256 ||
mh->patnum > 254 || !mh->patnum) {
_mm_errno = MMERR_NOT_A_MODULE;
return 0;
}
/* set module variables */ /* set module variables */
of.songname = DupStr(mh->songname,20,1); of.songname = DupStr(mh->songname,20,1);
@ -323,10 +333,10 @@ static int STX_Load(int curious)
version=_mm_read_I_UWORD(modreader); version=_mm_read_I_UWORD(modreader);
if(version==mh->patsize) { if(version==mh->patsize) {
version = 0x10; version = 0x10;
of.modtype = StrDup("STMIK 0.2 (STM2STX 1.0)"); of.modtype = MikMod_strdup("STMIK 0.2 (STM2STX 1.0)");
} else { } else {
version = 0x11; version = 0x11;
of.modtype = StrDup("STMIK 0.2 (STM2STX 1.1)"); of.modtype = MikMod_strdup("STMIK 0.2 (STM2STX 1.1)");
} }
/* read the order data */ /* read the order data */
@ -389,7 +399,7 @@ static int STX_Load(int curious)
q->loopstart = s.loopbeg; q->loopstart = s.loopbeg;
q->loopend = s.loopend; q->loopend = s.loopend;
q->volume = s.volume; q->volume = s.volume;
q->seekpos = (((long)s.memsegh)<<16|s.memsegl)<<4; q->seekpos = (((ULONG)s.memsegh)<<16|s.memsegl)<<4;
q->flags |= SF_SIGNED; q->flags |= SF_SIGNED;
if(s.flags&1) q->flags |= SF_LOOP; if(s.flags&1) q->flags |= SF_LOOP;

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_ult.c,v 1.3 2010/01/12 03:30:32 realtech Exp $ $Id$
Ultratracker (ULT) module loader Ultratracker (ULT) module loader
@ -80,7 +80,7 @@ typedef struct ULTEVENT {
#define ULTS_REVERSE 16 #define ULTS_REVERSE 16
#define ULT_VERSION_LEN 18 #define ULT_VERSION_LEN 18
static CHAR ULT_Version[ULT_VERSION_LEN]="Ultra Tracker v1.x"; static CHAR ULT_Version[ULT_VERSION_LEN+1]="Ultra Tracker v1.x";
static ULTEVENT ev; static ULTEVENT ev;
@ -130,7 +130,7 @@ static int ULT_Load(int curious)
SAMPLE *q; SAMPLE *q;
ULTSAMPLE s; ULTSAMPLE s;
ULTHEADER mh; ULTHEADER mh;
UBYTE nos,noc,rbnop; UBYTE nos,noc,RBnop;
(void)curious; (void)curious;
/* try to read module header */ /* try to read module header */
@ -207,26 +207,34 @@ static int ULT_Load(int curious)
if(!AllocPositions(256)) return 0; if(!AllocPositions(256)) return 0;
for(t=0;t<256;t++) for(t=0;t<256;t++)
of.positions[t]=_mm_read_UBYTE(modreader); of.positions[t]=_mm_read_UBYTE(modreader);
for(t=0;t<256;t++)
noc=_mm_read_UBYTE(modreader);
RBnop=_mm_read_UBYTE(modreader);
of.numchn=++noc;
of.numpat=++RBnop;
of.numtrk=of.numchn*of.numpat;
for(t=0;t<256;t++) {
if(of.positions[t]==255) { if(of.positions[t]==255) {
of.positions[t]=LAST_PATTERN; of.positions[t]=LAST_PATTERN;
break; break;
} }
if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
}
of.numpos=t; of.numpos=t;
noc=_mm_read_UBYTE(modreader);
rbnop=_mm_read_UBYTE(modreader);
of.numchn=++noc;
of.numpat=++rbnop;
of.numtrk=of.numchn*of.numpat;
if(!AllocTracks()) return 0; if(!AllocTracks()) return 0;
if(!AllocPatterns()) return 0; if(!AllocPatterns()) return 0;
for(u=0;u<of.numchn;u++) for(u=0;u<of.numchn;u++)
for(t=0;t<of.numpat;t++) for(t=0;t<of.numpat;t++)
of.patterns[(t*of.numchn)+u]=tracks++; of.patterns[(t*of.numchn)+u]=tracks++;
// SA37775 /* Secunia SA37775 / CVE-2009-3996 */
if (of.numchn>=UF_MAXCHAN) if (of.numchn>=UF_MAXCHAN)
of.numchn=UF_MAXCHAN - 1; of.numchn=UF_MAXCHAN - 1;
@ -313,7 +321,7 @@ static int ULT_Load(int curious)
return 1; return 1;
} }
static CHAR *ULT_LoadTitle(void) static CHAR * ULT_LoadTitle(void)
{ {
CHAR s[32]; CHAR s[32];

View file

@ -0,0 +1,476 @@
/* MikMod sound library
* (c) 2003-2004 Raphael Assenat 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.
*/
/* Epic Games Unreal UMX container loading for libmikmod
* Written by O. Sezer <sezero@users.sourceforge.net>
*
* Records data type/offset info in its Test() function, then acts
* as a middle-man, forwarding calls to the real loader units. It
* requires that the MREADER implementation in use always respects
* its iobase fields. Like all other libmikmod loaders, this code
* is not reentrant yet.
*
* UPKG parsing partially based on Unreal Media Ripper (UMR) v0.3
* by Andy Ward <wardwh@swbell.net>, with additional updates
* by O. Sezer - see git repo at https://github.com/sezero/umr/
*
* The cheaper way, i.e. linear search of music object like libxmp
* and libmodplug does, is possible. With this however we're using
* the embedded offset, size and object type directly from the umx
* file, and I feel safer with it.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "mikmod_internals.h"
/*========== upkg defs */
typedef SLONG fci_t; /* FCompactIndex */
#define UPKG_HDR_TAG 0x9e2a83c1
struct _genhist { /* for upkg versions >= 68 */
SLONG export_count;
SLONG name_count;
};
struct upkg_hdr {
ULONG tag; /* UPKG_HDR_TAG */
SLONG file_version;
ULONG pkg_flags;
SLONG name_count; /* number of names in name table (>= 0) */
SLONG name_offset; /* offset to name table (>= 0) */
SLONG export_count; /* num. exports in export table (>= 0) */
SLONG export_offset; /* offset to export table (>= 0) */
SLONG import_count; /* num. imports in export table (>= 0) */
SLONG import_offset; /* offset to import table (>= 0) */
/* number of GUIDs in heritage table (>= 1) and table's offset:
* only with versions < 68. */
SLONG heritage_count;
SLONG heritage_offset;
/* with versions >= 68: a GUID, a dword for generation count
* and export_count and name_count dwords for each generation: */
ULONG guid[4];
SLONG generation_count;
#define UPKG_HDR_SIZE 64 /* 64 bytes up until here */
/*struct _genhist *gen;*/
};
/* compile time assert for upkg_hdr size */
/*typedef int _check_hdrsize[2 * (offsetof(struct upkg_hdr, gen) == UPKG_HDR_SIZE) - 1];*/
typedef int _check_hdrsize[2 * (sizeof(struct upkg_hdr) == UPKG_HDR_SIZE) - 1];
/*========== Supported content types */
#define UMUSIC_IT 0
#define UMUSIC_S3M 1
#define UMUSIC_XM 2
#define UMUSIC_MOD 3
static const char *mustype[] = {
"IT", "S3M", "XM", "MOD",
NULL
};
/*========== UPKG parsing */
/* decode an FCompactIndex.
* original documentation by Tim Sweeney was at
* http://unreal.epicgames.com/Packages.htm
* also see Unreal Wiki:
* http://wiki.beyondunreal.com/Legacy:Package_File_Format/Data_Details
*/
static fci_t get_fci (const char *in, int *pos)
{
SLONG a;
int size;
size = 1;
a = in[0] & 0x3f;
if (in[0] & 0x40) {
size++;
a |= (in[1] & 0x7f) << 6;
if (in[1] & 0x80) {
size++;
a |= (in[2] & 0x7f) << 13;
if (in[2] & 0x80) {
size++;
a |= (in[3] & 0x7f) << 20;
if (in[3] & 0x80) {
size++;
a |= (in[4] & 0x3f) << 27;
}
}
}
}
if (in[0] & 0x80)
a = -a;
*pos += size;
return a;
}
static int get_objtype (SLONG ofs, int type)
{
char sig[16];
_retry:
_mm_fseek(modreader, ofs, SEEK_SET);
_mm_read_UBYTES(sig, 16, modreader);
if (type == UMUSIC_IT) {
if (memcmp(sig, "IMPM", 4) == 0)
return UMUSIC_IT;
return -1;
}
if (type == UMUSIC_XM) {
if (memcmp(sig, "Extended Module:", 16) != 0)
return -1;
_mm_read_UBYTES(sig, 16, modreader);
if (sig[0] != ' ') return -1;
_mm_read_UBYTES(sig, 16, modreader);
if (sig[5] != 0x1a) return -1;
return UMUSIC_XM;
}
_mm_fseek(modreader, ofs + 44, SEEK_SET);
_mm_read_UBYTES(sig, 4, modreader);
if (type == UMUSIC_S3M) {
if (memcmp(sig, "SCRM", 4) == 0)
return UMUSIC_S3M;
/*return -1;*/
/* SpaceMarines.umx and Starseek.umx from Return to NaPali
* report as "s3m" whereas the actual music format is "it" */
type = UMUSIC_IT;
goto _retry;
}
_mm_fseek(modreader, ofs + 1080, SEEK_SET);
_mm_read_UBYTES(sig, 4, modreader);
if (type == UMUSIC_MOD) {
if (memcmp(sig, "M.K.", 4) == 0 || memcmp(sig, "M!K!", 4) == 0)
return UMUSIC_MOD;
return -1;
}
return -1;
}
static int read_export (const struct upkg_hdr *hdr,
SLONG *ofs, SLONG *objsize)
{
char buf[40];
int idx = 0, t;
_mm_fseek(modreader, *ofs, SEEK_SET);
if (!_mm_read_UBYTES(buf, 40, modreader))
return -1;
if (hdr->file_version < 40) idx += 8; /* 00 00 00 00 00 00 00 00 */
if (hdr->file_version < 60) idx += 16; /* 81 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 00 */
get_fci(&buf[idx], &idx); /* skip junk */
t = get_fci(&buf[idx], &idx); /* type_name */
if (hdr->file_version > 61) idx += 4; /* skip export size */
*objsize = get_fci(&buf[idx], &idx);
*ofs += idx; /* offset for real data */
return t; /* return type_name index */
}
static int read_typname(const struct upkg_hdr *hdr,
int idx, char *out)
{
int i, s;
long l;
char buf[64];
if (idx >= hdr->name_count) return -1;
buf[63] = '\0';
for (i = 0, l = 0; i <= idx; i++) {
_mm_fseek(modreader, hdr->name_offset + l, SEEK_SET);
_mm_read_UBYTES(buf, 63, modreader);
if (hdr->file_version >= 64) {
s = *(signed char *)buf; /* numchars *including* terminator */
if (s <= 0 || s > 64) return -1;
l += s + 5; /* 1 for buf[0], 4 for int32_t name_flags */
} else {
l += (long)strlen(buf);
l += 5; /* 1 for terminator, 4 for int32_t name_flags */
}
}
strcpy(out, (hdr->file_version >= 64)? &buf[1] : buf);
return 0;
}
static int probe_umx (const struct upkg_hdr *hdr,
SLONG *ofs, SLONG *objsize)
{
int i, idx, t;
SLONG s, pos;
long fsiz;
char buf[64];
idx = 0;
_mm_fseek(modreader, 0, SEEK_END);
fsiz = _mm_ftell(modreader);
/* Find the offset and size of the first IT, S3M or XM
* by parsing the exports table. The umx files should
* have only one export. Kran32.umx from Unreal has two,
* but both pointing to the same music. */
if (hdr->export_offset >= fsiz) return -1;
memset(buf, 0, 64);
_mm_fseek(modreader, hdr->export_offset, SEEK_SET);
_mm_read_UBYTES(buf, 64, modreader);
get_fci(&buf[idx], &idx); /* skip class_index */
get_fci(&buf[idx], &idx); /* skip super_index */
if (hdr->file_version >= 60) idx += 4; /* skip int32 package_index */
get_fci(&buf[idx], &idx); /* skip object_name */
idx += 4; /* skip int32 object_flags */
s = get_fci(&buf[idx], &idx); /* get serial_size */
if (s <= 0) return -1;
pos = get_fci(&buf[idx],&idx); /* get serial_offset */
if (pos < 0 || pos > fsiz - 40) return -1;
if ((t = read_export(hdr, &pos, &s)) < 0) return -1;
if (s <= 0 || s > fsiz - pos) return -1;
if (read_typname(hdr, t, buf) < 0) return -1;
for (i = 0; mustype[i] != NULL; i++) {
if (!strcasecmp(buf, mustype[i])) {
t = i;
break;
}
}
if (mustype[i] == NULL) return -1;
if ((t = get_objtype(pos, t)) < 0) return -1;
*ofs = pos;
*objsize = s;
return t;
}
static SLONG probe_header (void *header)
{
struct upkg_hdr *hdr;
unsigned char *p;
ULONG *swp;
int i;
/* byte swap the header - all members are 32 bit LE values */
p = (unsigned char *) header;
swp = (ULONG *) header;
for (i = 0; i < UPKG_HDR_SIZE/4; i++, p += 4) {
swp[i] = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
hdr = (struct upkg_hdr *) header;
if (hdr->tag != UPKG_HDR_TAG) {
return -1;
}
if (hdr->name_count < 0 ||
hdr->name_offset < 0 ||
hdr->export_count < 0 ||
hdr->export_offset < 0 ||
hdr->import_count < 0 ||
hdr->import_offset < 0 ) {
return -1;
}
switch (hdr->file_version) {
case 35: case 37: /* Unreal beta - */
case 40: case 41: /* 1998 */
case 61:/* Unreal */
case 62:/* Unreal Tournament */
case 63:/* Return to NaPali */
case 64:/* Unreal Tournament */
case 66:/* Unreal Tournament */
case 68:/* Unreal Tournament */
case 69:/* Tactical Ops */
case 83:/* Mobile Forces */
return 0;
}
return -1;
}
static int process_upkg (SLONG *ofs, SLONG *objsize)
{
char header[UPKG_HDR_SIZE];
if (!_mm_read_UBYTES(header, UPKG_HDR_SIZE, modreader))
return -1;
if (probe_header(header) < 0)
return -1;
return probe_umx((struct upkg_hdr *)header, ofs, objsize);
}
/*========== Loader vars */
typedef struct _umx_info {
int type;
SLONG ofs, size;
MLOADER* loader;
} umx_info;
static umx_info *umx_data = NULL;
/*========== Loader code */
/* Without Test() being called first, Load[Title] is never called.
* A Test() is always followed by either a Load() or a LoadTitle().
* A Load() is always followed by Cleanup() regardless of success.
*
* Therefore, in between Test() and LoadTitle() or Load()/Cleanup(),
* we must remember the type and the offset of the umx music data,
* and always clear it when returning from LoadTitle() or Cleanup().
*/
static int UMX_Test(void)
{
int type;
SLONG ofs = 0, size = 0;
if (umx_data) {
#ifdef MIKMOD_DEBUG
fprintf(stderr, "UMX_Test called while a previous instance is active\n");
#endif
MikMod_free(umx_data);
umx_data = NULL;
}
_mm_fseek(modreader, 0, SEEK_SET);
type = process_upkg(&ofs, &size);
if (type < 0 || type > UMUSIC_MOD)
return 0;
umx_data = (umx_info*) MikMod_calloc(1, sizeof(umx_info));
if (!umx_data) return 0;
umx_data->type = type;
umx_data->ofs = ofs;
umx_data->size = size;
switch (type) {
case UMUSIC_IT:
umx_data->loader = &load_it;
break;
case UMUSIC_S3M:
umx_data->loader = &load_s3m;
break;
case UMUSIC_XM:
umx_data->loader = &load_xm;
break;
case UMUSIC_MOD:
umx_data->loader = &load_mod;
break;
}
return 1;
}
static int UMX_Init(void)
{
if (!umx_data || !umx_data->loader)
return 0;
if (umx_data->loader->Init)
return umx_data->loader->Init();
return 1;
}
static void UMX_Cleanup(void)
{
if (!umx_data) return;
if (umx_data->loader && umx_data->loader->Cleanup)
umx_data->loader->Cleanup();
MikMod_free(umx_data);
umx_data = NULL;
}
static int UMX_Load(int curious)
{
if (!umx_data || !umx_data->loader)
return 0;
_mm_fseek(modreader, umx_data->ofs, SEEK_SET);
/* set reader iobase to the umx object offset */
_mm_iobase_revert(modreader);
_mm_iobase_setcur(modreader);
return umx_data->loader->Load(curious);
}
static CHAR *UMX_LoadTitle(void)
{
CHAR *title;
if (!umx_data) return NULL;
if (!umx_data->loader) {
title = NULL;
}
else {
_mm_fseek(modreader, umx_data->ofs, SEEK_SET);
/* set reader iobase to the umx object offset */
_mm_iobase_revert(modreader);
_mm_iobase_setcur(modreader);
title = umx_data->loader->LoadTitle();
}
MikMod_free(umx_data);
umx_data = NULL;
return title;
}
/*========== Loader information */
MIKMODAPI MLOADER load_umx = {
NULL,
"UMX",
"UMX (Unreal UMX container)",
UMX_Init,
UMX_Test,
UMX_Load,
UMX_Cleanup,
UMX_LoadTitle
};
/* ex:set ts=8: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_uni.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ $Id$
UNIMOD (libmikmod's and APlayer's internal module format) loader UNIMOD (libmikmod's and APlayer's internal module format) loader
@ -94,18 +94,18 @@ static UNISMP05 *wh=NULL,*s=NULL;
/*========== Loader code */ /*========== Loader code */
static char* readstring(void) static char * readstring(void)
{ {
char *s=NULL; char *str=NULL;
UWORD len; UWORD len;
len=_mm_read_I_UWORD(modreader); len=_mm_read_I_UWORD(modreader);
if(len) { if(len) {
s=MikMod_malloc(len+1); str=(char *) MikMod_malloc(len+1);
_mm_read_UBYTES(s,len,modreader); _mm_read_UBYTES(str,len,modreader);
s[len]=0; str[len]=0;
} }
return s; return str;
} }
static int UNI_Test(void) static int UNI_Test(void)
@ -133,7 +133,7 @@ static int UNI_Init(void)
static void UNI_Cleanup(void) static void UNI_Cleanup(void)
{ {
MikMod_free(wh); MikMod_free(wh);
s=NULL; wh = s = NULL;
} }
static UBYTE* readtrack(void) static UBYTE* readtrack(void)
@ -148,7 +148,7 @@ static UBYTE* readtrack(void)
len=_mm_read_I_UWORD(modreader); len=_mm_read_I_UWORD(modreader);
if(!len) return NULL; if(!len) return NULL;
if(!(t=MikMod_malloc(len))) return NULL; if(!(t=(UBYTE*)MikMod_malloc(len))) return NULL;
_mm_read_UBYTES(t,len,modreader); _mm_read_UBYTES(t,len,modreader);
/* Check if the track is correct */ /* Check if the track is correct */
@ -221,65 +221,65 @@ static UBYTE* readtrack(void)
static int loadsmp6(void) static int loadsmp6(void)
{ {
int t; int t;
SAMPLE *s; SAMPLE *sptr;
s=of.samples; sptr=of.samples;
for(t=0;t<of.numsmp;t++,s++) { for(t=0;t<of.numsmp;t++,sptr++) {
int flags; int flags;
flags = _mm_read_M_UWORD(modreader); flags = _mm_read_M_UWORD(modreader);
s->flags=0; sptr->flags=0;
if(flags&0x0004) s->flags|=SF_STEREO; if(flags&0x0004) sptr->flags|=SF_STEREO;
if(flags&0x0002) s->flags|=SF_SIGNED; if(flags&0x0002) sptr->flags|=SF_SIGNED;
if(flags&0x0001) s->flags|=SF_16BITS; if(flags&0x0001) sptr->flags|=SF_16BITS;
/* convert flags */ /* convert flags */
if(universion>=0x104) { if(universion>=0x104) {
if(flags&0x2000) s->flags|=SF_UST_LOOP; if(flags&0x2000) sptr->flags|=SF_UST_LOOP;
if(flags&0x1000) s->flags|=SF_OWNPAN; if(flags&0x1000) sptr->flags|=SF_OWNPAN;
if(flags&0x0800) s->flags|=SF_SUSTAIN; if(flags&0x0800) sptr->flags|=SF_SUSTAIN;
if(flags&0x0400) s->flags|=SF_REVERSE; if(flags&0x0400) sptr->flags|=SF_REVERSE;
if(flags&0x0200) s->flags|=SF_BIDI; if(flags&0x0200) sptr->flags|=SF_BIDI;
if(flags&0x0100) s->flags|=SF_LOOP; if(flags&0x0100) sptr->flags|=SF_LOOP;
if(flags&0x0020) s->flags|=SF_ITPACKED; if(flags&0x0020) sptr->flags|=SF_ITPACKED;
if(flags&0x0010) s->flags|=SF_DELTA; if(flags&0x0010) sptr->flags|=SF_DELTA;
if(flags&0x0008) s->flags|=SF_BIG_ENDIAN; if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN;
} else if(universion>=0x102) { } else if(universion>=0x102) {
if(flags&0x0800) s->flags|=SF_UST_LOOP; if(flags&0x0800) sptr->flags|=SF_UST_LOOP;
if(flags&0x0400) s->flags|=SF_OWNPAN; if(flags&0x0400) sptr->flags|=SF_OWNPAN;
if(flags&0x0200) s->flags|=SF_SUSTAIN; if(flags&0x0200) sptr->flags|=SF_SUSTAIN;
if(flags&0x0100) s->flags|=SF_REVERSE; if(flags&0x0100) sptr->flags|=SF_REVERSE;
if(flags&0x0080) s->flags|=SF_BIDI; if(flags&0x0080) sptr->flags|=SF_BIDI;
if(flags&0x0040) s->flags|=SF_LOOP; if(flags&0x0040) sptr->flags|=SF_LOOP;
if(flags&0x0020) s->flags|=SF_ITPACKED; if(flags&0x0020) sptr->flags|=SF_ITPACKED;
if(flags&0x0010) s->flags|=SF_DELTA; if(flags&0x0010) sptr->flags|=SF_DELTA;
if(flags&0x0008) s->flags|=SF_BIG_ENDIAN; if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN;
} else { } else {
if(flags&0x400) s->flags|=SF_UST_LOOP; if(flags&0x400) sptr->flags|=SF_UST_LOOP;
if(flags&0x200) s->flags|=SF_OWNPAN; if(flags&0x200) sptr->flags|=SF_OWNPAN;
if(flags&0x100) s->flags|=SF_REVERSE; if(flags&0x100) sptr->flags|=SF_REVERSE;
if(flags&0x080) s->flags|=SF_SUSTAIN; if(flags&0x080) sptr->flags|=SF_SUSTAIN;
if(flags&0x040) s->flags|=SF_BIDI; if(flags&0x040) sptr->flags|=SF_BIDI;
if(flags&0x020) s->flags|=SF_LOOP; if(flags&0x020) sptr->flags|=SF_LOOP;
if(flags&0x010) s->flags|=SF_BIG_ENDIAN; if(flags&0x010) sptr->flags|=SF_BIG_ENDIAN;
if(flags&0x008) s->flags|=SF_DELTA; if(flags&0x008) sptr->flags|=SF_DELTA;
} }
s->speed = _mm_read_M_ULONG(modreader); sptr->speed = _mm_read_M_ULONG(modreader);
s->volume = _mm_read_UBYTE(modreader); sptr->volume = _mm_read_UBYTE(modreader);
s->panning = _mm_read_M_UWORD(modreader); sptr->panning = _mm_read_M_UWORD(modreader);
s->length = _mm_read_M_ULONG(modreader); sptr->length = _mm_read_M_ULONG(modreader);
s->loopstart = _mm_read_M_ULONG(modreader); sptr->loopstart = _mm_read_M_ULONG(modreader);
s->loopend = _mm_read_M_ULONG(modreader); sptr->loopend = _mm_read_M_ULONG(modreader);
s->susbegin = _mm_read_M_ULONG(modreader); sptr->susbegin = _mm_read_M_ULONG(modreader);
s->susend = _mm_read_M_ULONG(modreader); sptr->susend = _mm_read_M_ULONG(modreader);
s->globvol = _mm_read_UBYTE(modreader); sptr->globvol = _mm_read_UBYTE(modreader);
s->vibflags = _mm_read_UBYTE(modreader); sptr->vibflags = _mm_read_UBYTE(modreader);
s->vibtype = _mm_read_UBYTE(modreader); sptr->vibtype = _mm_read_UBYTE(modreader);
s->vibsweep = _mm_read_UBYTE(modreader); sptr->vibsweep = _mm_read_UBYTE(modreader);
s->vibdepth = _mm_read_UBYTE(modreader); sptr->vibdepth = _mm_read_UBYTE(modreader);
s->vibrate = _mm_read_UBYTE(modreader); sptr->vibrate = _mm_read_UBYTE(modreader);
s->samplename=readstring(); sptr->samplename=readstring();
if(_mm_eof(modreader)) { if(_mm_eof(modreader)) {
_mm_errno = MMERR_LOADING_SAMPLEINFO; _mm_errno = MMERR_LOADING_SAMPLEINFO;
@ -308,7 +308,7 @@ static int loadinstr6(void)
i->rpanvar = _mm_read_UBYTE(modreader); i->rpanvar = _mm_read_UBYTE(modreader);
i->volfade = _mm_read_M_UWORD(modreader); i->volfade = _mm_read_M_UWORD(modreader);
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define UNI_LoadEnvelope6(name) \ #define UNI_LoadEnvelope6(name) \
i-> name##flg=_mm_read_UBYTE(modreader); \ i-> name##flg=_mm_read_UBYTE(modreader); \
i-> name##pts=_mm_read_UBYTE(modreader); \ i-> name##pts=_mm_read_UBYTE(modreader); \
@ -373,7 +373,7 @@ static int loadinstr5(void)
for(u=0;u<96;u++) for(u=0;u<96;u++)
i->samplenumber[u]=of.numsmp+_mm_read_UBYTE(modreader); i->samplenumber[u]=of.numsmp+_mm_read_UBYTE(modreader);
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define UNI_LoadEnvelope5(name) \ #define UNI_LoadEnvelope5(name) \
i-> name##flg=_mm_read_UBYTE(modreader); \ i-> name##flg=_mm_read_UBYTE(modreader); \
i-> name##pts=_mm_read_UBYTE(modreader); \ i-> name##pts=_mm_read_UBYTE(modreader); \
@ -415,7 +415,7 @@ static int loadinstr5(void)
/* Allocate more room for sample information if necessary */ /* Allocate more room for sample information if necessary */
if(of.numsmp+u==wavcnt) { if(of.numsmp+u==wavcnt) {
wavcnt+=UNI_SMPINCR; wavcnt+=UNI_SMPINCR;
if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(UNISMP05)))) { if(!(wh=(UNISMP05*)MikMod_realloc(wh,wavcnt*sizeof(UNISMP05)))) {
_mm_errno=MMERR_OUT_OF_MEMORY; _mm_errno=MMERR_OUT_OF_MEMORY;
return 0; return 0;
} }
@ -447,7 +447,7 @@ static int loadinstr5(void)
/* sanity check */ /* sanity check */
if(!of.numsmp) { if(!of.numsmp) {
if(wh) { MikMod_free(wh);wh=NULL; } MikMod_free(wh);wh=NULL;
_mm_errno=MMERR_LOADING_SAMPLEINFO; _mm_errno=MMERR_LOADING_SAMPLEINFO;
return 0; return 0;
} }
@ -514,11 +514,11 @@ static int UNI_Load(int curious)
universion=0x100; universion=0x100;
if(universion>=6) { if(universion>=6) {
if (universion==6) if (universion==6) {
(void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);
else } else {
universion=_mm_read_M_UWORD(modreader); universion=_mm_read_M_UWORD(modreader);
}
mh.flags =_mm_read_M_UWORD(modreader); mh.flags =_mm_read_M_UWORD(modreader);
mh.numchn =_mm_read_UBYTE(modreader); mh.numchn =_mm_read_UBYTE(modreader);
mh.numvoices =_mm_read_UBYTE(modreader); mh.numvoices =_mm_read_UBYTE(modreader);
@ -578,21 +578,21 @@ static int UNI_Load(int curious)
oldtype=readstring(); oldtype=readstring();
if(oldtype) { if(oldtype) {
size_t len=strlen(oldtype)+20; size_t len=strlen(oldtype)+20;
if(!(modtype=MikMod_malloc(len))) return 0; if(!(modtype=(char*)MikMod_malloc(len))) return 0;
#ifdef HAVE_SNPRINTF #ifdef HAVE_SNPRINTF
snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
#else #else
sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
#endif #endif
} else { } else {
if(!(modtype=MikMod_malloc(10))) return 0; if(!(modtype=(char*)MikMod_malloc(10))) return 0;
#ifdef HAVE_SNPRINTF #ifdef HAVE_SNPRINTF
snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
#else #else
sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
#endif #endif
} }
of.modtype=StrDup(modtype); of.modtype=MikMod_strdup(modtype);
MikMod_free(modtype);MikMod_free(oldtype); MikMod_free(modtype);MikMod_free(oldtype);
of.comment=readstring(); of.comment=readstring();
@ -624,9 +624,14 @@ static int UNI_Load(int curious)
for(t=0;t<of.numchn;t++) of.panning[t]=mh.panning[t]; for(t=0;t<of.numchn;t++) of.panning[t]=mh.panning[t];
} }
/* convert the ``end of song'' pattern code if necessary */ /* convert the ``end of song'' pattern code if necessary */
if(universion<0x106) for(t=0;t<of.numpos;t++) {
for(t=0;t<of.numpos;t++) if(universion<0x106 && of.positions[t]==255) of.positions[t]=LAST_PATTERN;
if(of.positions[t]==255) of.positions[t]=LAST_PATTERN; else if (of.positions[t]>of.numpat) { /* SANITIY CHECK */
/* fprintf(stderr,"position[%d]=%d > numpat=%d\n",t,of.positions[t],of.numpat);*/
_mm_errno = MMERR_LOADING_HEADER;
return 0;
}
}
/* instruments and samples */ /* instruments and samples */
if(universion>=6) { if(universion>=6) {
@ -642,7 +647,7 @@ static int UNI_Load(int curious)
if(!AllocInstruments()) return 0; if(!AllocInstruments()) return 0;
if(!loadinstr5()) return 0; if(!loadinstr5()) return 0;
if(!AllocSamples()) { if(!AllocSamples()) {
if(wh) { MikMod_free(wh);wh=NULL; } MikMod_free(wh);wh=NULL;
return 0; return 0;
} }
if(!loadsmp5()) return 0; if(!loadsmp5()) return 0;

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: load_xm.c,v 1.5 2008/02/29 18:49:03 denis111 Exp $ $Id$
Fasttracker (XM) module loader Fasttracker (XM) module loader
@ -129,7 +129,7 @@ typedef struct XMNOTE {
static XMNOTE *xmpat=NULL; static XMNOTE *xmpat=NULL;
static XMHEADER *mh=NULL; static XMHEADER *mh=NULL;
/* increment unit for sample array MikMod_reallocation */ /* increment unit for sample array reallocation */
#define XM_SMPINCR 64 #define XM_SMPINCR 64
static ULONG *nextwav=NULL; static ULONG *nextwav=NULL;
static XMWAVHEADER *wh=NULL,*s=NULL; static XMWAVHEADER *wh=NULL,*s=NULL;
@ -155,6 +155,7 @@ static int XM_Init(void)
static void XM_Cleanup(void) static void XM_Cleanup(void)
{ {
MikMod_free(mh); MikMod_free(mh);
mh=NULL;
} }
static int XM_ReadNote(XMNOTE* n) static int XM_ReadNote(XMNOTE* n)
@ -443,11 +444,17 @@ static void FixEnvelope(ENVPT *cur, int pts)
static int LoadInstruments(void) static int LoadInstruments(void)
{ {
int t,u, ck; long filend,ck;
int t,u;
INSTRUMENT *d; INSTRUMENT *d;
ULONG next=0; ULONG next=0;
UWORD wavcnt=0; UWORD wavcnt=0;
ck = _mm_ftell(modreader);
_mm_fseek(modreader,0,SEEK_END);
filend = _mm_ftell(modreader);
_mm_fseek(modreader,ck,SEEK_SET);
if(!AllocInstruments()) return 0; if(!AllocInstruments()) return 0;
d=of.instruments; d=of.instruments;
for(t=0;t<of.numins;t++,d++) { for(t=0;t<of.numins;t++,d++) {
@ -461,12 +468,9 @@ static int LoadInstruments(void)
ih.size = _mm_read_I_ULONG(modreader); ih.size = _mm_read_I_ULONG(modreader);
headend += ih.size; headend += ih.size;
ck = _mm_ftell(modreader); ck = _mm_ftell(modreader);
_mm_fseek(modreader,0,SEEK_END); if ((headend<0) || (filend<headend) || (headend<ck)) {
if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
_mm_fseek(modreader,ck,SEEK_SET);
break; break;
} }
_mm_fseek(modreader,ck,SEEK_SET);
_mm_read_string(ih.name, 22, modreader); _mm_read_string(ih.name, 22, modreader);
ih.type = _mm_read_UBYTE(modreader); ih.type = _mm_read_UBYTE(modreader);
ih.numsmp = _mm_read_I_UWORD(modreader); ih.numsmp = _mm_read_I_UWORD(modreader);
@ -500,7 +504,11 @@ static int LoadInstruments(void)
/* read the remainder of the header /* read the remainder of the header
(2 bytes for 1.03, 22 for 1.04) */ (2 bytes for 1.03, 22 for 1.04) */
if (headend>=_mm_ftell(modreader)) for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader); if (headend>=_mm_ftell(modreader)) {
for(u=headend-_mm_ftell(modreader);u;u--) {
_mm_skip_BYTE(modreader);
}
}
/* we can't trust the envelope point count here, as some /* we can't trust the envelope point count here, as some
modules have incorrect values (K_OSPACE.XM reports 32 volume modules have incorrect values (K_OSPACE.XM reports 32 volume
@ -509,8 +517,8 @@ static int LoadInstruments(void)
if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2; if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) { if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
if(nextwav) { MikMod_free(nextwav);nextwav=NULL; } MikMod_free(nextwav);nextwav=NULL;
if(wh) { MikMod_free(wh);wh=NULL; } MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO; _mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0; return 0;
} }
@ -519,7 +527,7 @@ static int LoadInstruments(void)
d->samplenumber[u]=pth.what[u]+of.numsmp; d->samplenumber[u]=pth.what[u]+of.numsmp;
d->volfade = pth.volfade; d->volfade = pth.volfade;
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define XM_ProcessEnvelope(name) \ #define XM_ProcessEnvelope(name) \
for (u = 0; u < (XMENVCNT >> 1); u++) { \ for (u = 0; u < (XMENVCNT >> 1); u++) { \
d-> name##env[u].pos = pth. name##env[u << 1]; \ d-> name##env[u].pos = pth. name##env[u << 1]; \
@ -577,15 +585,23 @@ static int LoadInstruments(void)
everything over */ everything over */
if(mh->version>0x0103) next = 0; if(mh->version>0x0103) next = 0;
for(u=0;u<ih.numsmp;u++,s++) { for(u=0;u<ih.numsmp;u++,s++) {
/* XM sample header is 40 bytes: make sure we won't hit EOF */
/* Note: last instrument is at the end of file in version 0x0104 */
if(_mm_ftell(modreader)+40>filend) {
MikMod_free(nextwav);MikMod_free(wh);
nextwav=NULL;wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
}
/* Allocate more room for sample information if necessary */ /* Allocate more room for sample information if necessary */
if(of.numsmp+u==wavcnt) { if(of.numsmp+u==wavcnt) {
wavcnt+=XM_SMPINCR; wavcnt+=XM_SMPINCR;
if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){ if(!(nextwav=(ULONG*)MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){
if(wh) { MikMod_free(wh);wh=NULL; } MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_OUT_OF_MEMORY; _mm_errno = MMERR_OUT_OF_MEMORY;
return 0; return 0;
} }
if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) { if(!(wh=(XMWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
MikMod_free(nextwav);nextwav=NULL; MikMod_free(nextwav);nextwav=NULL;
_mm_errno = MMERR_OUT_OF_MEMORY; _mm_errno = MMERR_OUT_OF_MEMORY;
return 0; return 0;
@ -610,13 +626,6 @@ static int LoadInstruments(void)
nextwav[of.numsmp+u]=next; nextwav[of.numsmp+u]=next;
next+=s->length; next+=s->length;
if(_mm_eof(modreader)) {
MikMod_free(nextwav);MikMod_free(wh);
nextwav=NULL;wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0;
}
} }
if(mh->version>0x0103) { if(mh->version>0x0103) {
@ -628,15 +637,15 @@ static int LoadInstruments(void)
} else { } else {
/* read the remainder of the header */ /* read the remainder of the header */
ck = _mm_ftell(modreader); ck = _mm_ftell(modreader);
_mm_fseek(modreader,0,SEEK_END); if ((headend<0) || (filend<headend) || (headend<ck)) {
if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
_mm_fseek(modreader,ck,SEEK_SET);
break; break;
} }
_mm_fseek(modreader,ck,SEEK_SET); for(u=headend-_mm_ftell(modreader);u;u--) {
for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader); _mm_skip_BYTE(modreader);
}
if(_mm_eof(modreader)) { /* last instrument is at the end of file in version 0x0104 */
if(_mm_eof(modreader) && (mh->version<0x0104 || t<of.numins-1)) {
MikMod_free(nextwav);MikMod_free(wh); MikMod_free(nextwav);MikMod_free(wh);
nextwav=NULL;wh=NULL; nextwav=NULL;wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO; _mm_errno = MMERR_LOADING_SAMPLEINFO;
@ -648,8 +657,8 @@ static int LoadInstruments(void)
/* sanity check */ /* sanity check */
if(!of.numsmp) { if(!of.numsmp) {
if(nextwav) { MikMod_free(nextwav);nextwav=NULL; } MikMod_free(nextwav);nextwav=NULL;
if(wh) { MikMod_free(wh);wh=NULL; } MikMod_free(wh);wh=NULL;
_mm_errno = MMERR_LOADING_SAMPLEINFO; _mm_errno = MMERR_LOADING_SAMPLEINFO;
return 0; return 0;
} }
@ -671,10 +680,8 @@ static int XM_Load(int curious)
_mm_read_string(mh->songname,21,modreader); _mm_read_string(mh->songname,21,modreader);
_mm_read_string(mh->trackername,20,modreader); _mm_read_string(mh->trackername,20,modreader);
mh->version =_mm_read_I_UWORD(modreader); mh->version =_mm_read_I_UWORD(modreader);
if((mh->version<0x102)||(mh->version>0x104)) { if(mh->version < 0x102 || mh->version > 0x104)
_mm_errno=MMERR_NOT_A_MODULE; goto bad_xm;
return 0;
}
mh->headersize =_mm_read_I_ULONG(modreader); mh->headersize =_mm_read_I_ULONG(modreader);
mh->songlength =_mm_read_I_UWORD(modreader); mh->songlength =_mm_read_I_UWORD(modreader);
mh->restart =_mm_read_I_UWORD(modreader); mh->restart =_mm_read_I_UWORD(modreader);
@ -684,22 +691,24 @@ static int XM_Load(int curious)
mh->flags =_mm_read_I_UWORD(modreader); mh->flags =_mm_read_I_UWORD(modreader);
mh->tempo =_mm_read_I_UWORD(modreader); mh->tempo =_mm_read_I_UWORD(modreader);
mh->bpm =_mm_read_I_UWORD(modreader); mh->bpm =_mm_read_I_UWORD(modreader);
if(!mh->bpm) { if(mh->numchn > 64) goto bad_xm;
_mm_errno=MMERR_NOT_A_MODULE; if(mh->tempo > 32 || mh->bpm < 32 || mh->bpm > 255)
return 0; goto bad_xm;
} if(mh->songlength > 256 || mh->headersize < 20 || mh->headersize > 20+256)
_mm_read_UBYTES(mh->orders,mh->headersize-20,modreader); goto bad_xm;
if(mh->numpat > 256 || mh->numins > 255 || mh->restart > 255)
if(_mm_eof(modreader)) { goto bad_xm;
_mm_errno = MMERR_LOADING_HEADER; /* _mm_read_UBYTES(mh->orders,256,modreader);*/
return 0; /* _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);*/
} _mm_read_UBYTES(mh->orders,mh->songlength,modreader);
if(_mm_fseek(modreader, mh->headersize+60, SEEK_SET) || _mm_eof(modreader))
goto bad_hdr;
/* set module variables */ /* set module variables */
of.initspeed = mh->tempo; of.initspeed = mh->tempo;
of.inittempo = mh->bpm; of.inittempo = mh->bpm;
strncpy(tracker,mh->trackername,20);tracker[20]=0; strncpy(tracker,mh->trackername,20);tracker[20]=0;
for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0; for(t=20;(t>=0)&&(tracker[t]<=' ');t--) tracker[t]=0;
/* some modules have the tracker name empty */ /* some modules have the tracker name empty */
if (!tracker[0]) if (!tracker[0])
@ -712,7 +721,7 @@ static int XM_Load(int curious)
sprintf(modtype,"%s (XM format %d.%02d)", sprintf(modtype,"%s (XM format %d.%02d)",
tracker,mh->version>>8,mh->version&0xff); tracker,mh->version>>8,mh->version&0xff);
#endif #endif
of.modtype = StrDup(modtype); of.modtype = MikMod_strdup(modtype);
of.numchn = mh->numchn; of.numchn = mh->numchn;
of.numpat = mh->numpat; of.numpat = mh->numpat;
of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */ of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
@ -720,8 +729,7 @@ static int XM_Load(int curious)
of.numpos = mh->songlength; /* copy the songlength */ of.numpos = mh->songlength; /* copy the songlength */
of.reppos = mh->restart<mh->songlength?mh->restart:0; of.reppos = mh->restart<mh->songlength?mh->restart:0;
of.numins = mh->numins; of.numins = mh->numins;
of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | UF_PANNING;
UF_PANNING;
if(mh->flags&1) of.flags |= UF_LINEAR; if(mh->flags&1) of.flags |= UF_LINEAR;
of.bpmlimit = 32; of.bpmlimit = 32;
@ -802,16 +810,19 @@ static int XM_Load(int curious)
MikMod_free(wh);MikMod_free(nextwav); MikMod_free(wh);MikMod_free(nextwav);
wh=NULL;nextwav=NULL; wh=NULL;nextwav=NULL;
return 1; return 1;
bad_hdr: _mm_errno = MMERR_LOADING_HEADER; return 0;
bad_xm: _mm_errno = MMERR_NOT_A_MODULE; return 0;
} }
static CHAR *XM_LoadTitle(void) static CHAR *XM_LoadTitle(void)
{ {
CHAR s[21]; CHAR str[21];
_mm_fseek(modreader,17,SEEK_SET); _mm_fseek(modreader,17,SEEK_SET);
if(!_mm_read_UBYTES(s,21,modreader)) return NULL; if(!_mm_read_UBYTES(str, 21, modreader)) return NULL;
return(DupStr(s,21,1)); return(DupStr(str,21,1));
} }
/*========== Loader information */ /*========== Loader information */

View file

@ -20,8 +20,6 @@
/*============================================================================== /*==============================================================================
$Id: mdreg.c,v 1.2 2005/03/30 19:11:13 realtech Exp $
Routine for registering all drivers in libmikmod for the current platform. Routine for registering all drivers in libmikmod for the current platform.
==============================================================================*/ ==============================================================================*/
@ -34,12 +32,13 @@
static void _mm_registeralldrivers(void) static void _mm_registeralldrivers(void)
{ {
#if 0
/* Register network drivers */ /* Register network drivers */
#ifdef DRV_AF #ifdef DRV_AF
_mm_registerdriver(&drv_AF); _mm_registerdriver(&drv_AF);
#endif #endif
#ifdef DRV_PULSEAUDIO
_mm_registerdriver(&drv_pulseaudio);
#endif
#ifdef DRV_ESD #ifdef DRV_ESD
_mm_registerdriver(&drv_esd); _mm_registerdriver(&drv_esd);
#endif #endif
@ -51,8 +50,22 @@ static void _mm_registeralldrivers(void)
#ifdef DRV_ULTRA #ifdef DRV_ULTRA
_mm_registerdriver(&drv_ultra); _mm_registerdriver(&drv_ultra);
#endif #endif
#ifdef DRV_SAM9407
_mm_registerdriver(&drv_sam9407);
#endif
/* Register hardware drivers - software mixing */ /* Register multi-platform drivers -- software mixing */
#ifdef DRV_SDL
_mm_registerdriver(&drv_sdl);
#endif
#ifdef DRV_OPENAL
_mm_registerdriver(&drv_openal);
#endif
/* Register OS-specific hardware drivers - software mixing */
#ifdef DRV_AHI
_mm_registerdriver(&drv_ahi);
#endif
#ifdef DRV_AIX #ifdef DRV_AIX
_mm_registerdriver(&drv_aix); _mm_registerdriver(&drv_aix);
#endif #endif
@ -62,6 +75,9 @@ static void _mm_registeralldrivers(void)
#ifdef DRV_HP #ifdef DRV_HP
_mm_registerdriver(&drv_hp); _mm_registerdriver(&drv_hp);
#endif #endif
#ifdef DRV_SNDIO
_mm_registerdriver(&drv_sndio);
#endif
#ifdef DRV_OSS #ifdef DRV_OSS
_mm_registerdriver(&drv_oss); _mm_registerdriver(&drv_oss);
#endif #endif
@ -77,6 +93,9 @@ static void _mm_registeralldrivers(void)
#ifdef DRV_OS2 #ifdef DRV_OS2
_mm_registerdriver(&drv_os2); _mm_registerdriver(&drv_os2);
#endif #endif
#ifdef DRV_XAUDIO2
_mm_registerdriver(&drv_xaudio2);
#endif
#ifdef DRV_DS #ifdef DRV_DS
_mm_registerdriver(&drv_ds); _mm_registerdriver(&drv_ds);
#endif #endif
@ -89,13 +108,24 @@ static void _mm_registeralldrivers(void)
#ifdef DRV_OSX #ifdef DRV_OSX
_mm_registerdriver(&drv_osx); _mm_registerdriver(&drv_osx);
#endif #endif
#ifdef DRV_DC
_mm_registerdriver(&drv_dc);
#endif
#ifdef DRV_GP32 #ifdef DRV_GP32
_mm_registerdriver(&drv_gp32); _mm_registerdriver(&drv_gp32);
#endif #endif
#ifdef DRV_PSP
_mm_registerdriver(&drv_psp);
#endif
#ifdef DRV_OSLES
_mm_registerdriver(&drv_osles);
#endif
#ifdef DRV_N64
_mm_registerdriver(&drv_n64);
#endif
/* dos drivers */ /* dos drivers - wss first, since some cards emulate sb */
#ifdef DRV_WSS #ifdef DRV_WSS
/* wss first, since some cards emulate sb */
_mm_registerdriver(&drv_wss); _mm_registerdriver(&drv_wss);
#endif #endif
#ifdef DRV_SB #ifdef DRV_SB
@ -103,25 +133,29 @@ static void _mm_registeralldrivers(void)
#endif #endif
/* Register disk writers */ /* Register disk writers */
_mm_registerdriver(&drv_raw); #ifdef DRV_WAV
_mm_registerdriver(&drv_wav); _mm_registerdriver(&drv_wav);
#endif
#ifdef DRV_AIFF #ifdef DRV_AIFF
_mm_registerdriver(&drv_aiff); _mm_registerdriver(&drv_aiff);
#endif #endif
#ifdef DRV_RAW
_mm_registerdriver(&drv_raw);
#endif
/* Register other drivers */ /* Register other drivers */
#ifdef DRV_PIPE #ifdef DRV_PIPE
_mm_registerdriver(&drv_pipe); _mm_registerdriver(&drv_pipe);
#endif #endif
#ifndef macintosh #if defined(DRV_STDOUT) && !defined(macintosh)
_mm_registerdriver(&drv_stdout); _mm_registerdriver(&drv_stdout);
#endif #endif
#endif /* Register 'nosound' driver */
_mm_registerdriver(&drv_nos); _mm_registerdriver(&drv_nos);
} }
void MikMod_RegisterAllDrivers(void) MIKMODAPI void MikMod_RegisterAllDrivers(void)
{ {
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
_mm_registeralldrivers(); _mm_registeralldrivers();

View file

@ -1,6 +1,6 @@
/* MikMod sound library /* MikMod sound library
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS (c) 1998-2014 Miodrag Vallat and others - see file AUTHORS
for complete list. for a complete list.
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as it under the terms of the GNU Library General Public License as
@ -20,8 +20,6 @@
/*============================================================================== /*==============================================================================
$Id: mdriver.c,v 1.4 2007/12/03 20:59:05 denis111 Exp $
These routines are used to access the available soundcard drivers. These routines are used to access the available soundcard drivers.
==============================================================================*/ ==============================================================================*/
@ -34,47 +32,52 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#if 0 #include <string.h>
#if defined unix || (defined __APPLE__ && defined __MACH__)
#include "mikmod_internals.h"
#if (MIKMOD_UNIX)
#include <pwd.h> #include <pwd.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "mikmod_internals.h"
#ifdef SUNOS #ifdef SUNOS
extern int fprintf(FILE *, const char *, ...); extern int fprintf(FILE *, const char *, ...);
#endif #endif
static MDRIVER *firstdriver=NULL;
MIKMODAPI MDRIVER *md_driver=NULL;
extern MODULE *pf; /* modfile being played */ extern MODULE *pf; /* modfile being played */
/* EXPORTED GLOBALS */
MIKMODAPI MDRIVER *md_driver = NULL;
/* Initial global settings */ /* Initial global settings */
MIKMODAPI UWORD md_device = 0; /* autodetect */ MIKMODAPI UWORD md_device = 0; /* autodetect */
MIKMODAPI UWORD md_mixfreq = 44100; MIKMODAPI ULONG md_mixfreq = 44100;
MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS | MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS |
DMODE_SURROUND |DMODE_SOFT_MUSIC | DMODE_SURROUND |
DMODE_SOFT_SNDFX; DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */
MIKMODAPI UBYTE md_reverb = 0; /* no reverb */ MIKMODAPI UBYTE md_reverb = 0; /* no reverb */
MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */ MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */
MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */ MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */
MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */ MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */
UWORD md_bpm = 125; /* tempo */
/* Do not modify the numchn variables yourself! use MD_SetVoices() */ /* INTERNAL GLOBALS */
UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0; UWORD md_bpm = 125; /* tempo */
UBYTE md_hardchn=0,md_softchn=0;
/* Do not modify the numchn variables yourself! use MikMod_SetNumVoices() */
UBYTE md_numchn = 0, md_sngchn = 0, md_sfxchn = 0;
UBYTE md_hardchn = 0, md_softchn= 0;
MikMod_player_t md_player = Player_HandleTick;
MikMod_callback_t vc_callback = NULL;
/* PRIVATE VARS */
static MDRIVER *firstdriver = NULL;
static volatile int isplaying = 0, initialized = 0;
void (*md_player)(void) = Player_HandleTick;
static volatile int isplaying=0, initialized = 0;
static UBYTE *sfxinfo; static UBYTE *sfxinfo;
static int sfxpool; static int sfxpool;
@ -183,16 +186,17 @@ MIKMODAPI CHAR* MikMod_InfoDriver(void)
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
/* compute size of buffer */ /* compute size of buffer */
for(l=firstdriver;l;l=l->next) for(l = firstdriver; l; l = l->next)
len+=4+(l->next?1:0)+strlen(l->Version); len += 4 + (l->next ? 1 : 0) + strlen(l->Version);
if(len) if(len)
if((list=MikMod_malloc(len*sizeof(CHAR)))) { if((list=(CHAR*)MikMod_malloc(len*sizeof(CHAR))) != NULL) {
list[0]=0; CHAR *list_end = list;
list[0] = 0;
/* list all registered device drivers : */ /* list all registered device drivers : */
for(t=1,l=firstdriver;l;l=l->next,t++) for(t = 1, l = firstdriver; l; l = l->next, t++) {
sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s", list_end += sprintf(list_end, "%2d %s%s", t, l->Version, (l->next)? "\n" : "");
list,t,l->Version); }
} }
MUTEX_UNLOCK(lists); MUTEX_UNLOCK(lists);
return list; return list;
@ -230,7 +234,7 @@ MIKMODAPI void MikMod_RegisterDriver(struct MDRIVER* drv)
MUTEX_UNLOCK(lists); MUTEX_UNLOCK(lists);
} }
MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias) MIKMODAPI int MikMod_DriverFromAlias(const CHAR *alias)
{ {
int rank=1; int rank=1;
MDRIVER *cruise; MDRIVER *cruise;
@ -255,8 +259,7 @@ MIKMODAPI MDRIVER *MikMod_DriverByOrdinal(int ordinal)
MDRIVER *cruise; MDRIVER *cruise;
/* Allow only driver ordinals > 0 */ /* Allow only driver ordinals > 0 */
if (!ordinal) if (!ordinal) return NULL;
return 0;
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
cruise = firstdriver; cruise = firstdriver;
@ -496,14 +499,12 @@ MIKMODAPI ULONG Voice_RealVolume(SBYTE voice)
return result; return result;
} }
extern MikMod_callback_t vc_callback;
MIKMODAPI void VC_SetCallback(MikMod_callback_t callback) MIKMODAPI void VC_SetCallback(MikMod_callback_t callback)
{ {
vc_callback = callback; vc_callback = callback;
} }
static int _mm_init(CHAR *cmdline) static int _mm_init(const CHAR *cmdline)
{ {
UWORD t; UWORD t;
@ -561,7 +562,7 @@ static int _mm_init(CHAR *cmdline)
return 0; return 0;
} }
MIKMODAPI int MikMod_Init(CHAR *cmdline) MIKMODAPI int MikMod_Init(const CHAR *cmdline)
{ {
int result; int result;
@ -581,8 +582,8 @@ void MikMod_Exit_internal(void)
md_numchn = md_sfxchn = md_sngchn = 0; md_numchn = md_sfxchn = md_sngchn = 0;
md_driver = &drv_nos; md_driver = &drv_nos;
if(sfxinfo) MikMod_free(sfxinfo); MikMod_free(sfxinfo);
if(md_sample) MikMod_free(md_sample); MikMod_free(md_sample);
md_sample = NULL; md_sample = NULL;
sfxinfo = NULL; sfxinfo = NULL;
@ -600,7 +601,7 @@ MIKMODAPI void MikMod_Exit(void)
/* Reset the driver using the new global variable settings. /* Reset the driver using the new global variable settings.
If the driver has not been initialized, it will be now. */ If the driver has not been initialized, it will be now. */
static int _mm_reset(CHAR *cmdline) static int _mm_reset(const CHAR *cmdline)
{ {
int wasplaying = 0; int wasplaying = 0;
@ -630,11 +631,11 @@ static int _mm_reset(CHAR *cmdline)
} }
} }
if (wasplaying) md_driver->PlayStart(); if (wasplaying) return md_driver->PlayStart();
return 0; return 0;
} }
MIKMODAPI int MikMod_Reset(CHAR *cmdline) MIKMODAPI int MikMod_Reset(const CHAR *cmdline)
{ {
int result; int result;
@ -661,8 +662,8 @@ int MikMod_SetNumVoices_internal(int music, int sfx)
resume = 1; resume = 1;
} }
if(sfxinfo) MikMod_free(sfxinfo); MikMod_free(sfxinfo);
if(md_sample) MikMod_free(md_sample); MikMod_free(md_sample);
md_sample = NULL; md_sample = NULL;
sfxinfo = NULL; sfxinfo = NULL;
@ -825,12 +826,15 @@ MIKMODAPI long MikMod_GetVersion(void)
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
#define INIT_MUTEX(name) \ #define INIT_MUTEX(name) \
pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER
#elif defined(__OS2__)||defined(__EMX__) #elif defined(__OS2__)||defined(__EMX__)
#define INIT_MUTEX(name) \ #define INIT_MUTEX(name) \
HMTX _mm_mutex_##name HMTX _mm_mutex_##name
#elif defined(WIN32)
#elif defined(_WIN32)
#define INIT_MUTEX(name) \ #define INIT_MUTEX(name) \
HANDLE _mm_mutex_##name HANDLE _mm_mutex_##name
#else #else
#define INIT_MUTEX(name) \ #define INIT_MUTEX(name) \
void *_mm_mutex_##name = NULL void *_mm_mutex_##name = NULL
@ -842,7 +846,7 @@ INIT_MUTEX(lists);
MIKMODAPI int MikMod_InitThreads(void) MIKMODAPI int MikMod_InitThreads(void)
{ {
static int firstcall=1; static int firstcall=1;
static int result=0; static int result = 0;
if (firstcall) { if (firstcall) {
firstcall=0; firstcall=0;
@ -855,9 +859,9 @@ MIKMODAPI int MikMod_InitThreads(void)
result=0; result=0;
} else } else
result=1; result=1;
#elif defined(WIN32) #elif defined(_WIN32)
if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))|| if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,TEXT("libmikmod(lists)"))))||
(!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)")))) (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,TEXT("libmikmod(vars)")))))
result=0; result=0;
else else
result=1; result=1;
@ -880,24 +884,24 @@ MIKMODAPI void MikMod_Lock(void)
/*========== Parameter extraction helper */ /*========== Parameter extraction helper */
CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,int implicit) CHAR *MD_GetAtom(const CHAR *atomname, const CHAR *cmdline, int implicit)
{ {
CHAR *ret=NULL; CHAR *ret=NULL;
if(cmdline) { if(cmdline) {
CHAR *buf=strstr(cmdline,atomname); const CHAR *buf=strstr(cmdline,atomname);
if((buf)&&((buf==cmdline)||(*(buf-1)==','))) { if((buf)&&((buf==cmdline)||(*(buf-1)==','))) {
CHAR *ptr=buf+strlen(atomname); const CHAR *ptr=buf+strlen(atomname);
if(*ptr=='=') { if(*ptr=='=') {
for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++); for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++);
ret=MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); ret=(CHAR *)MikMod_malloc((1+ptr-buf)*sizeof(CHAR));
if(ret) if(ret)
strncpy(ret,buf,ptr-buf); strncpy(ret,buf,ptr-buf);
} else if((*ptr==',')||(!*ptr)) { } else if((*ptr==',')||(!*ptr)) {
if(implicit) { if(implicit) {
ret=MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); ret=(CHAR *)MikMod_malloc((1+ptr-buf)*sizeof(CHAR));
if(ret) if(ret)
strncpy(ret,buf,ptr-buf); strncpy(ret,buf,ptr-buf);
} }
@ -907,8 +911,7 @@ CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,int implicit)
return ret; return ret;
} }
#if 0 #if (MIKMOD_UNIX)
#if defined unix || (defined __APPLE__ && defined __MACH__)
/*========== Posix helper functions */ /*========== Posix helper functions */
@ -917,7 +920,7 @@ CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,int implicit)
reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise. reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise.
The goal is to prevent a setuid root libmikmod application from overriding The goal is to prevent a setuid root libmikmod application from overriding
files like /etc/passwd with digital sound... */ files like /etc/passwd with digital sound... */
int MD_Access(CHAR *filename) int MD_Access(const CHAR * filename)
{ {
struct stat buf; struct stat buf;
@ -961,5 +964,5 @@ int MD_DropPrivileges(void)
} }
#endif #endif
#endif
/* ex:set ts=4: */ /* ex:set ts=8: */

View file

@ -25,7 +25,7 @@
/* Persistent configuration */ /* Persistent configuration */
#define MIKMOD_CONFIGFILE "mikmod.cfg" #define MIKMOD_CONFIGFILE "mikmod.cfg"
#define MIKMOD_SETTINGS_MINVERSION 1 #define MIKMOD_SETTINGS_MINVERSION 1
#define MIKMOD_SETTINGS_VERSION 1 #define MIKMOD_SETTINGS_VERSION 2
#ifdef USETHREADS #ifdef USETHREADS
#define EV_EXIT 9999 #define EV_EXIT 9999
@ -161,7 +161,6 @@ static bool mod_ext(const char ext[])
!rb->strcasecmp(ext,".dsm") || !rb->strcasecmp(ext,".dsm") ||
!rb->strcasecmp(ext,".far") || !rb->strcasecmp(ext,".far") ||
!rb->strcasecmp(ext,".gdm") || !rb->strcasecmp(ext,".gdm") ||
!rb->strcasecmp(ext,".gt2") ||
!rb->strcasecmp(ext,".imf") || !rb->strcasecmp(ext,".imf") ||
!rb->strcasecmp(ext,".it") || !rb->strcasecmp(ext,".it") ||
!rb->strcasecmp(ext,".m15") || !rb->strcasecmp(ext,".m15") ||
@ -174,6 +173,7 @@ static bool mod_ext(const char ext[])
!rb->strcasecmp(ext,".stx") || !rb->strcasecmp(ext,".stx") ||
!rb->strcasecmp(ext,".ult") || !rb->strcasecmp(ext,".ult") ||
!rb->strcasecmp(ext,".uni") || !rb->strcasecmp(ext,".uni") ||
!rb->strcasecmp(ext,".umx") ||
!rb->strcasecmp(ext,".xm") ) !rb->strcasecmp(ext,".xm") )
return true; return true;
else else
@ -465,32 +465,44 @@ struct mikmod_settings
{ {
int pansep; int pansep;
int reverb; int reverb;
int sample_rate;
bool interp; bool interp;
bool reverse; bool reverse;
bool surround; bool surround;
bool hqmixer;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
bool boost; bool boost;
#endif
}; };
static struct mikmod_settings settings = static struct mikmod_settings settings =
{ {
128, .pansep = 128,
0, .reverb = 0,
0, .sample_rate = -1,
0, .interp = 0,
1, .reverse = 0,
1 .surround = 1,
.hqmixer = 0,
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
.boost = 1,
#endif
}; };
static struct mikmod_settings old_settings; static struct mikmod_settings old_settings;
static struct configdata config[] = static const struct configdata config[] =
{ {
{ TYPE_INT, 0, 128, { .int_p = &settings.pansep }, "Panning Separation", NULL}, { TYPE_INT, 0, 128, { .int_p = &settings.pansep }, "Panning Separation", NULL},
{ TYPE_INT, 0, 15, { .int_p = &settings.reverb }, "Reverberation", NULL}, { TYPE_INT, 0, 15, { .int_p = &settings.reverb }, "Reverberation", NULL},
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.interp }, "Interpolation", NULL}, { TYPE_BOOL, 0, 1, { .bool_p = &settings.interp }, "Interpolation", NULL},
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.reverse }, "Reverse Channels", NULL}, { TYPE_BOOL, 0, 1, { .bool_p = &settings.reverse }, "Reverse Channels", NULL},
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.surround }, "Surround", NULL}, { TYPE_BOOL, 0, 1, { .bool_p = &settings.surround }, "Surround", NULL},
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.hqmixer }, "HQ Mixer", NULL},
{ TYPE_INT, 0, HW_NUM_FREQ-1, { .int_p = &settings.sample_rate }, "Sample Rate", NULL},
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.boost }, "CPU Boost", NULL}, { TYPE_BOOL, 0, 1, { .bool_p = &settings.boost }, "CPU Boost", NULL},
#endif
}; };
static void applysettings(void) static void applysettings(void)
@ -498,6 +510,7 @@ static void applysettings(void)
md_pansep = settings.pansep; md_pansep = settings.pansep;
md_reverb = settings.reverb; md_reverb = settings.reverb;
md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
if ( settings.interp ) if ( settings.interp )
{ {
md_mode |= DMODE_INTERP; md_mode |= DMODE_INTERP;
@ -510,6 +523,21 @@ static void applysettings(void)
{ {
md_mode |= DMODE_SURROUND; md_mode |= DMODE_SURROUND;
} }
#ifndef NO_HQMIXER
if ( settings.hqmixer )
{
md_mode |= DMODE_HQMIXER;
}
#endif
if (md_mixfreq != rb->hw_freq_sampr[settings.sample_rate]) {
md_mixfreq = rb->hw_freq_sampr[settings.sample_rate];
// MikMod_Reset(""); BROKEN!
rb->pcm_play_stop();
rb->mixer_set_frequency(md_mixfreq);
rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
if ( Player_Active() ) if ( Player_Active() )
{ {
@ -518,6 +546,21 @@ static void applysettings(void)
#endif #endif
} }
static const struct opt_items sr_names[HW_NUM_FREQ] = {
HW_HAVE_96_([HW_FREQ_96] = { "96kHz", TALK_ID(96, UNIT_KHZ) },)
HW_HAVE_88_([HW_FREQ_88] = { "88.2kHz", TALK_ID(88, UNIT_KHZ) },)
HW_HAVE_64_([HW_FREQ_64] = { "64kHz", TALK_ID(64, UNIT_KHZ) },)
HW_HAVE_48_([HW_FREQ_48] = { "48kHz", TALK_ID(48, UNIT_KHZ) },)
HW_HAVE_44_([HW_FREQ_44] = { "44.1kHz", TALK_ID(44, UNIT_KHZ) },)
HW_HAVE_32_([HW_FREQ_32] = { "32kHz", TALK_ID(32, UNIT_KHZ) },)
HW_HAVE_24_([HW_FREQ_24] = { "24kHz", TALK_ID(24, UNIT_KHZ) },)
HW_HAVE_22_([HW_FREQ_22] = { "22.05kHz", TALK_ID(22, UNIT_KHZ) },)
HW_HAVE_16_([HW_FREQ_16] = { "16kHz", TALK_ID(16, UNIT_KHZ) },)
HW_HAVE_12_([HW_FREQ_12] = { "12kHz", TALK_ID(12, UNIT_KHZ) },)
HW_HAVE_11_([HW_FREQ_11] = { "11.025kHz", TALK_ID(11, UNIT_KHZ) },)
HW_HAVE_8_( [HW_FREQ_8 ] = { "8kHz", TALK_ID( 8, UNIT_KHZ) },)
};
/** /**
Shows the settings menu Shows the settings menu
*/ */
@ -531,6 +574,8 @@ static int settings_menu(void)
ID2P(LANG_INTERPOLATION), ID2P(LANG_INTERPOLATION),
ID2P(LANG_SWAP_CHANNELS), ID2P(LANG_SWAP_CHANNELS),
ID2P(LANG_MIKMOD_SURROUND), ID2P(LANG_MIKMOD_SURROUND),
ID2P(LANG_MIKMOD_HQMIXER),
ID2P(LANG_MIKMOD_SAMPLERATE),
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
ID2P(LANG_CPU_BOOST) ID2P(LANG_CPU_BOOST)
#endif #endif
@ -571,9 +616,22 @@ static int settings_menu(void)
break; break;
case 5: case 5:
rb->set_bool(rb->str(LANG_MIKMOD_HQMIXER), &(settings.hqmixer));
applysettings();
break;
case 6:
rb->set_option(rb->str(LANG_MIKMOD_SAMPLERATE), &(settings.sample_rate), INT, sr_names,
HW_NUM_FREQ, NULL);
applysettings();
break;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
case 7:
rb->set_bool(rb->str(LANG_CPU_BOOST), &(settings.boost)); rb->set_bool(rb->str(LANG_CPU_BOOST), &(settings.boost));
applysettings(); applysettings();
break; break;
#endif
case MENU_ATTACHED_USB: case MENU_ATTACHED_USB:
return PLUGIN_USB_CONNECTED; return PLUGIN_USB_CONNECTED;
@ -675,8 +733,7 @@ static int playfile(char* filename)
} }
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
if ( settings.boost ) rb->cpu_boost(settings.boost);
rb->cpu_boost(true);
#endif #endif
#ifdef USETHREADS #ifdef USETHREADS
rb->queue_init(&thread_q, true); rb->queue_init(&thread_q, true);
@ -850,7 +907,6 @@ static int playfile(char* filename)
rb->queue_delete(&thread_q); rb->queue_delete(&thread_q);
#endif #endif
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
if ( settings.boost )
rb->cpu_boost(false); rb->cpu_boost(false);
#endif #endif
@ -891,7 +947,6 @@ enum plugin_status plugin_start(const void* parameter)
rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
#endif #endif
rb->mixer_set_frequency(SAMPLE_RATE);
audio_buffer = rb->plugin_get_audio_buffer((size_t *)&audio_buffer_free); audio_buffer = rb->plugin_get_audio_buffer((size_t *)&audio_buffer_free);
@ -908,11 +963,24 @@ enum plugin_status plugin_start(const void* parameter)
MikMod_RegisterAllLoaders(); MikMod_RegisterAllLoaders();
MikMod_RegisterErrorHandler(mm_errorhandler); MikMod_RegisterErrorHandler(mm_errorhandler);
md_mixfreq = SAMPLE_RATE;
configfile_load(MIKMOD_CONFIGFILE, config, configfile_load(MIKMOD_CONFIGFILE, config,
ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION); ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION);
rb->memcpy(&old_settings, &settings, sizeof (settings)); rb->memcpy(&old_settings, &settings, sizeof (settings));
/* If there's no configured rate, use the default */
if (settings.sample_rate == -1) {
int i;
for (i = 0 ; i < HW_NUM_FREQ ; i++) {
if (rb->hw_freq_sampr[i] == SAMPLE_RATE) {
settings.sample_rate = i;
break;
}
}
if (settings.sample_rate == -1) {
settings.sample_rate = HW_NUM_FREQ -1;
}
}
applysettings(); applysettings();
if (MikMod_Init("")) if (MikMod_Init(""))
@ -934,7 +1002,6 @@ enum plugin_status plugin_start(const void* parameter)
if (retval == PLUGIN_OK) if (retval == PLUGIN_OK)
{ {
rb->splash(0, "Saving Settings");
if (rb->memcmp(&settings, &old_settings, sizeof (settings))) if (rb->memcmp(&settings, &old_settings, sizeof (settings)))
{ {
configfile_save(MIKMOD_CONFIGFILE, config, configfile_save(MIKMOD_CONFIGFILE, config,

View file

@ -1,5 +1,5 @@
/* MikMod sound library /* MikMod sound library
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS (c) 1998-2014 Miodrag Vallat and others - see the AUTHORS file
for complete list. for complete list.
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify
@ -20,11 +20,9 @@
/*============================================================================== /*==============================================================================
$Id: mikmod.h.in,v 1.3 2005/03/30 19:09:21 realtech Exp $
MikMod sound library include file MikMod sound library include file
==============================================================================*/ ==============================================================================*/
#ifndef _MIKMOD_H_ #ifndef _MIKMOD_H_
#define _MIKMOD_H_ #define _MIKMOD_H_
@ -40,16 +38,36 @@ extern "C" {
/* /*
* ========== Compiler magic for shared libraries * ========== Compiler magic for shared libraries
*
* ========== NOTE TO WINDOWS DEVELOPERS:
* If you are compiling for Windows and will link to the static library
* (libmikmod.a with MinGW, or mikmod_static.lib with MSVC or LCC, etc),
* you must define MIKMOD_STATIC in your project. Otherwise, dllimport
* will be assumed.
*/ */
#if defined(_WIN32) || defined(__CYGWIN__)
#if defined WIN32 && defined _DLL # if defined(MIKMOD_BUILD) && defined(DLL_EXPORT) /* building libmikmod as a dll for windows */
#ifdef DLL_EXPORTS # define MIKMODAPI __declspec(dllexport)
#define MIKMODAPI __declspec(dllexport) # elif defined(MIKMOD_BUILD) || defined(MIKMOD_STATIC) /* building or using static libmikmod for windows */
# define MIKMODAPI
# else
# define MIKMODAPI __declspec(dllimport) /* using libmikmod dll for windows */
# endif
#elif defined(__OS2__) && defined(__WATCOMC__)
# if defined(MIKMOD_BUILD) && defined(__SW_BD) /* building libmikmod as a dll for os/2 */
# define MIKMODAPI __declspec(dllexport)
# else
# define MIKMODAPI /* using dll or static libmikmod for os/2 */
# endif
/* SYM_VISIBILITY should be defined if both the compiler
* and the target support the visibility attributes. the
* configury does that automatically. for the standalone
* makefiles, etc, the developer should add the required
* flags, i.e.: -DSYM_VISIBILITY -fvisibility=hidden */
#elif defined(MIKMOD_BUILD) && defined(SYM_VISIBILITY)
# define MIKMODAPI __attribute__((visibility("default")))
#else #else
#define MIKMODAPI __declspec(dllimport) # define MIKMODAPI
#endif
#else
#define MIKMODAPI
#endif #endif
/* /*
@ -57,8 +75,8 @@ extern "C" {
*/ */
#define LIBMIKMOD_VERSION_MAJOR 3L #define LIBMIKMOD_VERSION_MAJOR 3L
#define LIBMIKMOD_VERSION_MINOR 2L #define LIBMIKMOD_VERSION_MINOR 3L
#define LIBMIKMOD_REVISION 0L #define LIBMIKMOD_REVISION 11L
#define LIBMIKMOD_VERSION \ #define LIBMIKMOD_VERSION \
((LIBMIKMOD_VERSION_MAJOR<<16)| \ ((LIBMIKMOD_VERSION_MAJOR<<16)| \
@ -68,52 +86,90 @@ extern "C" {
MIKMODAPI extern long MikMod_GetVersion(void); MIKMODAPI extern long MikMod_GetVersion(void);
/* /*
* ========== Platform independent-type definitions * ========== Dependency platform headers
*/ */
#if 0
#ifdef WIN32 #ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
#include <mmsystem.h> #include <mmsystem.h>
#define _MIKMOD_WIN32
#endif #endif
#if defined(__OS2__)||defined(__EMX__) #if defined(__DJGPP__) || defined(MSDOS) || defined(__MSDOS__) || defined(__DOS__)
#define _MIKMOD_DOS
#endif
#if defined(__OS2__) || defined(__EMX__)
#define INCL_DOSSEMAPHORES #define INCL_DOSSEMAPHORES
#include <os2.h> #include <os2.h>
#else #include <io.h>
#define _MIKMOD_OS2
#endif
#if defined(__MORPHOS__) || defined(__AROS__) || defined(_AMIGA) || defined(__AMIGA__) || defined(__amigaos__) || defined(AMIGAOS)
#include <exec/types.h>
#define _MIKMOD_AMIGA
#endif
/*
* ========== Platform independent-type definitions
* (pain when it comes to cross-platform maintenance..)
*/
#if !(defined(_MIKMOD_OS2) || defined(_MIKMOD_WIN32))
typedef char CHAR; typedef char CHAR;
#endif #endif
/* int: 0=false, <>0 true -- 16 bits on Amiga, int-wide on others. */
#if !(defined(_MIKMOD_OS2) || defined(_MIKMOD_WIN32) || defined(_MIKMOD_AMIGA))
//typedef int int;
#endif #endif
typedef char CHAR; /* 1 byte, signed and unsigned: */
typedef signed char SBYTE;
#ifndef _MIKMOD_AMIGA
typedef unsigned char UBYTE;
#endif
/* 2 bytes, signed and unsigned: */
#if !(defined __LCC__ && defined _WIN32)
typedef signed short int SWORD;
#endif
#if !((defined __LCC__ && defined _WIN32) || defined(_MIKMOD_AMIGA))
typedef unsigned short int UWORD;
#endif
#if defined(__arch64__) || defined(__alpha) || defined(__x86_64) || defined(__powerpc64__) /* 4 bytes, signed and unsigned: */
/* 64 bit architectures */ #if defined(_LP64) || defined(__LP64__) || defined(__arch64__) || defined(__alpha) || defined(__x86_64) || defined(__powerpc64__)
/* 64 bit architectures: */
typedef signed int SLONG;
#if !(defined(_WIN32) || defined(_MIKMOD_AMIGA))
typedef unsigned int ULONG;
#endif
typedef signed char SBYTE; /* 1 byte, signed */ #else /* 32 bit architectures: */
typedef unsigned char UBYTE; /* 1 byte, unsigned */ typedef signed long int SLONG;
typedef signed short SWORD; /* 2 bytes, signed */ #if !(defined(_MIKMOD_OS2) || defined(_MIKMOD_WIN32) || defined(_MIKMOD_AMIGA))
typedef unsigned short UWORD; /* 2 bytes, unsigned */ typedef unsigned long int ULONG;
typedef signed int SLONG; /* 4 bytes, signed */
typedef unsigned int ULONG; /* 4 bytes, unsigned */
//typedef int BOOL; /* 0=false, <>0 true */
#else
/* 32 bit architectures */
typedef signed char SBYTE; /* 1 byte, signed */
typedef unsigned char UBYTE; /* 1 byte, unsigned */
typedef signed short SWORD; /* 2 bytes, signed */
typedef unsigned short UWORD; /* 2 bytes, unsigned */
typedef signed long SLONG; /* 4 bytes, signed */
#if !defined(__OS2__)&&!defined(__EMX__)&&!defined(WIN32)
typedef unsigned long ULONG; /* 4 bytes, unsigned */
//typedef int BOOL; /* 0=false, <>0 true */
#endif #endif
#endif #endif
/* make sure types are of correct sizes: */
typedef int __mikmod_typetest [
(
(sizeof(SBYTE)==1) && (sizeof(UBYTE)==1)
&& (sizeof(SWORD)==2) && (sizeof(UWORD)==2)
&& (sizeof(SLONG)==4) && (sizeof(ULONG)==4)
#ifndef _MIKMOD_AMIGA
&& (sizeof(int) == sizeof(int))
#endif
&& (sizeof(CHAR) == sizeof(char))
) * 2 - 1 ];
/* /*
* ========== Error codes * ========== Error codes
*/ */
@ -210,6 +266,33 @@ enum {
MMERR_DOSWSS_STARTDMA, MMERR_DOSWSS_STARTDMA,
MMERR_DOSSB_STARTDMA, MMERR_DOSSB_STARTDMA,
MMERR_NO_FLOAT32,/* should actually be after MMERR_ULAW or something */
MMERR_OPENAL_CREATECTX,
MMERR_OPENAL_CTXCURRENT,
MMERR_OPENAL_GENBUFFERS,
MMERR_OPENAL_GENSOURCES,
MMERR_OPENAL_SOURCE,
MMERR_OPENAL_QUEUEBUFFERS,
MMERR_OPENAL_UNQUEUEBUFFERS,
MMERR_OPENAL_BUFFERDATA,
MMERR_OPENAL_GETSOURCE,
MMERR_OPENAL_SOURCEPLAY,
MMERR_OPENAL_SOURCESTOP,
MMERR_ALSA_NOCONFIG,
MMERR_ALSA_SETPARAMS,
MMERR_ALSA_SETFORMAT,
MMERR_ALSA_SETRATE,
MMERR_ALSA_SETCHANNELS,
MMERR_ALSA_BUFFERSIZE,
MMERR_ALSA_PCM_START,
MMERR_ALSA_PCM_WRITE,
MMERR_ALSA_PCM_RECOVER,
MMERR_SNDIO_SETPARAMS,
MMERR_SNDIO_BADPARAMS,
MMERR_MAX MMERR_MAX
}; };
@ -222,7 +305,7 @@ typedef MikMod_handler *MikMod_handler_t;
MIKMODAPI extern int MikMod_errno; MIKMODAPI extern int MikMod_errno;
MIKMODAPI extern int MikMod_critical; MIKMODAPI extern int MikMod_critical;
MIKMODAPI extern char *MikMod_strerror(int); MIKMODAPI extern const char *MikMod_strerror(int);
MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t); MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t);
@ -236,12 +319,12 @@ MIKMODAPI extern void MikMod_RegisterAllDrivers(void);
MIKMODAPI extern CHAR* MikMod_InfoDriver(void); MIKMODAPI extern CHAR* MikMod_InfoDriver(void);
MIKMODAPI extern void MikMod_RegisterDriver(struct MDRIVER*); MIKMODAPI extern void MikMod_RegisterDriver(struct MDRIVER*);
MIKMODAPI extern int MikMod_DriverFromAlias(CHAR*); MIKMODAPI extern int MikMod_DriverFromAlias(const CHAR*);
MIKMODAPI extern struct MDRIVER *MikMod_DriverByOrdinal(int); MIKMODAPI extern struct MDRIVER *MikMod_DriverByOrdinal(int);
MIKMODAPI extern int MikMod_Init(CHAR*); MIKMODAPI extern int MikMod_Init(const CHAR*);
MIKMODAPI extern void MikMod_Exit(void); MIKMODAPI extern void MikMod_Exit(void);
MIKMODAPI extern int MikMod_Reset(CHAR*); MIKMODAPI extern int MikMod_Reset(const CHAR*);
MIKMODAPI extern int MikMod_SetNumVoices(int,int); MIKMODAPI extern int MikMod_SetNumVoices(int,int);
MIKMODAPI extern int MikMod_Active(void); MIKMODAPI extern int MikMod_Active(void);
MIKMODAPI extern int MikMod_EnableOutput(void); MIKMODAPI extern int MikMod_EnableOutput(void);
@ -253,9 +336,10 @@ MIKMODAPI extern void MikMod_Lock(void);
MIKMODAPI extern void MikMod_Unlock(void); MIKMODAPI extern void MikMod_Unlock(void);
MIKMODAPI extern void* MikMod_malloc(size_t); MIKMODAPI extern void* MikMod_malloc(size_t);
MIKMODAPI extern void* MikMod_realloc(void *, size_t);
MIKMODAPI extern void* MikMod_calloc(size_t,size_t); MIKMODAPI extern void* MikMod_calloc(size_t,size_t);
MIKMODAPI extern void MikMod_free(void*); MIKMODAPI extern void* MikMod_realloc(void*,size_t);
MIKMODAPI extern CHAR* MikMod_strdup(const CHAR*);
MIKMODAPI extern void MikMod_free(void*); /* frees if ptr != NULL */
/* /*
* ========== Reader, Writer * ========== Reader, Writer
@ -272,10 +356,10 @@ typedef struct MREADER {
} MREADER; } MREADER;
typedef struct MWRITER { typedef struct MWRITER {
int (*Seek)(struct MWRITER*,long,int); int (*Seek)(struct MWRITER*, long, int);
long (*Tell)(struct MWRITER*); long (*Tell)(struct MWRITER*);
int (*Write)(struct MWRITER*,void*,size_t); int (*Write)(struct MWRITER*, const void*, size_t);
int (*Put)(struct MWRITER*,int); int (*Put)(struct MWRITER*, int);
} MWRITER; } MWRITER;
/* /*
@ -351,12 +435,12 @@ typedef struct SAMPLE {
/* Sample functions */ /* Sample functions */
MIKMODAPI extern SAMPLE *Sample_LoadRaw(CHAR *,ULONG rate, ULONG channel, ULONG flags); MIKMODAPI extern SAMPLE *Sample_LoadRaw(const CHAR *,ULONG rate, ULONG channel, ULONG flags);
MIKMODAPI extern SAMPLE *Sample_LoadRawFP(int fp,ULONG rate,ULONG channel, ULONG flags); MIKMODAPI extern SAMPLE *Sample_LoadRawFP(int fp,ULONG rate,ULONG channel, ULONG flags);
MIKMODAPI extern SAMPLE *Sample_LoadRawMem(const char *buf, int len, ULONG rate, ULONG channel, ULONG flags); MIKMODAPI extern SAMPLE *Sample_LoadRawMem(const char *buf, int len, ULONG rate, ULONG channel, ULONG flags);
MIKMODAPI extern SAMPLE *Sample_LoadRawGeneric(MREADER*reader,ULONG rate, ULONG channel, ULONG flags); MIKMODAPI extern SAMPLE *Sample_LoadRawGeneric(MREADER*reader,ULONG rate, ULONG channel, ULONG flags);
MIKMODAPI extern SAMPLE *Sample_Load(CHAR*); MIKMODAPI extern SAMPLE *Sample_Load(const CHAR*);
MIKMODAPI extern SAMPLE *Sample_LoadFP(int); MIKMODAPI extern SAMPLE *Sample_LoadFP(int);
MIKMODAPI extern SAMPLE *Sample_LoadMem(const char *buf, int len); MIKMODAPI extern SAMPLE *Sample_LoadMem(const char *buf, int len);
MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*); MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*);
@ -481,8 +565,10 @@ typedef struct MODULE {
UWORD numpat; /* number of patterns in this song */ UWORD numpat; /* number of patterns in this song */
UWORD numins; /* number of instruments */ UWORD numins; /* number of instruments */
UWORD numsmp; /* number of samples */ UWORD numsmp; /* number of samples */
struct INSTRUMENT* instruments; /* all instruments */
struct SAMPLE* samples; /* all samples */ struct INSTRUMENT* instruments; /* all instruments */
struct SAMPLE* samples; /* all samples */
UBYTE realchn; /* real number of channels used */ UBYTE realchn; /* real number of channels used */
UBYTE totalchn; /* total number of channels used (incl NNAs) */ UBYTE totalchn; /* total number of channels used (incl NNAs) */
@ -521,8 +607,8 @@ struct SAMPLE* samples; /* all samples */
UWORD vbtick; /* tick counter (counts from 0 to sngspd) */ UWORD vbtick; /* tick counter (counts from 0 to sngspd) */
UWORD sngremainder;/* used for song time computation */ UWORD sngremainder;/* used for song time computation */
struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */ struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */
struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */ struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */
UBYTE globalslide; /* global volume slide rate */ UBYTE globalslide; /* global volume slide rate */
UBYTE pat_repcrazy;/* module has just looped to position -1 */ UBYTE pat_repcrazy;/* module has just looped to position -1 */
@ -572,6 +658,7 @@ MIKMODAPI extern struct MLOADER load_stm; /* ScreamTracker 2 (by Future Crew) */
MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */ MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */
MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */ MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */
MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker (by MAS) */ MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker (by MAS) */
MIKMODAPI extern struct MLOADER load_umx; /* Unreal UMX container of Epic Games */
MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */ MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */
MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */ MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */
@ -579,11 +666,11 @@ MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */
* ========== Module player * ========== Module player
*/ */
MIKMODAPI extern MODULE* Player_Load(CHAR*,int,int); MIKMODAPI extern MODULE* Player_Load(const CHAR*,int,int);
MIKMODAPI extern MODULE* Player_LoadFP(int,int,int); MIKMODAPI extern MODULE* Player_LoadFP(int,int,int);
MIKMODAPI extern MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,int curious); MIKMODAPI extern MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,int curious);
MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,int); MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,int);
MIKMODAPI extern CHAR* Player_LoadTitle(CHAR*); MIKMODAPI extern CHAR* Player_LoadTitle(const CHAR*);
MIKMODAPI extern CHAR* Player_LoadTitleFP(int); MIKMODAPI extern CHAR* Player_LoadTitleFP(int);
MIKMODAPI extern CHAR* Player_LoadTitleMem(const char *buffer,int len); MIKMODAPI extern CHAR* Player_LoadTitleMem(const char *buffer,int len);
MIKMODAPI extern CHAR* Player_LoadTitleGeneric(MREADER*); MIKMODAPI extern CHAR* Player_LoadTitleGeneric(MREADER*);
@ -649,19 +736,21 @@ enum {
#define DMODE_SIMDMIXER 0x0800 /* enable SIMD mixing */ #define DMODE_SIMDMIXER 0x0800 /* enable SIMD mixing */
#define DMODE_NOISEREDUCTION 0x1000 /* Low pass filtering */ #define DMODE_NOISEREDUCTION 0x1000 /* Low pass filtering */
struct SAMPLOAD; struct SAMPLOAD;
typedef struct MDRIVER { typedef struct MDRIVER {
struct MDRIVER* next; struct MDRIVER* next;
CHAR* Name; const CHAR* Name;
CHAR* Version; const CHAR* Version;
UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */ UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */
UBYTE SoftVoiceLimit; /* Limit of software mixer voices */ UBYTE SoftVoiceLimit; /* Limit of software mixer voices */
CHAR *Alias; const CHAR* Alias;
CHAR *CmdLineHelp; const CHAR* CmdLineHelp;
void (*CommandLine) (CHAR*); void (*CommandLine) (const CHAR*);
int (*IsPresent) (void); int (*IsPresent) (void);
SWORD (*SampleLoad) (struct SAMPLOAD*,int); SWORD (*SampleLoad) (struct SAMPLOAD*,int);
void (*SampleUnload) (SWORD); void (*SampleUnload) (SWORD);
@ -700,7 +789,7 @@ MIKMODAPI extern UBYTE md_pansep; /* 0 = mono; 128 == 100% (full left/righ
in a skip or pop in audio (depending on the soundcard driver and the settings in a skip or pop in audio (depending on the soundcard driver and the settings
changed). */ changed). */
MIKMODAPI extern UWORD md_device; /* device */ MIKMODAPI extern UWORD md_device; /* device */
MIKMODAPI extern UWORD md_mixfreq; /* mixing frequency */ MIKMODAPI extern ULONG md_mixfreq; /* mixing frequency */
MIKMODAPI extern UWORD md_mode; /* mode. See DMODE_? flags above */ MIKMODAPI extern UWORD md_mode; /* mode. See DMODE_? flags above */
/* The following variable should not be changed! */ /* The following variable should not be changed! */
@ -709,7 +798,6 @@ MIKMODAPI extern MDRIVER* md_driver; /* Current driver in use. */
/* Known drivers list */ /* Known drivers list */
MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */ MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */
#if 0
MIKMODAPI extern struct MDRIVER drv_pipe; /* piped output */ MIKMODAPI extern struct MDRIVER drv_pipe; /* piped output */
MIKMODAPI extern struct MDRIVER drv_raw; /* raw file disk writer [music.raw] */ MIKMODAPI extern struct MDRIVER drv_raw; /* raw file disk writer [music.raw] */
MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */ MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */
@ -717,32 +805,43 @@ MIKMODAPI extern struct MDRIVER drv_wav; /* RIFF WAVE file disk writer [music
MIKMODAPI extern struct MDRIVER drv_aiff; /* AIFF file disk writer [music.aiff] */ MIKMODAPI extern struct MDRIVER drv_aiff; /* AIFF file disk writer [music.aiff] */
MIKMODAPI extern struct MDRIVER drv_ultra; /* Linux Ultrasound driver */ MIKMODAPI extern struct MDRIVER drv_ultra; /* Linux Ultrasound driver */
MIKMODAPI extern struct MDRIVER drv_sam9407; /* Linux sam9407 driver */ MIKMODAPI extern struct MDRIVER drv_sam9407;/* Linux sam9407 driver */
MIKMODAPI extern struct MDRIVER drv_AF; /* Dec Alpha AudioFile */ MIKMODAPI extern struct MDRIVER drv_AF; /* Dec Alpha AudioFile */
MIKMODAPI extern struct MDRIVER drv_ahi; /* Amiga AHI */
MIKMODAPI extern struct MDRIVER drv_aix; /* AIX audio device */ MIKMODAPI extern struct MDRIVER drv_aix; /* AIX audio device */
MIKMODAPI extern struct MDRIVER drv_alsa; /* Advanced Linux Sound Architecture (ALSA) */ MIKMODAPI extern struct MDRIVER drv_alsa; /* Advanced Linux Sound Architecture (ALSA) */
MIKMODAPI extern struct MDRIVER drv_esd; /* Enlightened sound daemon (EsounD) */ MIKMODAPI extern struct MDRIVER drv_esd; /* Enlightened sound daemon (EsounD) */
MIKMODAPI extern struct MDRIVER drv_pulseaudio; /* PulseAudio */
MIKMODAPI extern struct MDRIVER drv_hp; /* HP-UX audio device */ MIKMODAPI extern struct MDRIVER drv_hp; /* HP-UX audio device */
MIKMODAPI extern struct MDRIVER drv_nas; /* Network Audio System (NAS) */ MIKMODAPI extern struct MDRIVER drv_nas; /* Network Audio System (NAS) */
MIKMODAPI extern struct MDRIVER drv_oss; /* OpenSound System (Linux,FreeBSD...) */ MIKMODAPI extern struct MDRIVER drv_oss; /* OpenSound System (Linux,FreeBSD...) */
MIKMODAPI extern struct MDRIVER drv_openal; /* OpenAL driver */
MIKMODAPI extern struct MDRIVER drv_sdl; /* SDL audio driver */
MIKMODAPI extern struct MDRIVER drv_sgi; /* SGI audio library */ MIKMODAPI extern struct MDRIVER drv_sgi; /* SGI audio library */
MIKMODAPI extern struct MDRIVER drv_sndio; /* OpenBSD sndio */
MIKMODAPI extern struct MDRIVER drv_sun; /* Sun/NetBSD/OpenBSD audio device */ MIKMODAPI extern struct MDRIVER drv_sun; /* Sun/NetBSD/OpenBSD audio device */
MIKMODAPI extern struct MDRIVER drv_dart; /* OS/2 Direct Audio RealTime */ MIKMODAPI extern struct MDRIVER drv_dart; /* OS/2 Direct Audio RealTime */
MIKMODAPI extern struct MDRIVER drv_os2; /* OS/2 MMPM/2 */ MIKMODAPI extern struct MDRIVER drv_os2; /* OS/2 MMPM/2 */
MIKMODAPI extern struct MDRIVER drv_ds; /* Win32 DirectSound driver */ MIKMODAPI extern struct MDRIVER drv_ds; /* Win32 DirectSound driver */
MIKMODAPI extern struct MDRIVER drv_xaudio2;/* Win32 XAudio2 driver */
MIKMODAPI extern struct MDRIVER drv_win; /* Win32 multimedia API driver */ MIKMODAPI extern struct MDRIVER drv_win; /* Win32 multimedia API driver */
MIKMODAPI extern struct MDRIVER drv_mac; /* Macintosh Sound Manager driver */ MIKMODAPI extern struct MDRIVER drv_mac; /* Macintosh Sound Manager driver */
MIKMODAPI extern struct MDRIVER drv_osx; /* MacOS X CoreAudio Driver */ MIKMODAPI extern struct MDRIVER drv_osx; /* MacOS X CoreAudio Driver */
MIKMODAPI extern struct MDRIVER drv_dc; /* Dreamcast driver */
MIKMODAPI extern struct MDRIVER drv_gp32; /* GP32 Sound driver */ MIKMODAPI extern struct MDRIVER drv_gp32; /* GP32 Sound driver */
MIKMODAPI extern struct MDRIVER drv_psp; /* PlayStation Portable driver */
MIKMODAPI extern struct MDRIVER drv_n64; /* Nintendo64 driver */
MIKMODAPI extern struct MDRIVER drv_wss; /* DOS WSS driver */ MIKMODAPI extern struct MDRIVER drv_wss; /* DOS WSS driver */
MIKMODAPI extern struct MDRIVER drv_sb; /* DOS SB driver */ MIKMODAPI extern struct MDRIVER drv_sb; /* DOS S/B driver */
#endif
MIKMODAPI extern struct MDRIVER drv_osles; /* OpenSL ES driver for android */
/*========== Virtual channel mixer interface (for user-supplied drivers only) */ /*========== Virtual channel mixer interface (for user-supplied drivers only) */
MIKMODAPI extern int VC_Init(void); MIKMODAPI extern int VC_Init(void);

View file

@ -20,11 +20,9 @@
/*============================================================================== /*==============================================================================
$Id: mikmod_internals.h,v 1.7 2010/01/12 03:30:31 realtech Exp $
MikMod sound library internal definitions MikMod sound library internal definitions
==============================================================================*/ ==============================================================================*/
#ifndef _MIKMOD_INTERNALS_H #ifndef _MIKMOD_INTERNALS_H
#define _MIKMOD_INTERNALS_H #define _MIKMOD_INTERNALS_H
@ -34,32 +32,52 @@ extern "C" {
#endif #endif
#include <stdarg.h> #include <stdarg.h>
#if 0
#if defined(__OS2__)||defined(__EMX__)||defined(WIN32) #if defined(_MSC_VER) && !defined(__cplusplus) && !defined(HAVE_CONFIG_H)
#define strcasecmp(s,t) stricmp(s,t) #define inline __inline
#endif
#endif #endif
#include "mikmod.h" #include "mikmod.h"
#ifndef MIKMOD_UNIX
#if (defined(unix) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) && \
!(defined(_MIKMOD_WIN32) || defined(_MIKMOD_OS2) || defined(_MIKMOD_DOS) || defined(_MIKMOD_AMIGA) || defined(macintosh))
#define MIKMOD_UNIX 1
#else
#define MIKMOD_UNIX 0
#endif
#endif /* MIKMOD_UNIX */
/*========== More type definitions */ /*========== More type definitions */
/* SLONGLONG: 64bit, signed */ /* SLONGLONG: 64bit, signed */
#if defined (__arch64__) || defined(__alpha) || defined (__x64_64) || defined (_LP64) || defined (__powerpc64__) #if !defined(_WIN32) && \
(defined(_LP64) || defined(__LP64__) || defined(__arch64__) || defined(__alpha) || defined(__x64_64) || defined(__powerpc64__))
typedef long SLONGLONG; typedef long SLONGLONG;
#define NATIVE_64BIT_INT #define NATIVE_64BIT_INT
#if 0 #elif defined(_WIN64) /* win64 is LLP64, not LP64 */
#define NATIVE_64BIT_INT
typedef long long SLONGLONG;
#elif defined(__WATCOMC__) #elif defined(__WATCOMC__)
typedef __int64 SLONGLONG; typedef __int64 SLONGLONG;
#elif defined(WIN32) && !defined(__MWERKS__) #elif defined(_WIN32) && !defined(__MWERKS__)
typedef LONGLONG SLONGLONG; typedef LONGLONG SLONGLONG;
#elif macintosh && !TYPE_LONGLONG #elif defined(macintosh) && !TYPE_LONGLONG
#include <Types.h> #include <Types.h>
typedef SInt64 SLONGLONG; typedef SInt64 SLONGLONG;
#endif
#else #else
typedef long long SLONGLONG; typedef long long SLONGLONG;
#endif #endif
typedef int __s64_typetest [(sizeof(SLONGLONG)==8) * 2 - 1];
/* pointer-sized signed int (ssize_t/intptr_t) : */
#if defined(_WIN64) /* win64 is LLP64, not LP64 */
typedef long long SINTPTR_T;
#else
/* long should be pointer-sized for all others : */
typedef long SINTPTR_T;
#endif
typedef int __iptr_typetest [(sizeof(SINTPTR_T)==sizeof(void*)) * 2 - 1];
/*========== Error handling */ /*========== Error handling */
@ -77,25 +95,28 @@ extern MikMod_handler_t _mm_errorhandler;
pthread_mutex_lock(&_mm_mutex_##name) pthread_mutex_lock(&_mm_mutex_##name)
#define MUTEX_UNLOCK(name) \ #define MUTEX_UNLOCK(name) \
pthread_mutex_unlock(&_mm_mutex_##name) pthread_mutex_unlock(&_mm_mutex_##name)
#elif defined(__OS2__)||defined(__EMX__) #elif defined(__OS2__)||defined(__EMX__)
#define DECLARE_MUTEX(name) \ #define DECLARE_MUTEX(name) \
extern HMTX _mm_mutex_##name extern HMTX _mm_mutex_##name
#define MUTEX_LOCK(name) \ #define MUTEX_LOCK(name) \
if(_mm_mutex_##name) \ if(_mm_mutex_##name)\
DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT) DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT)
#define MUTEX_UNLOCK(name) \ #define MUTEX_UNLOCK(name) \
if(_mm_mutex_##name) \ if(_mm_mutex_##name)\
DosReleaseMutexSem(_mm_mutex_##name) DosReleaseMutexSem(_mm_mutex_##name)
#elif defined(WIN32)
#elif defined(_WIN32)
#include <windows.h> #include <windows.h>
#define DECLARE_MUTEX(name) \ #define DECLARE_MUTEX(name) \
extern HANDLE _mm_mutex_##name extern HANDLE _mm_mutex_##name
#define MUTEX_LOCK(name) \ #define MUTEX_LOCK(name) \
if(_mm_mutex_##name) \ if(_mm_mutex_##name)\
WaitForSingleObject(_mm_mutex_##name,INFINITE) WaitForSingleObject(_mm_mutex_##name,INFINITE)
#define MUTEX_UNLOCK(name) \ #define MUTEX_UNLOCK(name) \
if(_mm_mutex_##name) \ if(_mm_mutex_##name)\
ReleaseMutex(_mm_mutex_##name) ReleaseMutex(_mm_mutex_##name)
#else #else
#define DECLARE_MUTEX(name) \ #define DECLARE_MUTEX(name) \
extern void *_mm_mutex_##name extern void *_mm_mutex_##name
@ -106,9 +127,13 @@ extern MikMod_handler_t _mm_errorhandler;
DECLARE_MUTEX(lists); DECLARE_MUTEX(lists);
DECLARE_MUTEX(vars); DECLARE_MUTEX(vars);
/*========== Replacement funcs */
//extern int strcasecmp (const char *__s1, const char *__s2);
/*========== Portable file I/O */ /*========== Portable file I/O */
extern MREADER* _mm_new_mem_reader(const void *buffer, int len); extern MREADER* _mm_new_mem_reader(const void *buffer, long len);
extern void _mm_delete_mem_reader(MREADER *reader); extern void _mm_delete_mem_reader(MREADER *reader);
extern MREADER* _mm_new_file_reader(int fp); extern MREADER* _mm_new_file_reader(int fp);
@ -117,16 +142,17 @@ extern void _mm_delete_file_reader(MREADER*);
extern MWRITER* _mm_new_file_writer(int fp); extern MWRITER* _mm_new_file_writer(int fp);
extern void _mm_delete_file_writer(MWRITER*); extern void _mm_delete_file_writer(MWRITER*);
extern int _mm_FileExists(CHAR *fname); extern int _mm_FileExists(const CHAR *fname);
#define _mm_write_SBYTE(x,y) y->Put(y,(int)x) #define _mm_write_SBYTE(x,y) y->Put(y,(int)x)
#define _mm_write_UBYTE(x,y) y->Put(y,(int)x) #define _mm_write_UBYTE(x,y) y->Put(y,(int)x)
#define _mm_read_SBYTE(x) (SBYTE)x->Get(x) #define _mm_read_SBYTE(x) (SBYTE)x->Get(x)
#define _mm_read_UBYTE(x) (UBYTE)x->Get(x) #define _mm_read_UBYTE(x) (UBYTE)x->Get(x)
#define _mm_skip_BYTE(x) (void)x->Get(x)
#define _mm_write_SBYTES(x,y,z) z->Write(z,(void *)x,y) #define _mm_write_SBYTES(x,y,z) z->Write(z,(const void *)x,y)
#define _mm_write_UBYTES(x,y,z) z->Write(z,(void *)x,y) #define _mm_write_UBYTES(x,y,z) z->Write(z,(const void *)x,y)
#define _mm_read_SBYTES(x,y,z) z->Read(z,(void *)x,y) #define _mm_read_SBYTES(x,y,z) z->Read(z,(void *)x,y)
#define _mm_read_UBYTES(x,y,z) z->Read(z,(void *)x,y) #define _mm_read_UBYTES(x,y,z) z->Read(z,(void *)x,y)
@ -138,11 +164,9 @@ extern int _mm_FileExists(CHAR *fname);
extern void _mm_iobase_setcur(MREADER*); extern void _mm_iobase_setcur(MREADER*);
extern void _mm_iobase_revert(MREADER*); extern void _mm_iobase_revert(MREADER*);
extern int _mm_fopen(CHAR*,CHAR*); extern int _mm_fopen(const CHAR *, const CHAR *);
extern int _mm_fclose(int); extern int _mm_fclose(int);
#if !defined(ROCKBOX) extern void _mm_write_string(const CHAR*,MWRITER*);
extern void _mm_write_string(CHAR*,MWRITER*);
#endif
extern int _mm_read_string (CHAR*,int,MREADER*); extern int _mm_read_string (CHAR*,int,MREADER*);
extern SWORD _mm_read_M_SWORD(MREADER*); extern SWORD _mm_read_M_SWORD(MREADER*);
@ -187,6 +211,8 @@ extern void _mm_write_I_ULONGS(ULONG*,int,MWRITER*);
/*========== Samples */ /*========== Samples */
#define MAX_SAMPLE_SIZE 0x10000000 /* a sane value guaranteed to not overflow an SLONG */
/* This is a handle of sorts attached to any sample registered with /* This is a handle of sorts attached to any sample registered with
SL_RegisterSample. Generally, this only need be used or changed by the SL_RegisterSample. Generally, this only need be used or changed by the
loaders and drivers of mikmod. */ loaders and drivers of mikmod. */
@ -306,16 +332,16 @@ enum {
UNI_ULTEFFECT9, /* Sample fine offset */ UNI_ULTEFFECT9, /* Sample fine offset */
/* OctaMED effects */ /* OctaMED effects */
UNI_MEDSPEED, UNI_MEDSPEED,
UNI_MEDEFFECTF1, /* play note twice */ UNI_MEDEFFECTF1,/* play note twice */
UNI_MEDEFFECTF2, /* delay note */ UNI_MEDEFFECTF2,/* delay note */
UNI_MEDEFFECTF3, /* play note three times */ UNI_MEDEFFECTF3,/* play note three times */
/* Oktalyzer effects */ /* Oktalyzer effects */
UNI_OKTARP, /* arpeggio */ UNI_OKTARP, /* arpeggio */
UNI_LAST UNI_LAST
}; };
extern UWORD unioperands[UNI_LAST]; extern const UWORD unioperands[UNI_LAST];
/* IT / S3M Extended SS effects: */ /* IT / S3M Extended SS effects: */
enum { enum {
@ -420,7 +446,7 @@ typedef struct ENVPR {
typedef struct MP_CHANNEL { typedef struct MP_CHANNEL {
INSTRUMENT* i; INSTRUMENT* i;
SAMPLE* s; SAMPLE *s;
UBYTE sample; /* which sample number */ UBYTE sample; /* which sample number */
UBYTE note; /* the audible note as heard, direct rep of period */ UBYTE note; /* the audible note as heard, direct rep of period */
SWORD outvolume; /* output volume (vol + sampcol + instvol) */ SWORD outvolume; /* output volume (vol + sampcol + instvol) */
@ -445,7 +471,7 @@ typedef struct MP_CHANNEL {
typedef struct MP_CONTROL { typedef struct MP_CONTROL {
struct MP_CHANNEL main; struct MP_CHANNEL main;
struct MP_VOICE *slave; /* Audio Slave of current effects control channel */ struct MP_VOICE* slave; /* Audio Slave of current effects control channel */
UBYTE slavechn; /* Audio Slave of current effects control channel */ UBYTE slavechn; /* Audio Slave of current effects control channel */
UBYTE muted; /* if set, channel not played */ UBYTE muted; /* if set, channel not played */
@ -463,7 +489,7 @@ typedef struct MP_CONTROL {
SWORD tmpvolume; /* tmp volume */ SWORD tmpvolume; /* tmp volume */
UWORD tmpperiod; /* tmp period */ UWORD tmpperiod; /* tmp period */
UWORD wantedperiod; /* period to slide to (with effect 3 or 5) */ UWORD wantedperiod;/* period to slide to (with effect 3 or 5) */
UBYTE arpmem; /* arpeggio command memory */ UBYTE arpmem; /* arpeggio command memory */
UBYTE pansspd; /* panslide speed */ UBYTE pansspd; /* panslide speed */
@ -472,10 +498,10 @@ typedef struct MP_CONTROL {
UBYTE s3mtremor; /* s3m tremor (effect I) counter */ UBYTE s3mtremor; /* s3m tremor (effect I) counter */
UBYTE s3mtronof; /* s3m tremor ontime/offtime */ UBYTE s3mtronof; /* s3m tremor ontime/offtime */
UBYTE s3mvolslide; /* last used volslide */ UBYTE s3mvolslide;/* last used volslide */
SBYTE sliding; SBYTE sliding;
UBYTE s3mrtgspeed; /* last used retrig speed */ UBYTE s3mrtgspeed;/* last used retrig speed */
UBYTE s3mrtgslide; /* last used retrig slide */ UBYTE s3mrtgslide;/* last used retrig slide */
UBYTE glissando; /* glissando (0 means off) */ UBYTE glissando; /* glissando (0 means off) */
UBYTE wavecontrol; UBYTE wavecontrol;
@ -492,15 +518,15 @@ typedef struct MP_CONTROL {
UBYTE fslidednspd; UBYTE fslidednspd;
UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */ UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */
UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */ UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */
UBYTE ffportupspd; /* fx X1 (extra fine portamento up) data */ UBYTE ffportupspd;/* fx X1 (extra fine portamento up) data */
UBYTE ffportdnspd; /* fx X2 (extra fine portamento dn) data */ UBYTE ffportdnspd;/* fx X2 (extra fine portamento dn) data */
ULONG hioffset; /* last used high order of sample offset */ ULONG hioffset; /* last used high order of sample offset */
UWORD soffset; /* last used low order of sample-offset (effect 9) */ UWORD soffset; /* last used low order of sample-offset (effect 9) */
UBYTE sseffect; /* last used Sxx effect */ UBYTE sseffect; /* last used Sxx effect */
UBYTE ssdata; /* last used Sxx data info */ UBYTE ssdata; /* last used Sxx data info */
UBYTE chanvolslide; /* last used channel volume slide */ UBYTE chanvolslide;/* last used channel volume slide */
UBYTE panbwave; /* current panbrello waveform */ UBYTE panbwave; /* current panbrello waveform */
UBYTE panbpos; /* current panbrello position */ UBYTE panbpos; /* current panbrello position */
@ -539,9 +565,9 @@ typedef struct MP_VOICE {
/*========== Loaders */ /*========== Loaders */
typedef struct MLOADER { typedef struct MLOADER {
struct MLOADER* next; struct MLOADER* next;
CHAR* type; const CHAR* type;
CHAR* version; const CHAR* version;
int (*Init)(void); int (*Init)(void);
int (*Test)(void); int (*Test)(void);
int (*Load)(int); int (*Load)(int);
@ -551,9 +577,9 @@ struct MLOADER* next;
/* internal loader variables */ /* internal loader variables */
extern MREADER* modreader; extern MREADER* modreader;
extern UWORD finetune[16];
extern MODULE of; /* static unimod loading space */ extern MODULE of; /* static unimod loading space */
extern UWORD npertab[7*OCTAVE]; /* used by the original MOD loaders */ extern const UWORD finetune[16];
extern const UWORD npertab[7*OCTAVE];/* used by the original MOD loaders */
extern SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */ extern SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */
extern UBYTE* poslookup; /* lookup table for pattern jumps after extern UBYTE* poslookup; /* lookup table for pattern jumps after
@ -577,8 +603,7 @@ extern int AllocPatterns(void);
extern int AllocTracks(void); extern int AllocTracks(void);
extern int AllocInstruments(void); extern int AllocInstruments(void);
extern int AllocSamples(void); extern int AllocSamples(void);
extern CHAR* DupStr(CHAR*,UWORD,int); extern CHAR* DupStr(const CHAR*, UWORD, int);
extern CHAR* StrDup(CHAR *s);
/* loader utility functions */ /* loader utility functions */
extern int* AllocLinear(void); extern int* AllocLinear(void);
@ -598,7 +623,7 @@ extern ULONG getfrequency(UWORD,ULONG);
/* loader shared data */ /* loader shared data */
#define STM_NTRACKERS 3 #define STM_NTRACKERS 3
extern CHAR *STM_Signatures[STM_NTRACKERS]; extern const CHAR *STM_Signatures[STM_NTRACKERS];
/*========== Player interface */ /*========== Player interface */
@ -606,6 +631,16 @@ extern int Player_Init(MODULE*);
extern void Player_Exit(MODULE*); extern void Player_Exit(MODULE*);
extern void Player_HandleTick(void); extern void Player_HandleTick(void);
/*========== UnPackers */
typedef int (*MUNPACKER) (struct MREADER*,
void** /* unpacked data out */ ,
long* /* unpacked data size */ );
extern int PP20_Unpack(MREADER*, void**, long*);
extern int MMCMP_Unpack(MREADER*, void**, long*);
extern int XPK_Unpack(MREADER*, void**, long*);
extern int S404_Unpack(MREADER*, void**, long*);
/*========== Drivers */ /*========== Drivers */
/* max. number of handles a driver has to provide. (not strict) */ /* max. number of handles a driver has to provide. (not strict) */
@ -625,7 +660,7 @@ extern UBYTE md_softchn; /* number of software mixed voices */
/* This is for use by the hardware drivers only. It points to the registered /* This is for use by the hardware drivers only. It points to the registered
tickhandler function. */ tickhandler function. */
extern void (*md_player)(void); extern MikMod_player_t md_player;
extern SWORD MD_SampleLoad(SAMPLOAD*,int); extern SWORD MD_SampleLoad(SAMPLOAD*,int);
extern void MD_SampleUnload(SWORD); extern void MD_SampleUnload(SWORD);
@ -636,16 +671,16 @@ extern ULONG MD_SampleLength(int,SAMPLE*);
extern void unsignedtoulaw(char *,int); extern void unsignedtoulaw(char *,int);
/* Parameter extraction helper */ /* Parameter extraction helper */
extern CHAR *MD_GetAtom(CHAR*,CHAR*,int); extern CHAR *MD_GetAtom(const CHAR*, const CHAR*, int);
/* Internal software mixer stuff */ /* Internal software mixer stuff */
extern void VC_SetupPointers(void); extern void VC_SetupPointers(void);
extern int VC1_Init(void); extern int VC1_Init(void);
extern int VC2_Init(void); extern int VC2_Init(void);
#if defined(unix) || defined(__APPLE__) && defined(__MACH__) #if (MIKMOD_UNIX)
/* POSIX helper functions */ /* POSIX helper functions */
extern int MD_Access(CHAR *); extern int MD_Access(const CHAR *);
extern int MD_DropPrivileges(void); extern int MD_DropPrivileges(void);
#endif #endif
@ -673,6 +708,15 @@ extern void Voice_SetVolume_internal(SBYTE,UWORD);
extern void Voice_Stop_internal(SBYTE); extern void Voice_Stop_internal(SBYTE);
extern int Voice_Stopped_internal(SBYTE); extern int Voice_Stopped_internal(SBYTE);
extern int VC1_PlayStart(void);
extern int VC2_PlayStart(void);
extern void VC1_PlayStop(void);
extern void VC2_PlayStop(void);
extern int VC1_SetNumVoices(void);
extern int VC2_SetNumVoices(void);
extern MikMod_callback_t vc_callback;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -680,30 +724,36 @@ extern int Voice_Stopped_internal(SBYTE);
/*========== SIMD mixing routines */ /*========== SIMD mixing routines */
#undef HAVE_ALTIVEC #undef HAVE_ALTIVEC
#undef HAVE_SSE2 #undef HAVE_SSE2
#if defined(MIKMOD_SIMD)
#if defined(__APPLE__) && !defined (__i386__) #if (defined(__ppc__) || defined(__ppc64__)) && defined(__VEC__) && !(defined(__GNUC__) && (__GNUC__ < 3))
#if defined __VEC__ && !(defined(__GNUC__) && (__GNUC__ < 3))
#define HAVE_ALTIVEC #define HAVE_ALTIVEC
#endif // __VEC__
#elif defined WIN32 || defined __WIN64 || (defined __APPLE__ && defined (__i386__) && defined __VEC__) #elif defined(__GNUC__) && defined(__SSE2__) /* x86 / x86_64 */
// FIXME: emmintrin.h requires VC6 processor pack or VC2003+
#define HAVE_SSE2 #define HAVE_SSE2
/* Fixes couples warnings */ #elif defined(_MSC_VER) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64))
#ifdef _MSC_VER /* FIXME: emmintrin.h requires VC6 processor pack or VC2003+ */
#define HAVE_SSE2
/* avoid some warnings */
#pragma warning(disable:4761) #pragma warning(disable:4761)
#pragma warning(disable:4391) #pragma warning(disable:4391)
#pragma warning(disable:4244) #pragma warning(disable:4244)
#endif
#endif #endif /* AltiVec/SSE2 */
// TODO: Test for GCC Linux #endif /* MIKMOD_SIMD */
/*========== SIMD mixing helper functions =============*/ /*========== SIMD mixing helper functions =============*/
#define IS_ALIGNED_16(ptr) (!(((intptr_t)(ptr)) & 15)) #if defined(_WIN64)
# if defined(_MSC_VER)
# define IS_ALIGNED_16(ptr) (!((__int64)(ptr) & 15i64))
# else /* GCC, LCC, .. */
# define IS_ALIGNED_16(ptr) (!((long long)(ptr) & 15LL))
# endif
#else /* long cast should be OK for all else */
#define IS_ALIGNED_16(ptr) (!((long)(ptr) & 15L))
#endif
/* Altivec helper function */ /* Altivec helper function */
#if defined HAVE_ALTIVEC #if defined HAVE_ALTIVEC
@ -715,29 +765,25 @@ extern int Voice_Stopped_internal(SBYTE);
#include <ppc_intrinsics.h> #include <ppc_intrinsics.h>
#endif #endif
// Helper functions /* Helper functions */
// Set single float across the four values /* Set single float across the four values */
static inline vector float vec_mul( const vector float a, const vector float b) static inline vector float vec_mul(const vector float a, const vector float b) {
{
return vec_madd(a, b, (const vector float)(0.f)); return vec_madd(a, b, (const vector float)(0.f));
} }
// Set single float across the four values /* Set single float across the four values */
static inline vector float vec_load_ps1(const float *pF ) static inline vector float vec_load_ps1(const float *pF) {
{
vector float data = vec_lde(0, pF); vector float data = vec_lde(0, pF);
return vec_splat(vec_perm(data, data, vec_lvsl(0, pF)), 0); return vec_splat(vec_perm(data, data, vec_lvsl(0, pF)), 0);
} }
// Set vector to 0 /* Set vector to 0 */
static inline const vector float vec_setzero() static inline vector float vec_setzero() {
{ return (vector float) (0.);
return (const vector float) (0.);
} }
static inline vector signed char vec_set1_8(unsigned char splatchar) static inline vector signed char vec_set1_8(unsigned char splatchar) {
{
vector unsigned char splatmap = vec_lvsl(0, &splatchar); vector unsigned char splatmap = vec_lvsl(0, &splatchar);
vector unsigned char result = vec_lde(0, &splatchar); vector unsigned char result = vec_lde(0, &splatchar);
splatmap = vec_splat(splatmap, 0); splatmap = vec_splat(splatmap, 0);
@ -753,24 +799,22 @@ static inline vector signed char vec_set1_8(unsigned char splatchar)
#define PERM_B2 0x18,0x19,0x1A,0x1B #define PERM_B2 0x18,0x19,0x1A,0x1B
#define PERM_B3 0x1C,0x1D,0x1E,0x1F #define PERM_B3 0x1C,0x1D,0x1E,0x1F
// Equivalent to _mm_unpacklo_epi32 /* Equivalent to _mm_unpacklo_epi32 */
static inline vector signed int vec_unpacklo(vector signed int a, vector signed int b) static inline vector signed int vec_unpacklo(vector signed int a, vector signed int b) {
{
return vec_perm(a, b, (vector unsigned char)(PERM_A0,PERM_A1,PERM_B0,PERM_B1)); return vec_perm(a, b, (vector unsigned char)(PERM_A0,PERM_A1,PERM_B0,PERM_B1));
} }
// Equivalent to _mm_srli_si128(a, 8) (without the zeroing in high part). /* Equivalent to _mm_srli_si128(a, 8) (without the zeroing in high part). */
static inline vector signed int vec_hiqq(vector signed int a) static inline vector signed int vec_hiqq(vector signed int a) {
{
vector signed int b = vec_splat_s32(0); vector signed int b = vec_splat_s32(0);
return vec_perm(a, b, (vector unsigned char)(PERM_A2,PERM_A3,PERM_B2,PERM_B3)); return vec_perm(a, b, (vector unsigned char)(PERM_A2,PERM_A3,PERM_B2,PERM_B3));
} }
// vec_sra is max +15. We have to do in two times ... /* vec_sra is max +15. We have to do in two times ... */
#define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = vec_mul(vec_ctf(vec_sra(vec_ld(0, (vector signed int*)(srce)), vec_splat_u32(BITSHIFT-size)),0), mul); #define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = vec_mul(vec_ctf(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(BITSHIFT-size)),0), mul);
#define EXTRACT_SAMPLE_SIMD_0(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int*)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-0)); #define EXTRACT_SAMPLE_SIMD_0(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-0));
#define EXTRACT_SAMPLE_SIMD_8(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int*)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-8)); #define EXTRACT_SAMPLE_SIMD_8(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-8));
#define EXTRACT_SAMPLE_SIMD_16(srce, var) var = vec_sra(vec_ld(0, (vector signed int*)(srce)), vec_splat_u32(BITSHIFT+16-16)); #define EXTRACT_SAMPLE_SIMD_16(srce, var) var = vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(BITSHIFT+16-16));
#define PUT_SAMPLE_SIMD_W(dste, v1, v2) vec_st(vec_packs(v1, v2), 0, dste); #define PUT_SAMPLE_SIMD_W(dste, v1, v2) vec_st(vec_packs(v1, v2), 0, dste);
#define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) vec_st(vec_add(vec_packs((vector signed short)vec_packs(v1, v2), (vector signed short)vec_packs(v3, v4)), vec_set1_8(128)), 0, dste); #define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) vec_st(vec_add(vec_packs((vector signed short)vec_packs(v1, v2), (vector signed short)vec_packs(v3, v4)), vec_set1_8(128)), 0, dste);
#define PUT_SAMPLE_SIMD_F(dste, v1) vec_st(v1, 0, dste); #define PUT_SAMPLE_SIMD_F(dste, v1) vec_st(v1, 0, dste);
@ -778,18 +822,17 @@ static inline vector signed int vec_hiqq(vector signed int a)
#elif defined HAVE_SSE2 #elif defined HAVE_SSE2
/* SSE2 helper function */
#include <emmintrin.h> #include <emmintrin.h>
static __inline __m128i mm_hiqq(const __m128i a) /* SSE2 helper function */
{
return _mm_srli_si128(a, 8); // get the 64bit upper part. new 64bit upper is undefined (zeroed is fine). static __inline __m128i mm_hiqq(const __m128i a) {
return _mm_srli_si128(a, 8); /* get the 64bit upper part. new 64bit upper is undefined (zeroed is fine). */
} }
/* 128-bit mixing macros */ /* 128-bit mixing macros */
#define EXTRACT_SAMPLE_SIMD(srce, var, size) var = _mm_srai_epi32(_mm_load_si128((__m128i*)(srce)), BITSHIFT+16-size); #define EXTRACT_SAMPLE_SIMD(srce, var, size) var = _mm_srai_epi32(_mm_load_si128((__m128i const *)(srce)), BITSHIFT+16-size);
#define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = _mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_load_si128((__m128i*)(srce)), BITSHIFT-size)), mul); #define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = _mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_load_si128((__m128i const *)(srce)), BITSHIFT-size)), mul);
#define EXTRACT_SAMPLE_SIMD_0(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 0) #define EXTRACT_SAMPLE_SIMD_0(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 0)
#define EXTRACT_SAMPLE_SIMD_8(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 8) #define EXTRACT_SAMPLE_SIMD_8(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 8)
#define EXTRACT_SAMPLE_SIMD_16(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 16) #define EXTRACT_SAMPLE_SIMD_16(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 16)
@ -802,7 +845,25 @@ static __inline __m128i mm_hiqq(const __m128i a)
#endif #endif
#if defined(HAVE_SSE2) || defined(HAVE_ALTIVEC)
/* MikMod_amalloc() returns a 16 byte aligned zero-filled
memory in SIMD-enabled builds.
- the returned memory can be freed with MikMod_afree()
- the returned memory CAN NOT be realloc()'ed safely. */
#ifdef __cplusplus
extern "C" {
#endif
void* MikMod_amalloc(size_t);
void MikMod_afree(void *); /* frees if ptr != NULL */
#ifdef __cplusplus
}
#endif #endif
#else /* NO SIMD */
#define MikMod_amalloc MikMod_malloc
#define MikMod_afree MikMod_free
#endif
#endif /* _MIKMOD_INTERNALS_H */
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -8,6 +8,9 @@
#undef WIN32 #undef WIN32
#define NO_DEPACKERS // We don't support these
//#define NO_HQMIXER // We don't have the oomph
#ifndef NO_MMSUPP_DEFINES #ifndef NO_MMSUPP_DEFINES
#define snprintf(...) rb->snprintf(__VA_ARGS__) #define snprintf(...) rb->snprintf(__VA_ARGS__)
#define fdprintf(...) rb->fdprintf(__VA_ARGS__) #define fdprintf(...) rb->fdprintf(__VA_ARGS__)

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: mloader.c,v 1.3 2005/04/07 19:57:39 realtech Exp $ $Id$
These routines are used to access the available module loaders These routines are used to access the available module loaders
@ -50,7 +50,17 @@ MODULE of;
static MLOADER *firstloader=NULL; static MLOADER *firstloader=NULL;
UWORD finetune[16]={ #ifndef NO_DEPACKERS
static MUNPACKER unpackers[] = {
PP20_Unpack,
MMCMP_Unpack,
XPK_Unpack,
S404_Unpack,
NULL
};
#endif
const UWORD finetune[16] = {
8363,8413,8463,8529,8581,8651,8723,8757, 8363,8413,8463,8529,8581,8651,8723,8757,
7895,7941,7985,8046,8107,8169,8232,8280 7895,7941,7985,8046,8107,8169,8232,8280
}; };
@ -63,14 +73,17 @@ MIKMODAPI CHAR* MikMod_InfoLoader(void)
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
/* compute size of buffer */ /* compute size of buffer */
for(l=firstloader;l;l=l->next) len+=1+(l->next?1:0)+strlen(l->version); for(l = firstloader; l; l = l->next)
len += 1 + (l->next ? 1 : 0) + strlen(l->version);
if(len) if(len)
if((list=MikMod_malloc(len*sizeof(CHAR)))) { if((list=(CHAR*)MikMod_malloc(len*sizeof(CHAR))) != NULL) {
list[0]=0; CHAR *list_end = list;
list[0] = 0;
/* list all registered module loders */ /* list all registered module loders */
for(l=firstloader;l;l=l->next) for(l = firstloader; l; l = l->next) {
sprintf(list,(l->next)?"%s%s\n":"%s%s",list,l->version); list_end += sprintf(list_end, "%s%s", l->version, (l->next) ? "\n" : "");
}
} }
MUTEX_UNLOCK(lists); MUTEX_UNLOCK(lists);
return list; return list;
@ -122,44 +135,44 @@ int ReadComment(UWORD len)
int ReadLinedComment(UWORD len,UWORD linelen) int ReadLinedComment(UWORD len,UWORD linelen)
{ {
CHAR *tempcomment,*line,*storage; /* Adapted from the OpenMPT project, C'ified. */
UWORD total=0,t,lines; CHAR *buf, *storage, *p;
int i; size_t numlines, line, fpos, cpos, lpos, cnt;
lines = (len + linelen - 1) / linelen; if (!linelen) return 0;
if (len) { if (!len) return 1;
if(!(tempcomment=(CHAR*)MikMod_malloc(len+1))) return 0;
if(!(storage=(CHAR*)MikMod_malloc(linelen+1))) {
MikMod_free(tempcomment);
return 0;
}
memset(tempcomment, ' ', len);
_mm_read_UBYTES(tempcomment,len,modreader);
/* compute message length */ if (!(buf = (CHAR *) MikMod_malloc(len))) return 0;
for(line=tempcomment,total=t=0;t<lines;t++,line+=linelen) { numlines = (len + linelen - 1) / linelen;
for(i=linelen;(i>=0)&&(line[i]==' ');i--) line[i]=0; cnt = (linelen + 1) * numlines;
for(i=0;i<linelen;i++) if (!line[i]) break; if (!(storage = (CHAR *) MikMod_malloc(cnt + 1))) {
total+=1+i; MikMod_free(buf);
}
if(total>lines) {
if(!(of.comment=(CHAR*)MikMod_malloc(total+1))) {
MikMod_free(storage);
MikMod_free(tempcomment);
return 0; return 0;
} }
/* convert message */ _mm_read_UBYTES(buf,len,modreader);
for(line=tempcomment,t=0;t<lines;t++,line+=linelen) { storage[cnt] = 0;
for(i=0;i<linelen;i++) if(!(storage[i]=line[i])) break; for (line = 0, fpos = 0, cpos = 0; line < numlines; line++, fpos += linelen, cpos += (linelen + 1))
storage[i]=0; /* if (i==linelen) */ {
strcat(of.comment,storage);strcat(of.comment,"\r"); cnt = len - fpos;
} if (cnt > linelen) cnt = linelen;
MikMod_free(storage); p = storage + cpos;
MikMod_free(tempcomment); memcpy(p, buf + fpos, cnt);
p[cnt] = '\r';
/* fix weird chars */
for (lpos = 0; lpos < linelen; lpos++, p++) {
switch (*p) {
case '\0':
case '\n':
case '\r':
*p = ' ';
break;
} }
} }
}
of.comment = storage;
MikMod_free(buf);
return 1; return 1;
} }
@ -169,7 +182,7 @@ int AllocPositions(int total)
_mm_errno=MMERR_NOT_A_MODULE; _mm_errno=MMERR_NOT_A_MODULE;
return 0; return 0;
} }
if(!(of.positions=MikMod_calloc(total,sizeof(UWORD)))) return 0; if(!(of.positions=(UWORD*)MikMod_calloc(total,sizeof(UWORD)))) return 0;
return 1; return 1;
} }
@ -258,7 +271,7 @@ static int ML_LoadSamples(void)
/* Creates a CSTR out of a character buffer of 'len' bytes, but strips any /* Creates a CSTR out of a character buffer of 'len' bytes, but strips any
terminating non-printing characters like 0, spaces etc. */ terminating non-printing characters like 0, spaces etc. */
CHAR *DupStr(CHAR* s,UWORD len,int strict) CHAR *DupStr(const CHAR* s, UWORD len, int strict)
{ {
UWORD t; UWORD t;
CHAR *d=NULL; CHAR *d=NULL;
@ -277,48 +290,42 @@ CHAR *DupStr(CHAR* s,UWORD len,int strict)
/* When the buffer wasn't completely empty, allocate a cstring and copy the /* When the buffer wasn't completely empty, allocate a cstring and copy the
buffer into that string, except for any control-chars */ buffer into that string, except for any control-chars */
if((d=(CHAR*)MikMod_malloc(sizeof(CHAR)*(len+1)))) { if((d=(CHAR*)MikMod_malloc(sizeof(CHAR)*(len+1))) != NULL) {
for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t]; for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t];
d[len]=0; d[len]=0;
} }
return d; return d;
} }
CHAR *StrDup(CHAR *s)
{
size_t l = strlen(s) + 1;
CHAR *d = MikMod_malloc(l);
strcpy(d, s);
return d;
}
static void ML_XFreeSample(SAMPLE *s) static void ML_XFreeSample(SAMPLE *s)
{ {
if(s->handle>=0) if(s->handle>=0)
MD_SampleUnload(s->handle); MD_SampleUnload(s->handle);
if(s->samplename) MikMod_free(s->samplename);
/* moved samplename freeing to our caller ML_FreeEx(),
* because we are called conditionally. */
} }
static void ML_XFreeInstrument(INSTRUMENT *i) static void ML_XFreeInstrument(INSTRUMENT *i)
{ {
if(i->insname) MikMod_free(i->insname); MikMod_free(i->insname);
} }
static void ML_FreeEx(MODULE *mf) static void ML_FreeEx(MODULE *mf)
{ {
UWORD t; UWORD t;
if(mf->songname) MikMod_free(mf->songname); MikMod_free(mf->songname);
if(mf->comment) MikMod_free(mf->comment); MikMod_free(mf->comment);
if(mf->modtype) MikMod_free(mf->modtype); MikMod_free(mf->modtype);
if(mf->positions) MikMod_free(mf->positions); MikMod_free(mf->positions);
if(mf->patterns) MikMod_free(mf->patterns); MikMod_free(mf->patterns);
if(mf->pattrows) MikMod_free(mf->pattrows); MikMod_free(mf->pattrows);
if(mf->tracks) { if(mf->tracks) {
for(t=0;t<mf->numtrk;t++) for(t=0;t<mf->numtrk;t++)
if(mf->tracks[t]) MikMod_free(mf->tracks[t]); MikMod_free(mf->tracks[t]);
MikMod_free(mf->tracks); MikMod_free(mf->tracks);
} }
if(mf->instruments) { if(mf->instruments) {
@ -327,8 +334,10 @@ static void ML_FreeEx(MODULE *mf)
MikMod_free(mf->instruments); MikMod_free(mf->instruments);
} }
if(mf->samples) { if(mf->samples) {
for(t=0;t<mf->numsmp;t++) for(t=0;t<mf->numsmp;t++) {
MikMod_free(mf->samples[t].samplename);
if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]); if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]);
}
MikMod_free(mf->samples); MikMod_free(mf->samples);
} }
memset(mf,0,sizeof(MODULE)); memset(mf,0,sizeof(MODULE));
@ -337,11 +346,25 @@ static void ML_FreeEx(MODULE *mf)
static MODULE *ML_AllocUniMod(void) static MODULE *ML_AllocUniMod(void)
{ {
MODULE *mf; return (MODULE *) MikMod_malloc(sizeof(MODULE));
return (mf=MikMod_malloc(sizeof(MODULE)));
} }
#ifndef NO_DEPACKERS
static int ML_TryUnpack(MREADER *reader,void **out,long *outlen)
{
int i;
*out = NULL;
*outlen = 0;
for(i=0;unpackers[i]!=NULL;++i) {
_mm_rewind(reader);
if(unpackers[i](reader,out,outlen)) return 1;
}
return 0;
}
#endif
static void Player_Free_internal(MODULE *mf) static void Player_Free_internal(MODULE *mf)
{ {
if(mf) { if(mf) {
@ -360,25 +383,50 @@ MIKMODAPI void Player_Free(MODULE *mf)
static CHAR* Player_LoadTitle_internal(MREADER *reader) static CHAR* Player_LoadTitle_internal(MREADER *reader)
{ {
MLOADER *l; MLOADER *l;
CHAR *title;
#ifndef NO_DEPACKERS
void *unpk;
long newlen;
#endif
modreader=reader; modreader=reader;
_mm_errno = 0; _mm_errno = 0;
_mm_critical = 0; _mm_critical = 0;
_mm_iobase_setcur(modreader); _mm_iobase_setcur(modreader);
#ifndef NO_DEPACKERS
if(ML_TryUnpack(modreader,&unpk,&newlen)) {
if(!(modreader=_mm_new_mem_reader(unpk,newlen))) {
modreader=reader;
MikMod_free(unpk);
return NULL;
}
}
#endif
/* Try to find a loader that recognizes the module */ /* Try to find a loader that recognizes the module */
for(l=firstloader;l;l=l->next) { for(l=firstloader;l;l=l->next) {
_mm_rewind(modreader); _mm_rewind(modreader);
if(l->Test()) break; if(l->Test()) break;
} }
if(!l) { if(l) {
title = l->LoadTitle();
}
else {
_mm_errno = MMERR_NOT_A_MODULE; _mm_errno = MMERR_NOT_A_MODULE;
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
return NULL; title = NULL;
} }
return l->LoadTitle(); #ifndef NO_DEPACKERS
if (modreader!=reader) {
_mm_delete_mem_reader(modreader);
modreader=reader;
MikMod_free(unpk);
}
#endif
return title;
} }
MIKMODAPI CHAR* Player_LoadTitleFP(int fp) MIKMODAPI CHAR* Player_LoadTitleFP(int fp)
@ -386,7 +434,7 @@ MIKMODAPI CHAR* Player_LoadTitleFP(int fp)
CHAR* result=NULL; CHAR* result=NULL;
MREADER* reader; MREADER* reader;
if(fp && (reader=_mm_new_file_reader(fp))) { if(fp && (reader=_mm_new_file_reader(fp)) != NULL) {
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
result=Player_LoadTitle_internal(reader); result=Player_LoadTitle_internal(reader);
MUTEX_UNLOCK(lists); MUTEX_UNLOCK(lists);
@ -400,7 +448,8 @@ MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len)
CHAR *result=NULL; CHAR *result=NULL;
MREADER* reader; MREADER* reader;
if ((reader=_mm_new_mem_reader(buffer,len))) if (!buffer || len <= 0) return NULL;
if ((reader=_mm_new_mem_reader(buffer,len)) != NULL)
{ {
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
result=Player_LoadTitle_internal(reader); result=Player_LoadTitle_internal(reader);
@ -408,7 +457,6 @@ MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len)
_mm_delete_mem_reader(reader); _mm_delete_mem_reader(reader);
} }
return result; return result;
} }
@ -424,14 +472,14 @@ MIKMODAPI CHAR* Player_LoadTitleGeneric(MREADER *reader)
return result; return result;
} }
MIKMODAPI CHAR* Player_LoadTitle(CHAR* filename) MIKMODAPI CHAR* Player_LoadTitle(const CHAR* filename)
{ {
CHAR* result=NULL; CHAR* result=NULL;
int fp; int fp;
MREADER* reader; MREADER* reader;
if((fp=_mm_fopen(filename,"rb"))) { if((fp=_mm_fopen(filename,"rb")) >= 0) {
if((reader=_mm_new_file_reader(fp))) { if((reader=_mm_new_file_reader(fp)) != NULL) {
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
result=Player_LoadTitle_internal(reader); result=Player_LoadTitle_internal(reader);
MUTEX_UNLOCK(lists); MUTEX_UNLOCK(lists);
@ -449,12 +497,26 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio
MLOADER *l; MLOADER *l;
int ok; int ok;
MODULE *mf; MODULE *mf;
#ifndef NO_DEPACKERS
void *unpk;
long newlen;
#endif
modreader = reader; modreader = reader;
_mm_errno = 0; _mm_errno = 0;
_mm_critical = 0; _mm_critical = 0;
_mm_iobase_setcur(modreader); _mm_iobase_setcur(modreader);
#ifndef NO_DEPACKERS
if(ML_TryUnpack(modreader,&unpk,&newlen)) {
if(!(modreader=_mm_new_mem_reader(unpk,newlen))) {
modreader=reader;
MikMod_free(unpk);
return NULL;
}
}
#endif
/* Try to find a loader that recognizes the module */ /* Try to find a loader that recognizes the module */
for(l=firstloader;l;l=l->next) { for(l=firstloader;l;l=l->next) {
_mm_rewind(modreader); _mm_rewind(modreader);
@ -463,15 +525,31 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio
if(!l) { if(!l) {
_mm_errno = MMERR_NOT_A_MODULE; _mm_errno = MMERR_NOT_A_MODULE;
#ifndef NO_DEPACKERS
if(modreader!=reader) {
_mm_delete_mem_reader(modreader);
modreader=reader;
MikMod_free(unpk);
}
#endif
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
_mm_rewind(modreader);_mm_iobase_revert(modreader); _mm_rewind(modreader);
_mm_iobase_revert(modreader);
return NULL; return NULL;
} }
/* init unitrk routines */ /* init unitrk routines */
if(!UniInit()) { if(!UniInit()) {
#ifndef NO_DEPACKERS
if(modreader!=reader) {
_mm_delete_mem_reader(modreader);
modreader=reader;
MikMod_free(unpk);
}
#endif
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
_mm_rewind(modreader);_mm_iobase_revert(modreader); _mm_rewind(modreader);
_mm_iobase_revert(modreader);
return NULL; return NULL;
} }
@ -500,24 +578,20 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio
if (l->Cleanup) l->Cleanup(); if (l->Cleanup) l->Cleanup();
UniCleanup(); UniCleanup();
if(ok) ok = ML_LoadSamples();
if(ok) ok = ((mf=ML_AllocUniMod()) != NULL);
if(!ok) { if(!ok) {
ML_FreeEx(&of); ML_FreeEx(&of);
if(_mm_errorhandler) _mm_errorhandler(); #ifndef NO_DEPACKERS
_mm_rewind(modreader);_mm_iobase_revert(modreader); if(modreader!=reader) {
return NULL; _mm_delete_mem_reader(modreader);
modreader=reader;
MikMod_free(unpk);
} }
#endif
if(!ML_LoadSamples()) {
ML_FreeEx(&of);
if(_mm_errorhandler) _mm_errorhandler();
_mm_rewind(modreader);_mm_iobase_revert(modreader);
return NULL;
}
if(!(mf=ML_AllocUniMod())) {
ML_FreeEx(&of);
_mm_rewind(modreader);_mm_iobase_revert(modreader);
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
_mm_rewind(modreader);
_mm_iobase_revert(modreader);
return NULL; return NULL;
} }
@ -539,23 +613,25 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio
if(maxchan<mf->numchn) mf->flags |= UF_NNA; if(maxchan<mf->numchn) mf->flags |= UF_NNA;
if(MikMod_SetNumVoices_internal(maxchan,-1)) { ok = !MikMod_SetNumVoices_internal(maxchan,-1);
_mm_iobase_revert(modreader);
Player_Free(mf);
return NULL;
} }
if(ok) ok = !SL_LoadSamples();
if(ok) ok = !Player_Init(mf);
#ifndef NO_DEPACKERS
if(modreader!=reader) {
_mm_delete_mem_reader(modreader);
modreader=reader;
MikMod_free(unpk);
} }
if(SL_LoadSamples()) { #endif
_mm_iobase_revert(modreader); _mm_iobase_revert(modreader);
if(!ok) {
Player_Free_internal(mf); Player_Free_internal(mf);
return NULL; return NULL;
} }
if(Player_Init(mf)) {
_mm_iobase_revert(modreader);
Player_Free_internal(mf);
mf=NULL;
}
_mm_iobase_revert(modreader);
return mf; return mf;
} }
@ -577,7 +653,8 @@ MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,int curi
MODULE* result=NULL; MODULE* result=NULL;
MREADER* reader; MREADER* reader;
if ((reader=_mm_new_mem_reader(buffer, len))) { if (!buffer || len <= 0) return NULL;
if ((reader=_mm_new_mem_reader(buffer, len)) != NULL) {
result=Player_LoadGeneric(reader,maxchan,curious); result=Player_LoadGeneric(reader,maxchan,curious);
_mm_delete_mem_reader(reader); _mm_delete_mem_reader(reader);
} }
@ -589,9 +666,9 @@ MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,int curi
MIKMODAPI MODULE* Player_LoadFP(int fp,int maxchan,int curious) MIKMODAPI MODULE* Player_LoadFP(int fp,int maxchan,int curious)
{ {
MODULE* result=NULL; MODULE* result=NULL;
struct MREADER* reader=_mm_new_file_reader (fp); struct MREADER* reader;
if (reader) { if (fp && (reader=_mm_new_file_reader(fp)) != NULL) {
result=Player_LoadGeneric(reader,maxchan,curious); result=Player_LoadGeneric(reader,maxchan,curious);
_mm_delete_file_reader(reader); _mm_delete_file_reader(reader);
} }
@ -600,12 +677,12 @@ MIKMODAPI MODULE* Player_LoadFP(int fp,int maxchan,int curious)
/* Open a module via its filename. The loader will initialize the specified /* Open a module via its filename. The loader will initialize the specified
song-player 'player'. */ song-player 'player'. */
MIKMODAPI MODULE* Player_Load(CHAR* filename,int maxchan,int curious) MIKMODAPI MODULE* Player_Load(const CHAR* filename,int maxchan,int curious)
{ {
int fp; int fp;
MODULE *mf=NULL; MODULE *mf=NULL;
if((fp=_mm_fopen(filename,"rb"))) { if((fp=_mm_fopen(filename,"rb")) >= 0) {
mf=Player_LoadFP(fp,maxchan,curious); mf=Player_LoadFP(fp,maxchan,curious);
_mm_fclose(fp); _mm_fclose(fp);
} }

View file

@ -40,7 +40,7 @@ static void MikMod_RegisterAllLoaders_internal(void)
_mm_registerloader(&load_dsm); _mm_registerloader(&load_dsm);
_mm_registerloader(&load_far); _mm_registerloader(&load_far);
_mm_registerloader(&load_gdm); _mm_registerloader(&load_gdm);
_mm_registerloader(&load_gt2); /* _mm_registerloader(&load_gt2);*/ /* load_gt2 isn't complete */
_mm_registerloader(&load_it); _mm_registerloader(&load_it);
_mm_registerloader(&load_imf); _mm_registerloader(&load_imf);
_mm_registerloader(&load_mod); _mm_registerloader(&load_mod);
@ -51,13 +51,14 @@ static void MikMod_RegisterAllLoaders_internal(void)
_mm_registerloader(&load_stm); _mm_registerloader(&load_stm);
_mm_registerloader(&load_stx); _mm_registerloader(&load_stx);
_mm_registerloader(&load_ult); _mm_registerloader(&load_ult);
_mm_registerloader(&load_umx);
_mm_registerloader(&load_uni); _mm_registerloader(&load_uni);
_mm_registerloader(&load_xm); _mm_registerloader(&load_xm);
_mm_registerloader(&load_m15); _mm_registerloader(&load_m15);
} }
void MikMod_RegisterAllLoaders(void) MIKMODAPI void MikMod_RegisterAllLoaders(void)
{ {
MUTEX_LOCK(lists); MUTEX_LOCK(lists);
MikMod_RegisterAllLoaders_internal(); MikMod_RegisterAllLoaders_internal();

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: mlutil.c,v 1.3 2007/12/06 17:43:10 denis111 Exp $ $Id$
Utility functions for the module loader Utility functions for the module loader
@ -43,13 +43,13 @@ extern int fprintf(FILE *, const char *, ...);
/*========== Shared tracker identifiers */ /*========== Shared tracker identifiers */
CHAR *STM_Signatures[STM_NTRACKERS] = { const CHAR *STM_Signatures[STM_NTRACKERS] = {
"!Scream!", "!Scream!",
"BMOD2STM", "BMOD2STM",
"WUZAMOD!" "WUZAMOD!"
}; };
CHAR *STM_Version[STM_NTRACKERS] = { const CHAR *STM_Version[STM_NTRACKERS] = {
"Screamtracker 2", "Screamtracker 2",
"Converted by MOD2STM (STM format)", "Converted by MOD2STM (STM format)",
"Wuzamod (STM format)" "Wuzamod (STM format)"
@ -71,29 +71,27 @@ FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */
/*========== Linear periods stuff */ /*========== Linear periods stuff */
int* noteindex=NULL; /* remap value for linear period modules */ int* noteindex=NULL; /* remap value for linear period modules */
static int noteindexcount=0; static unsigned noteindexcount=0;
int *AllocLinear(void) int *AllocLinear(void)
{ {
if(of.numsmp>noteindexcount) { if(of.numsmp>noteindexcount) {
noteindexcount=of.numsmp; noteindexcount=of.numsmp;
noteindex=MikMod_realloc(noteindex,noteindexcount*sizeof(int)); noteindex=(int*)MikMod_realloc(noteindex,noteindexcount*sizeof(int));
} }
return noteindex; return noteindex;
} }
void FreeLinear(void) void FreeLinear(void)
{ {
if(noteindex) {
MikMod_free(noteindex); MikMod_free(noteindex);
noteindex=NULL; noteindex=NULL;
}
noteindexcount=0; noteindexcount=0;
} }
int speed_to_finetune(ULONG speed,int sample) int speed_to_finetune(ULONG speed,int sample)
{ {
ULONG ctmp=0,tmp,note=1,finetune=0; ULONG ctmp=0,tmp,note=1,ft=0;
speed>>=1; speed>>=1;
while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) { while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) {
@ -104,16 +102,16 @@ int speed_to_finetune(ULONG speed,int sample)
if(tmp!=speed) { if(tmp!=speed) {
if((tmp-speed)<(speed-ctmp)) if((tmp-speed)<(speed-ctmp))
while(tmp>speed) while(tmp>speed)
tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune)); tmp=getfrequency(of.flags,getlinearperiod(note<<1,--ft));
else { else {
note--; note--;
while(ctmp<speed) while(ctmp<speed)
ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++finetune)); ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++ft));
} }
} }
noteindex[sample]=note-4*OCTAVE; noteindex[sample]=note-4*OCTAVE;
return finetune; return ft;
} }
/*========== Order stuff */ /*========== Order stuff */
@ -141,13 +139,9 @@ void S3MIT_CreateOrders(int curious)
/*========== Effect stuff */ /*========== Effect stuff */
/* handles S3M and IT effects */ /* handles S3M and IT effects */
void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags) void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, unsigned int flags)
{ {
UBYTE /* hi,*/ lo; UBYTE lo = inf&0xF;
lo=inf&0xf;
/* hi=inf>>4; */
/* process S3M / IT specific command structure */ /* process S3M / IT specific command structure */
if(cmd!=255) { if(cmd!=255) {

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: mmalloc.c,v 1.3 2007/12/03 20:42:58 denis111 Exp $ $Id$
Dynamic memory routines Dynamic memory routines
@ -30,150 +30,113 @@
#include "config.h" #include "config.h"
#endif #endif
#ifdef HAVE_POSIX_MEMALIGN
#define _XOPEN_SOURCE 600 /* for posix_memalign */
#endif
#include "string.h"
#include "mikmod_internals.h" #include "mikmod_internals.h"
#define ALIGN_STRIDE 16 #if defined(HAVE_SSE2) || defined(HAVE_ALTIVEC)
/* not used #undef WIN32_ALIGNED_MALLOC
static void * align_pointer(char *ptr, size_t stride) #if defined(_WIN32) && !defined(_WIN32_WCE)
{ # if defined(_WIN64) /* OK with MSVC and MinGW */
char *pptr = ptr + sizeof(void*); # define WIN32_ALIGNED_MALLOC
char *fptr; # elif defined(_MSC_VER) && (_MSC_VER >= 1300)
size_t err = ((size_t)pptr)&(stride-1); # define WIN32_ALIGNED_MALLOC
if (err) # elif defined(__MINGW32__)
fptr = pptr + (stride - err); /* no guarantees that msvcrt.dll will have it */
else # endif
fptr = pptr;
*(size_t*)(fptr - sizeof(void*)) = (size_t)ptr;
return fptr;
}
static void *get_pointer(void *data)
{
unsigned char *_pptr = (unsigned char*)data - sizeof(void*);
size_t _ptr = *(size_t*)_pptr;
return (void*)_ptr;
}
*/
void* MikMod_realloc(void *data, size_t size)
{
return realloc(data, size);
#if 0
if (data)
{
#if defined __MACH__
void *d = realloc(data, size);
if (d)
{
return d;
}
return 0;
#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE)
return _aligned_realloc(data, size, ALIGN_STRIDE);
#else
unsigned char *newPtr = (unsigned char *)realloc(get_pointer(data), size + ALIGN_STRIDE + sizeof(void*));
return align_pointer(newPtr, ALIGN_STRIDE);
#endif #endif
}
return MikMod_malloc(size);
#endif
}
#define PTRSIZE (sizeof(void*))
/* Same as malloc, but sets error variable _mm_error when fails. Returns a 16-byte aligned pointer */ /* return a 16 byte aligned address */
void* MikMod_malloc(size_t size) void* MikMod_amalloc(size_t size)
{ {
void *d; void *d;
if(!(d=calloc(1,size))) { #if defined(HAVE_POSIX_MEMALIGN)
_mm_errno = MMERR_OUT_OF_MEMORY; if (!posix_memalign(&d, 16, size)) {
if(_mm_errorhandler) _mm_errorhandler(); memset(d, 0, size);
}
return d;
#if 0
#if defined __MACH__
void *d = calloc(1, size);
if (d)
{
return d; return d;
} }
return 0; #elif defined(WIN32_ALIGNED_MALLOC)
#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE) d = _aligned_malloc(size, 16);
void * d = _aligned_malloc(size, ALIGN_STRIDE); if (d) {
if (d)
{
ZeroMemory(d, size); ZeroMemory(d, size);
return d; return d;
} }
return 0;
#else #else
void *d = calloc(1, size + ALIGN_STRIDE + sizeof(void*)); size_t s = (size)? ((size + (PTRSIZE-1)) & ~(PTRSIZE-1)) : PTRSIZE;
s += PTRSIZE + 16;
d = calloc(1, s);
if (d) {
char *pptr = (char *)d + PTRSIZE;
size_t err = ((size_t)pptr) & 15;
char *fptr = pptr + (16 - err);
*(size_t*)(fptr - PTRSIZE) = (size_t)d;
return fptr;
}
#endif
if(!d) {
_mm_errno = MMERR_OUT_OF_MEMORY; _mm_errno = MMERR_OUT_OF_MEMORY;
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
} return NULL;
return align_pointer(d, ALIGN_STRIDE); }
#endif
void MikMod_afree(void *data)
{
if (!data) return;
#if defined(HAVE_POSIX_MEMALIGN)
free(data);
#elif defined(WIN32_ALIGNED_MALLOC)
_aligned_free(data);
#else
free((void *) *(size_t*)((unsigned char *)data - PTRSIZE));
#endif #endif
} }
#endif /* (HAVE_SSE2) || (HAVE_ALTIVEC) */
void* MikMod_realloc(void *data, size_t size)
{
if (data) return realloc(data, size);
return calloc(1, size);
}
/* Same as malloc, but sets error variable _mm_error when fails */
void* MikMod_malloc(size_t size)
{
return MikMod_calloc(1, size);
}
/* Same as calloc, but sets error variable _mm_error when fails */ /* Same as calloc, but sets error variable _mm_error when fails */
void* MikMod_calloc(size_t nitems,size_t size) void* MikMod_calloc(size_t nitems, size_t size)
{ {
void *d;
if(!(d=calloc(nitems,size))) {
_mm_errno = MMERR_OUT_OF_MEMORY;
if(_mm_errorhandler) _mm_errorhandler();
}
return d;
#if 0
#if defined __MACH__
void *d = calloc(nitems, size); void *d = calloc(nitems, size);
if (d) if (d) return d;
{
return d;
}
return 0;
#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE)
void * d = _aligned_malloc(size * nitems, ALIGN_STRIDE);
if (d)
{
ZeroMemory(d, size * nitems);
return d;
}
return 0;
#else
void *d = calloc(nitems, size + ALIGN_STRIDE + sizeof(void*));
if(!d) {
_mm_errno = MMERR_OUT_OF_MEMORY; _mm_errno = MMERR_OUT_OF_MEMORY;
if(_mm_errorhandler) _mm_errorhandler(); if(_mm_errorhandler) _mm_errorhandler();
} return NULL;
return align_pointer(d, ALIGN_STRIDE);
#endif
#endif
} }
void MikMod_free(void *data) void MikMod_free(void *data)
{ {
free(data); if (data) free(data);
}
#if 0 /* like strdup(), but the result must be freed using MikMod_free() */
if (data) CHAR *MikMod_strdup(const CHAR *s)
{ {
#if defined __MACH__ size_t l;
free(data); CHAR *d;
#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE)
_aligned_free(data); if (!s) return NULL;
#else
free(get_pointer(data)); l = strlen(s) + 1;
#endif d = (CHAR *) MikMod_calloc(1, l * sizeof(CHAR));
} if (d) strcpy(d, s);
#endif return d;
} }
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: mmerror.c,v 1.2 2005/03/30 19:10:41 realtech Exp $ $Id$
Error handling functions. Error handling functions.
Register an error handler with _mm_RegisterErrorHandler() and you're all set. Register an error handler with _mm_RegisterErrorHandler() and you're all set.
@ -40,7 +40,9 @@
#include "mikmod_internals.h" #include "mikmod_internals.h"
CHAR *_mm_errmsg[MMERR_MAX+1] = #define _mmerr_invalid "Invalid error code"
static const char *_mm_errmsg[MMERR_MAX+1] =
{ {
/* No error */ /* No error */
@ -82,62 +84,89 @@ CHAR *_mm_errmsg[MMERR_MAX+1] =
"Unable to set non-blocking mode for audio device", "Unable to set non-blocking mode for audio device",
/* AudioFile driver errors */ /* AudioFile driver errors */
#ifdef DRV_AF
"Cannot find suitable AudioFile audio port", "Cannot find suitable AudioFile audio port",
#else
_mmerr_invalid,
#endif
/* AIX driver errors */ /* AIX driver errors */
#ifdef DRV_AIX
"Configuration (init step) of audio device failed", "Configuration (init step) of audio device failed",
"Configuration (control step) of audio device failed", "Configuration (control step) of audio device failed",
"Configuration (start step) of audio device failed", "Configuration (start step) of audio device failed",
#else
/* ALSA driver errors */ _mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
#endif
/* EsounD driver errors */
/* Ultrasound driver errors */ /* Ultrasound driver errors */
#ifdef DRV_ULTRA
"Ultrasound driver only works in 16 bit stereo 44 KHz", "Ultrasound driver only works in 16 bit stereo 44 KHz",
"Ultrasound card could not be reset", "Ultrasound card could not be reset",
"Could not start Ultrasound timer", "Could not start Ultrasound timer",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
#endif
/* HP driver errors */ /* HP driver errors */
#ifdef DRV_HP
"Unable to select 16bit-linear sample format", "Unable to select 16bit-linear sample format",
"Could not select requested sample-rate", "Could not select requested sample-rate",
"Could not select requested number of channels", "Could not select requested number of channels",
"Unable to select audio output", "Unable to select audio output",
"Unable to get audio description", "Unable to get audio description",
"Could not set transmission buffer size", "Could not set transmission buffer size",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
#endif
/* Open Sound System driver errors */ /* Open Sound System driver errors */
#ifdef DRV_OSS
"Could not set fragment size", "Could not set fragment size",
"Could not set sample size", "Could not set sample size",
"Could not set mono/stereo setting", "Could not set mono/stereo setting",
"Could not set sample rate", "Could not set sample rate",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid,
#endif
/* SGI driver errors */ /* SGI driver errors */
#ifdef DRV_SGI
"Unsupported sample rate", "Unsupported sample rate",
"Hardware does not support 16 bit sound", "Hardware does not support 16 bit sound",
"Hardware does not support 8 bit sound", "Hardware does not support 8 bit sound",
"Hardware does not support stereo sound", "Hardware does not support stereo sound",
"Hardware does not support mono sound", "Hardware does not support mono sound",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid,
#endif
/* Sun driver errors */ /* Sun driver errors */
#ifdef DRV_SUN
"Sound device initialization failed", "Sound device initialization failed",
#else
_mmerr_invalid,
#endif
/* OS/2 drivers errors */ /* OS/2 drivers errors */
#if defined(DRV_OS2) || defined(DRV_DART)
"Could not set mixing parameters", "Could not set mixing parameters",
#else
_mmerr_invalid,
#endif
#ifdef DRV_OS2
"Could not create playback semaphores", "Could not create playback semaphores",
"Could not create playback timer", "Could not create playback timer",
"Could not create playback thread", "Could not create playback thread",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
#endif
/* DirectSound driver errors */ /* DirectSound driver errors */
#ifdef DRV_DS
"Could not set playback priority", "Could not set playback priority",
"Could not create playback buffers", "Could not create playback buffers",
"Could not set playback format", "Could not set playback format",
@ -145,22 +174,34 @@ CHAR *_mm_errmsg[MMERR_MAX+1] =
"Could not register event", "Could not register event",
"Could not create playback thread", "Could not create playback thread",
"Could not initialize playback thread", "Could not initialize playback thread",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid,
#endif
/* Windows Multimedia API driver errors */ /* Windows Multimedia API driver errors */
#ifdef DRV_WIN
"Invalid device handle", "Invalid device handle",
"The resource is already allocated", "The resource is already allocated",
"Invalid device identifier", "Invalid device identifier",
"Unsupported output format", "Unsupported output format",
"Unknown error", "Unknown error",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid,
#endif
/* Macintosh driver errors */ /* Macintosh driver errors */
#ifdef DRV_MAC
"Unsupported sample rate", "Unsupported sample rate",
"Could not start playback", "Could not start playback",
#else
_mmerr_invalid, _mmerr_invalid,
#endif
/* MacOS X/Darwin driver errors */ /* MacOS X/Darwin driver errors */
#ifdef DRV_OSX
"Unknown device", "Unknown device",
"Bad property", "Bad property",
"Could not set playback format", "Could not set playback format",
@ -169,20 +210,81 @@ CHAR *_mm_errmsg[MMERR_MAX+1] =
"Could not create playback thread", "Could not create playback thread",
"Could not start audio device", "Could not start audio device",
"Could not create buffer thread", "Could not create buffer thread",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid,
#endif
/* DOS driver errors */ /* DOS driver errors */
#ifdef DRV_WSS
"WSS_STARTDMA", "WSS_STARTDMA",
#else
_mmerr_invalid,
#endif
#ifdef DRV_SB
"SB_STARTDMA", "SB_STARTDMA",
#else
_mmerr_invalid,
#endif
/* float32 output */
"This driver doesn't support 32 bit float output",
/* OpenAL driver errors */
#ifdef DRV_OPENAL
"Could not create context",
"Could not make context current",
"Could not create buffers",
"Could not create sources",
"Could not change source parameters",
"Could not queue buffers",
"Could not unqueue buffers",
"Could not copy buffer data",
"Could not get source parameters",
"Could not play source",
"Could not stop source",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid,
#endif
/* ALSA driver errors */
#ifdef DRV_ALSA
"No ALSA configurations available",
"Could not set ALSA output params",
"Could not set playback format",
"Could not set sample rate",
"Could not set mono/stereo setting",
"Could not get buffer size from ALSA",
"ALSA PCM start error",
"ALSA PCM write error",
"ALSA PCM recovery failure",
#else
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
_mmerr_invalid, _mmerr_invalid, _mmerr_invalid,
#endif
/* Sndio errors */
#ifdef DRV_SNDIO
"Could not set SNDIO output params",
"Unsupported SNDIO output params",
#else
_mmerr_invalid, _mmerr_invalid,
#endif
/* Invalid error */ /* Invalid error */
"Invalid error code" _mmerr_invalid
}; };
MIKMODAPI char *MikMod_strerror(int code) MIKMODAPI const char *MikMod_strerror(int code)
{ {
if ((code<0)||(code>MMERR_MAX)) code=MMERR_MAX+1; if ((code<0)||(code>MMERR_MAX)) code=MMERR_MAX;
return _mm_errmsg[code]; return _mm_errmsg[code];
} }

View file

@ -20,8 +20,6 @@
/*============================================================================== /*==============================================================================
$Id: mmio.c,v 1.3 2005/03/30 19:10:58 realtech Exp $
Portable file I/O routines Portable file I/O routines
==============================================================================*/ ==============================================================================*/
@ -51,10 +49,14 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "mikmod.h"
#include "mikmod_internals.h" #include "mikmod_internals.h"
#ifdef SUNOS #ifdef SUNOS
@ -66,8 +68,6 @@ extern int fseek(FILE *, long, int);
extern size_t fwrite(const void *, size_t, size_t, FILE *); extern size_t fwrite(const void *, size_t, size_t, FILE *);
#endif #endif
#define COPY_BUFSIZE 1024
/* some prototypes */ /* some prototypes */
static int _mm_MemReader_Eof(MREADER* reader); static int _mm_MemReader_Eof(MREADER* reader);
static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size); static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size);
@ -75,13 +75,10 @@ static int _mm_MemReader_Get(MREADER* reader);
static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence); static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence);
static long _mm_MemReader_Tell(MREADER* reader); static long _mm_MemReader_Tell(MREADER* reader);
//static long _mm_iobase=0,temp_iobase=0; int _mm_fopen(const CHAR* fname, const CHAR* attrib)
int _mm_fopen(CHAR* fname,CHAR* attrib)
{ {
int fp; int fp;
(void)attrib; (void)attrib;
//if(!(fp=fopen(fname,attrib))) { //if(!(fp=fopen(fname,attrib))) {
// _mm_errno = MMERR_OPENING_FILE; // _mm_errno = MMERR_OPENING_FILE;
// if(_mm_errorhandler) _mm_errorhandler(); // if(_mm_errorhandler) _mm_errorhandler();
@ -94,7 +91,7 @@ int _mm_fopen(CHAR* fname,CHAR* attrib)
return fp; return fp;
} }
int _mm_FileExists(CHAR* fname) int _mm_FileExists(const CHAR* fname)
{ {
int fp; int fp;
@ -143,8 +140,8 @@ static int _mm_FileReader_Eof(MREADER* reader)
static int _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size) static int _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)
{ {
//return !!fread(ptr,size,1,((MFILEREADER*)reader)->file);
return read(((MFILEREADER*)reader)->file, ptr, size); return read(((MFILEREADER*)reader)->file, ptr, size);
//return !!fread(ptr,size,1,((MFILEREADER*)reader)->file);
} }
static int _mm_FileReader_Get(MREADER* reader) static int _mm_FileReader_Get(MREADER* reader)
@ -173,7 +170,7 @@ static long _mm_FileReader_Tell(MREADER* reader)
MREADER *_mm_new_file_reader(int fp) MREADER *_mm_new_file_reader(int fp)
{ {
MFILEREADER* reader=(MFILEREADER*)MikMod_malloc(sizeof(MFILEREADER)); MFILEREADER* reader=(MFILEREADER*)MikMod_calloc(1,sizeof(MFILEREADER));
if (reader) { if (reader) {
reader->core.Eof =&_mm_FileReader_Eof; reader->core.Eof =&_mm_FileReader_Eof;
reader->core.Read=&_mm_FileReader_Read; reader->core.Read=&_mm_FileReader_Read;
@ -187,7 +184,7 @@ MREADER *_mm_new_file_reader(int fp)
void _mm_delete_file_reader (MREADER* reader) void _mm_delete_file_reader (MREADER* reader)
{ {
if(reader) MikMod_free(reader); MikMod_free(reader);
} }
/*========== File Writer */ /*========== File Writer */
@ -209,10 +206,9 @@ static long _mm_FileWriter_Tell(MWRITER* writer)
return lseek(((MFILEWRITER*)writer)->file, 0, SEEK_CUR); return lseek(((MFILEWRITER*)writer)->file, 0, SEEK_CUR);
} }
static int _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size) static int _mm_FileWriter_Write(MWRITER* writer, const void* ptr, size_t size)
{ {
//return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size); //return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size);
//return (write(ptr,size,((MFILEWRITER*)writer)->file)==(int)size);
(void)writer; (void)writer;
(void)ptr; (void)ptr;
(void)size; (void)size;
@ -229,7 +225,7 @@ static int _mm_FileWriter_Put(MWRITER* writer,int value)
MWRITER *_mm_new_file_writer(int fp) MWRITER *_mm_new_file_writer(int fp)
{ {
MFILEWRITER* writer=(MFILEWRITER*)MikMod_malloc(sizeof(MFILEWRITER)); MFILEWRITER* writer=(MFILEWRITER*)MikMod_calloc(1,sizeof(MFILEWRITER));
if (writer) { if (writer) {
writer->core.Seek =&_mm_FileWriter_Seek; writer->core.Seek =&_mm_FileWriter_Seek;
writer->core.Tell =&_mm_FileWriter_Tell; writer->core.Tell =&_mm_FileWriter_Tell;
@ -242,12 +238,11 @@ MWRITER *_mm_new_file_writer(int fp)
void _mm_delete_file_writer (MWRITER* writer) void _mm_delete_file_writer (MWRITER* writer)
{ {
if(writer) MikMod_free (writer); MikMod_free (writer);
} }
/*========== Memory Reader */ /*========== Memory Reader */
typedef struct MMEMREADER { typedef struct MMEMREADER {
MREADER core; MREADER core;
const void *buffer; const void *buffer;
@ -257,12 +252,12 @@ typedef struct MMEMREADER {
void _mm_delete_mem_reader(MREADER* reader) void _mm_delete_mem_reader(MREADER* reader)
{ {
if (reader) { MikMod_free(reader); } MikMod_free(reader);
} }
MREADER *_mm_new_mem_reader(const void *buffer, int len) MREADER *_mm_new_mem_reader(const void *buffer, long len)
{ {
MMEMREADER* reader=(MMEMREADER*)MikMod_malloc(sizeof(MMEMREADER)); MMEMREADER* reader=(MMEMREADER*)MikMod_calloc(1,sizeof(MMEMREADER));
if (reader) if (reader)
{ {
reader->core.Eof =&_mm_MemReader_Eof; reader->core.Eof =&_mm_MemReader_Eof;
@ -279,74 +274,86 @@ MREADER *_mm_new_mem_reader(const void *buffer, int len)
static int _mm_MemReader_Eof(MREADER* reader) static int _mm_MemReader_Eof(MREADER* reader)
{ {
if (!reader) { return 1; } MMEMREADER* mr = (MMEMREADER*) reader;
if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { if (!mr) return 1;
return 1; if (mr->pos >= mr->len) return 1;
}
return 0; return 0;
} }
static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size) static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size)
{ {
unsigned char *d=ptr; unsigned char *d;
const unsigned char *s; const unsigned char *s;
MMEMREADER* mr;
long siz;
int ret;
if (!reader) { return 0; } if (!reader || !size || (size > (size_t) LONG_MAX))
return 0;
if (reader->Eof(reader)) { return 0; } mr = (MMEMREADER*) reader;
siz = (long) size;
s = ((MMEMREADER*)reader)->buffer; if (mr->pos >= mr->len) return 0; /* @ eof */
s += ((MMEMREADER*)reader)->pos; if (mr->pos + siz > mr->len) {
siz = mr->len - mr->pos;
if ( ((MMEMREADER*)reader)->pos + (long)size > ((MMEMREADER*)reader)->len) ret = 0; /* not enough remaining bytes */
{ }
((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; else {
return 0; /* not enough remaining bytes */ ret = 1;
} }
((MMEMREADER*)reader)->pos += (long)size; s = (const unsigned char *) mr->buffer;
s += mr->pos;
mr->pos += siz;
d = (unsigned char *) ptr;
while (size--) while (siz) {
{ *d++ = *s++;
*d = *s; siz--;
s++;
d++;
} }
return 1; return ret;
} }
static int _mm_MemReader_Get(MREADER* reader) static int _mm_MemReader_Get(MREADER* reader)
{ {
int pos; MMEMREADER* mr;
int c;
if (reader->Eof(reader)) { return 0; } mr = (MMEMREADER*) reader;
if (mr->pos >= mr->len) return EOF;
c = ((const unsigned char*) mr->buffer)[mr->pos];
mr->pos++;
pos = ((MMEMREADER*)reader)->pos; return c;
((MMEMREADER*)reader)->pos++;
return ((unsigned char*)(((MMEMREADER*)reader)->buffer))[pos];
} }
static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence) static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence)
{ {
if (!reader) { return -1; } MMEMREADER* mr;
if (!reader) return -1;
mr = (MMEMREADER*) reader;
switch(whence) switch(whence)
{ {
case SEEK_CUR: case SEEK_CUR:
((MMEMREADER*)reader)->pos += offset; mr->pos += offset;
break; break;
case SEEK_SET: case SEEK_SET:
((MMEMREADER*)reader)->pos = offset; mr->pos = reader->iobase + offset;
break; break;
case SEEK_END: case SEEK_END:
((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len - offset - 1; mr->pos = mr->len + offset;
break; break;
default: /* invalid */
return -1;
} }
if ( ((MMEMREADER*)reader)->pos < 0) { ((MMEMREADER*)reader)->pos = 0; } if (mr->pos < reader->iobase) {
if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { mr->pos = mr->core.iobase;
((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; return -1;
}
if (mr->pos > mr->len) {
mr->pos = mr->len;
} }
return 0; return 0;
} }
@ -354,13 +361,14 @@ static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence)
static long _mm_MemReader_Tell(MREADER* reader) static long _mm_MemReader_Tell(MREADER* reader)
{ {
if (reader) { if (reader) {
return ((MMEMREADER*)reader)->pos; return ((MMEMREADER*)reader)->pos - reader->iobase;
} }
return 0; return 0;
} }
/*========== Write functions */ /*========== Write functions */
void _mm_write_string(CHAR* data,MWRITER* writer)
void _mm_write_string(const CHAR* data,MWRITER* writer)
{ {
if(data) if(data)
_mm_write_UBYTES(data,strlen(data),writer); _mm_write_UBYTES(data,strlen(data),writer);
@ -410,37 +418,51 @@ void _mm_write_I_SLONG(SLONG data,MWRITER* writer)
_mm_write_I_ULONG((ULONG)data,writer); _mm_write_I_ULONG((ULONG)data,writer);
} }
#if defined __STDC__ || defined _MSC_VER || defined MPW_C void _mm_write_M_SWORDS(SWORD *buffer,int cnt,MWRITER* writer)
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ {
void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \ while(cnt-- > 0) _mm_write_M_SWORD(*(buffer++),writer);
{ \
while(number-->0) \
_mm_write_##type_name(*(buffer++),writer); \
} }
#else
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ void _mm_write_M_UWORDS(UWORD *buffer,int cnt,MWRITER* writer)
void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \ {
{ \ while(cnt-- > 0) _mm_write_M_UWORD(*(buffer++),writer);
while(number-->0) \
_mm_write_/**/type_name(*(buffer++),writer); \
} }
#endif
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD) void _mm_write_I_SWORDS(SWORD *buffer,int cnt,MWRITER* writer)
DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD) {
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD) while(cnt-- > 0) _mm_write_I_SWORD(*(buffer++),writer);
DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD) }
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG) void _mm_write_I_UWORDS(UWORD *buffer,int cnt,MWRITER* writer)
DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG) {
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG) while(cnt-- > 0) _mm_write_I_UWORD(*(buffer++),writer);
DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG) }
void _mm_write_M_SLONGS(SLONG *buffer,int cnt,MWRITER* writer)
{
while(cnt-- > 0) _mm_write_M_SLONG(*(buffer++),writer);
}
void _mm_write_M_ULONGS(ULONG *buffer,int cnt,MWRITER* writer)
{
while(cnt-- > 0) _mm_write_M_ULONG(*(buffer++),writer);
}
void _mm_write_I_SLONGS(SLONG *buffer,int cnt,MWRITER* writer)
{
while(cnt-- > 0) _mm_write_I_SLONG(*(buffer++),writer);
}
void _mm_write_I_ULONGS(ULONG *buffer,int cnt,MWRITER* writer)
{
while(cnt-- > 0) _mm_write_I_ULONG(*(buffer++),writer);
}
/*========== Read functions */ /*========== Read functions */
int _mm_read_string(CHAR* buffer,int number,MREADER* reader) int _mm_read_string(CHAR* buffer,int cnt,MREADER* reader)
{ {
return reader->Read(reader,buffer,number); return reader->Read(reader,buffer,cnt);
} }
UWORD _mm_read_M_UWORD(MREADER* reader) UWORD _mm_read_M_UWORD(MREADER* reader)
@ -491,32 +513,52 @@ SLONG _mm_read_I_SLONG(MREADER* reader)
return((SLONG)_mm_read_I_ULONG(reader)); return((SLONG)_mm_read_I_ULONG(reader));
} }
#if defined __STDC__ || defined _MSC_VER || defined MPW_C int _mm_read_M_SWORDS(SWORD *buffer,int cnt,MREADER* reader)
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ {
int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \ while(cnt-- > 0) *(buffer++)=_mm_read_M_SWORD(reader);
{ \ return !reader->Eof(reader);
while(number-->0) \
*(buffer++)=_mm_read_##type_name(reader); \
return !reader->Eof(reader); \
} }
#else
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ int _mm_read_M_UWORDS(UWORD *buffer,int cnt,MREADER* reader)
int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \ {
{ \ while(cnt-- > 0) *(buffer++)=_mm_read_M_UWORD(reader);
while(number-->0) \ return !reader->Eof(reader);
*(buffer++)=_mm_read_/**/type_name(reader); \
return !reader->Eof(reader); \
} }
#endif
DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD) int _mm_read_I_SWORDS(SWORD *buffer,int cnt,MREADER* reader)
DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD) {
DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD) while(cnt-- > 0) *(buffer++)=_mm_read_I_SWORD(reader);
DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD) return !reader->Eof(reader);
}
DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG) int _mm_read_I_UWORDS(UWORD *buffer,int cnt,MREADER* reader)
DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG) {
DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG) while(cnt-- > 0) *(buffer++)=_mm_read_I_UWORD(reader);
DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG) return !reader->Eof(reader);
}
int _mm_read_M_SLONGS(SLONG *buffer,int cnt,MREADER* reader)
{
while(cnt-- > 0) *(buffer++)=_mm_read_M_SLONG(reader);
return !reader->Eof(reader);
}
int _mm_read_M_ULONGS(ULONG *buffer,int cnt,MREADER* reader)
{
while(cnt-- > 0) *(buffer++)=_mm_read_M_ULONG(reader);
return !reader->Eof(reader);
}
int _mm_read_I_SLONGS(SLONG *buffer,int cnt,MREADER* reader)
{
while(cnt-- > 0) *(buffer++)=_mm_read_I_SLONG(reader);
return !reader->Eof(reader);
}
int _mm_read_I_ULONGS(ULONG *buffer,int cnt,MREADER* reader)
{
while(cnt-- > 0) *(buffer++)=_mm_read_I_ULONG(reader);
return !reader->Eof(reader);
}
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: mplayer.c,v 1.4 2006/08/08 00:06:31 realtech Exp $ $Id$
The Protracker Player Driver The Protracker Player Driver
@ -40,31 +40,35 @@
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#include <limits.h>
#include "mikmod_internals.h" #include "mikmod_internals.h"
#ifdef SUNOS #ifdef SUNOS
extern int fprintf(FILE *, const char *, ...); extern int fprintf(int, const char *, ...);
extern long int random(void); extern long int random(void);
#endif #endif
/* The currently playing module */ /* The currently playing module */
MODULE *pf = NULL; MODULE *pf = NULL;
#define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices)
#define HIGH_OCTAVE 2 /* number of above-range octaves */ #define HIGH_OCTAVE 2 /* number of above-range octaves */
static UWORD oldperiods[OCTAVE*2]={ static const UWORD oldperiods[OCTAVE*2]={
0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80, 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0, 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160, 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
}; };
static UBYTE VibratoTable[32]={ static const UBYTE VibratoTable[32]={
0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
}; };
static UBYTE avibtab[128]={ static const UBYTE avibtab[128]={
0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
@ -76,7 +80,7 @@ static UBYTE avibtab[128]={
}; };
/* Triton's linear periods to frequency translation table (for XM modules) */ /* Triton's linear periods to frequency translation table (for XM modules) */
static ULONG lintab[768]={ static const ULONG lintab[768]={
535232,534749,534266,533784,533303,532822,532341,531861, 535232,534749,534266,533784,533303,532822,532341,531861,
531381,530902,530423,529944,529466,528988,528511,528034, 531381,530902,530423,529944,529466,528988,528511,528034,
527558,527082,526607,526131,525657,525183,524709,524236, 527558,527082,526607,526131,525657,525183,524709,524236,
@ -176,7 +180,7 @@ static ULONG lintab[768]={
}; };
#define LOGFAC 2*16 #define LOGFAC 2*16
static UWORD logtab[104]={ static const UWORD logtab[104]={
LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887, LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838, LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
@ -205,7 +209,7 @@ static UWORD logtab[104]={
LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431 LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
}; };
static SBYTE PanbrelloTable[256]={ static const SBYTE PanbrelloTable[256]={
0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
@ -225,12 +229,12 @@ static SBYTE PanbrelloTable[256]={
}; };
/* returns a random value between 0 and ceil-1, ceil must be a power of two */ /* returns a random value between 0 and ceil-1, ceil must be a power of two */
static int getrandom(int ceil) static int getrandom(int ceilval)
{ {
#ifdef HAVE_SRANDOM #if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA)
return random()&(ceil-1); return random()&(ceilval-1);
#else #else
return (rand()*ceil)/(RAND_MAX+1.0); return (rand()*ceilval)/(RAND_MAX+1.0);
#endif #endif
} }
@ -246,14 +250,14 @@ static int MP_FindEmptyChannel(MODULE *mod)
MP_VOICE *a; MP_VOICE *a;
ULONG t,k,tvol,pp; ULONG t,k,tvol,pp;
for (t=0;t<md_sngchn;t++) for (t=0;t<NUMVOICES(mod);t++)
if (((mod->voice[t].main.kick==KICK_ABSENT)|| if (((mod->voice[t].main.kick==KICK_ABSENT)||
(mod->voice[t].main.kick==KICK_ENV))&& (mod->voice[t].main.kick==KICK_ENV))&&
Voice_Stopped_internal(t)) Voice_Stopped_internal(t))
return t; return t;
tvol=0xffffffUL;t=-1;a=mod->voice; tvol=0xffffffUL;t=-1;a=mod->voice;
for (k=0;k<md_sngchn;k++,a++) { for (k=0;k<NUMVOICES(mod);k++,a++) {
/* allow us to take over a nonexisting sample */ /* allow us to take over a nonexisting sample */
if (!a->main.s) if (!a->main.s)
return k; return k;
@ -359,9 +363,15 @@ static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susen
t->a=0; t->a=0;
t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1; t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
if (!t->pts) { /* FIXME: bad/crafted file. better/more general solution? */
t->b=0;
return t->env[0].val;
}
/* Imago Orpheus sometimes stores an extra initial point in the envelope */ /* Imago Orpheus sometimes stores an extra initial point in the envelope */
if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) { if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) {
t->a++;t->b++; t->a++;
t->b++;
} }
/* Fit in the envelope, still */ /* Fit in the envelope, still */
@ -808,7 +818,7 @@ static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
if (dat) a->soffset=(UWORD)dat<<8; if (dat) a->soffset=(UWORD)dat<<8;
a->main.start=a->hioffset|a->soffset; a->main.start=a->hioffset|a->soffset;
if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
a->main.s->loopstart:a->main.s->length; a->main.s->loopstart:a->main.s->length;
} }
@ -850,6 +860,11 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
if (tick || mod->patdly2) if (tick || mod->patdly2)
return 0; return 0;
if (dat >= mod->numpos) { /* crafted file? */
/* fprintf(stderr,"DoPTEffectB: numpos=%d, dat=%d -> %d\n",mod->numpos,dat,mod->numpos-1);*/
dat=mod->numpos-1;
}
/* Vincent Voois uses a nasty trick in "Universal Bolero" */ /* Vincent Voois uses a nasty trick in "Universal Bolero" */
if (dat == mod->sngpos && mod->patbrk == mod->patpos) if (dat == mod->sngpos && mod->patbrk == mod->patpos)
return 0; return 0;
@ -857,8 +872,8 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
if (!mod->loop && !mod->patbrk && if (!mod->loop && !mod->patbrk &&
(dat < mod->sngpos || (dat < mod->sngpos ||
(mod->sngpos == (mod->numpos - 1) && !mod->patbrk) || (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
(dat == mod->sngpos && (flags & UF_NOWRAP)) (dat == mod->sngpos && (flags & UF_NOWRAP)) ) )
)) { {
/* if we don't loop, better not to skip the end of the /* if we don't loop, better not to skip the end of the
pattern, after all... so: pattern, after all... so:
mod->patbrk=0; */ mod->patbrk=0; */
@ -870,6 +885,9 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
mod->sngpos=dat; mod->sngpos=dat;
mod->posjmp=2; mod->posjmp=2;
mod->patpos=0; mod->patpos=0;
/* cancel the FT2 pattern loop (E60) bug.
* also see DoEEffects() below for it. */
if (flags & UF_FT2QUIRKS) mod->patbrk=0;
} }
return 0; return 0;
@ -899,9 +917,14 @@ static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
dat=UniGetByte(); dat=UniGetByte();
if ((tick)||(mod->patdly2)) return 0; if ((tick)||(mod->patdly2)) return 0;
if (dat && dat >= mod->numrow) { /* crafted file? */
/* fprintf(stderr,"DoPTEffectD: numrow=%d, dat=%d -> 0\n",mod->numrow,dat);*/
dat=0;
}
if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&& if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
(dat>mod->pattrows[mod->positions[mod->sngpos]])) (dat>mod->pattrows[mod->positions[mod->sngpos]])) {
dat=mod->pattrows[mod->positions[mod->sngpos]]; dat=mod->pattrows[mod->positions[mod->sngpos]];
}
mod->patbrk=dat; mod->patbrk=dat;
if (!mod->posjmp) { if (!mod->posjmp) {
/* don't ask me to explain this code - it makes /* don't ask me to explain this code - it makes
@ -909,9 +932,8 @@ static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
correctly, among others. Take that for granted, or write correctly, among others. Take that for granted, or write
the page of comments yourself... you might need some the page of comments yourself... you might need some
aspirin - Miod */ aspirin - Miod */
if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)|| if ((mod->sngpos==mod->numpos-1)&&(dat)&&
(mod->positions[mod->sngpos]==(mod->numpat-1) ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) {
&& !(flags&UF_NOWRAP)))) {
mod->sngpos=0; mod->sngpos=0;
mod->posjmp=2; mod->posjmp=2;
} else } else
@ -982,8 +1004,13 @@ static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
} else } else
mod->patpos=a->pat_reppos; mod->patpos=a->pat_reppos;
} else a->pat_reppos=POS_NONE; } else a->pat_reppos=POS_NONE;
} else } else {
a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */ a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
/* emulate the FT2 pattern loop (E60) bug:
* http://milkytracker.org/docs/MilkyTracker.html#fxE6x
* roadblas.xm plays correctly with this. */
if (flags & UF_FT2QUIRKS) mod->patbrk=mod->patpos;
}
break; break;
case 0x7: /* set tremolo waveform */ case 0x7: /* set tremolo waveform */
a->wavecontrol&=0x0f; a->wavecontrol&=0x0f;
@ -1608,7 +1635,7 @@ static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
INSTRUMENT *i=a->main.i; INSTRUMENT *i=a->main.i;
MP_VOICE *aout; MP_VOICE *aout;
if ((aout=a->slave)) { if ((aout=a->slave) != NULL) {
if (aout->venv.env) { if (aout->venv.env) {
points=i->volenv[i->volpts-1].pos; points=i->volenv[i->volpts-1].pos;
aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos; aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
@ -2136,7 +2163,7 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
a->hioffset=inf<<16; a->hioffset=inf<<16;
a->main.start=a->hioffset|a->soffset; a->main.start=a->hioffset|a->soffset;
if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
a->main.s->loopstart:a->main.s->length; a->main.s->loopstart:a->main.s->length;
} }
@ -2228,7 +2255,7 @@ static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
a->ultoffset=offset; a->ultoffset=offset;
a->main.start=a->ultoffset<<2; a->main.start=a->ultoffset<<2;
if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
a->main.s->loopstart:a->main.s->length; a->main.s->loopstart:a->main.s->length;
@ -2382,7 +2409,11 @@ static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
int explicitslides = 0; int explicitslides = 0;
effect_func f; effect_func f;
while((c=UniGetByte())) { while((c=UniGetByte()) != 0) {
#if 0 /* this doesn't normally happen unless things go fubar elsewhere */
if (c >= UNI_LAST)
fprintf(stderr,"fubar'ed opcode %u\n",c);
#endif
f = effects[c]; f = effects[c];
if (f != DoNothing) if (f != DoNothing)
a->sliding = 0; a->sliding = 0;
@ -2401,12 +2432,12 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
switch (dat) { switch (dat) {
case 0x0: /* past note cut */ case 0x0: /* past note cut */
for (t=0;t<md_sngchn;t++) for (t=0;t<NUMVOICES(mod);t++)
if (mod->voice[t].master==a) if (mod->voice[t].master==a)
mod->voice[t].main.fadevol=0; mod->voice[t].main.fadevol=0;
break; break;
case 0x1: /* past note off */ case 0x1: /* past note off */
for (t=0;t<md_sngchn;t++) for (t=0;t<NUMVOICES(mod);t++)
if (mod->voice[t].master==a) { if (mod->voice[t].master==a) {
mod->voice[t].main.keyoff|=KEY_OFF; mod->voice[t].main.keyoff|=KEY_OFF;
if ((!(mod->voice[t].venv.flg & EF_ON))|| if ((!(mod->voice[t].venv.flg & EF_ON))||
@ -2415,7 +2446,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
} }
break; break;
case 0x2: /* past note fade */ case 0x2: /* past note fade */
for (t=0;t<md_sngchn;t++) for (t=0;t<NUMVOICES(mod);t++)
if (mod->voice[t].master==a) if (mod->voice[t].master==a)
mod->voice[t].main.keyoff|=KEY_FADE; mod->voice[t].main.keyoff|=KEY_FADE;
break; break;
@ -2470,7 +2501,7 @@ static void pt_UpdateVoices(MODULE *mod, int max_volume)
SAMPLE *s; SAMPLE *s;
mod->totalchn=mod->realchn=0; mod->totalchn=mod->realchn=0;
for (channel=0;channel<md_sngchn;channel++) { for (channel=0;channel<NUMVOICES(mod);channel++) {
aout=&mod->voice[channel]; aout=&mod->voice[channel];
i=aout->main.i; i=aout->main.i;
s=aout->main.s; s=aout->main.s;
@ -2484,7 +2515,7 @@ static void pt_UpdateVoices(MODULE *mod, int max_volume)
if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) { if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
Voice_Play_internal(channel,s,(aout->main.start==-1)? Voice_Play_internal(channel,s,(aout->main.start==-1)?
((s->flags&SF_UST_LOOP) ? (SLONG)s->loopstart : 0) : aout->main.start); ((s->flags&SF_UST_LOOP)?(SLONG)s->loopstart:0):aout->main.start);
aout->main.fadevol=32768; aout->main.fadevol=32768;
aout->aswppos=0; aout->aswppos=0;
} }
@ -2687,7 +2718,7 @@ static void pt_Notes(MODULE *mod)
UniSetRow(a->row); UniSetRow(a->row);
funky=0; funky=0;
while((c=UniGetByte())) while((c=UniGetByte()) != 0)
switch (c) { switch (c) {
case UNI_NOTE: case UNI_NOTE:
funky|=1; funky|=1;
@ -2720,7 +2751,7 @@ static void pt_Notes(MODULE *mod)
INSTRUMENT *i; INSTRUMENT *i;
SAMPLE *s; SAMPLE *s;
if ((i=a->main.i)) { if ((i=a->main.i) != NULL) {
if (i->samplenumber[a->anote] >= mod->numsmp) continue; if (i->samplenumber[a->anote] >= mod->numsmp) continue;
s=&mod->samples[i->samplenumber[a->anote]]; s=&mod->samples[i->samplenumber[a->anote]];
a->main.note=i->samplenote[a->anote]; a->main.note=i->samplenote[a->anote];
@ -2809,7 +2840,7 @@ static void pt_EffectsPass1(MODULE *mod)
for (channel=0;channel<mod->numchn;channel++) { for (channel=0;channel<mod->numchn;channel++) {
a=&mod->control[channel]; a=&mod->control[channel];
if ((aout=a->slave)) { if ((aout=a->slave) != NULL) {
a->main.fadevol=aout->main.fadevol; a->main.fadevol=aout->main.fadevol;
a->main.period=aout->main.period; a->main.period=aout->main.period;
if (a->main.kick==KICK_KEYOFF) if (a->main.kick==KICK_KEYOFF)
@ -2891,7 +2922,7 @@ static void pt_NNA(MODULE *mod)
if (a->dct!=DCT_OFF) { if (a->dct!=DCT_OFF) {
int t; int t;
for (t=0;t<md_sngchn;t++) for (t=0;t<NUMVOICES(mod);t++)
if ((!Voice_Stopped_internal(t))&& if ((!Voice_Stopped_internal(t))&&
(mod->voice[t].masterchn==channel)&& (mod->voice[t].masterchn==channel)&&
(a->main.sample==mod->voice[t].main.sample)) { (a->main.sample==mod->voice[t].main.sample)) {
@ -2955,7 +2986,7 @@ static void pt_SetupVoices(MODULE *mod)
a->slave=&mod->voice[a->slavechn=channel]; a->slave=&mod->voice[a->slavechn=channel];
/* assign parts of MP_VOICE only done for a KICK_NOTE */ /* assign parts of MP_VOICE only done for a KICK_NOTE */
if ((aout=a->slave)) { if ((aout=a->slave) != NULL) {
if (aout->mflag && aout->master) aout->master->slave=NULL; if (aout->mflag && aout->master) aout->master->slave=NULL;
aout->master=a; aout->master=a;
a->slave=aout; a->slave=aout;
@ -2984,7 +3015,7 @@ static void pt_EffectsPass2(MODULE *mod)
if (!a->row) continue; if (!a->row) continue;
UniSetRow(a->row); UniSetRow(a->row);
while((c=UniGetByte())) while((c=UniGetByte()) != 0)
if (c==UNI_ITEFFECTS0) { if (c==UNI_ITEFFECTS0) {
c=UniGetByte(); c=UniGetByte();
if ((c>>4)==SS_S7EFFECTS) if ((c>>4)==SS_S7EFFECTS)
@ -3046,6 +3077,9 @@ void Player_HandleTick(void)
pf->control[channel].pat_reppos=-1; pf->control[channel].pat_reppos=-1;
pf->patbrk=pf->posjmp=0; pf->patbrk=pf->posjmp=0;
if (pf->sngpos<0) pf->sngpos=(SWORD)(pf->numpos-1);
/* handle the "---" (end of song) pattern since it can occur /* handle the "---" (end of song) pattern since it can occur
*inside* the module in some formats */ *inside* the module in some formats */
if ((pf->sngpos>=pf->numpos)|| if ((pf->sngpos>=pf->numpos)||
@ -3060,7 +3094,6 @@ void Player_HandleTick(void)
pf->bpm=pf->inittempo<32?32:pf->inittempo; pf->bpm=pf->inittempo<32?32:pf->inittempo;
} }
} }
if (pf->sngpos<0) pf->sngpos=pf->numpos-1;
} }
if (!pf->patdly2) if (!pf->patdly2)
@ -3133,6 +3166,11 @@ int Player_Init(MODULE* mod)
if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE)))) if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
return 1; return 1;
/* mod->numvoices was used during loading to clamp md_sngchn.
After loading it's used to remember how big mod->voice is.
*/
mod->numvoices = md_sngchn;
Player_Init_internal(mod); Player_Init_internal(mod);
return 0; return 0;
} }
@ -3148,9 +3186,7 @@ void Player_Exit_internal(MODULE* mod)
pf=NULL; pf=NULL;
} }
if (mod->control)
MikMod_free(mod->control); MikMod_free(mod->control);
if (mod->voice)
MikMod_free(mod->voice); MikMod_free(mod->voice);
mod->control=NULL; mod->control=NULL;
mod->voice=NULL; mod->voice=NULL;
@ -3166,8 +3202,10 @@ void Player_Exit(MODULE* mod)
MIKMODAPI void Player_SetVolume(SWORD volume) MIKMODAPI void Player_SetVolume(SWORD volume)
{ {
MUTEX_LOCK(vars); MUTEX_LOCK(vars);
if (pf) if (pf) {
pf->volume=(volume<0)?0:(volume>128)?128:volume; pf->volume=(volume<0)?0:(volume>128)?128:volume;
pf->initvolume=pf->volume;
}
MUTEX_UNLOCK(vars); MUTEX_UNLOCK(vars);
} }
@ -3241,7 +3279,7 @@ MIKMODAPI void Player_NextPosition(void)
pf->patbrk=0; pf->patbrk=0;
pf->vbtick=pf->sngspd; pf->vbtick=pf->sngspd;
for (t=0;t<md_sngchn;t++) { for (t=0;t<NUMVOICES(pf);t++) {
Voice_Stop_internal(t); Voice_Stop_internal(t);
pf->voice[t].main.i=NULL; pf->voice[t].main.i=NULL;
pf->voice[t].main.s=NULL; pf->voice[t].main.s=NULL;
@ -3266,7 +3304,7 @@ MIKMODAPI void Player_PrevPosition(void)
pf->patbrk=0; pf->patbrk=0;
pf->vbtick=pf->sngspd; pf->vbtick=pf->sngspd;
for (t=0;t<md_sngchn;t++) { for (t=0;t<NUMVOICES(pf);t++) {
Voice_Stop_internal(t); Voice_Stop_internal(t);
pf->voice[t].main.i=NULL; pf->voice[t].main.i=NULL;
pf->voice[t].main.s=NULL; pf->voice[t].main.s=NULL;
@ -3293,7 +3331,7 @@ MIKMODAPI void Player_SetPosition(UWORD pos)
pf->sngpos=pos; pf->sngpos=pos;
pf->vbtick=pf->sngspd; pf->vbtick=pf->sngspd;
for (t=0;t<md_sngchn;t++) { for (t=0;t<NUMVOICES(pf);t++) {
Voice_Stop_internal(t); Voice_Stop_internal(t);
pf->voice[t].main.i=NULL; pf->voice[t].main.i=NULL;
pf->voice[t].main.s=NULL; pf->voice[t].main.s=NULL;
@ -3538,18 +3576,17 @@ MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo)
return numvoices; return numvoices;
} }
/* Get current module order */
// Get current module order
MIKMODAPI int Player_GetOrder(void) MIKMODAPI int Player_GetOrder(void)
{ {
int ret; int ret;
MUTEX_LOCK(vars); MUTEX_LOCK(vars);
ret = pf ? pf->sngpos :0; // pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; ret = pf ? pf->sngpos :0; /* pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; */
MUTEX_UNLOCK(vars); MUTEX_UNLOCK(vars);
return ret; return ret;
} }
// Get current module row /* Get current module row */
MIKMODAPI int Player_GetRow(void) MIKMODAPI int Player_GetRow(void)
{ {
int ret; int ret;
@ -3559,5 +3596,4 @@ MIKMODAPI int Player_GetRow(void)
return ret; return ret;
} }
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: munitrk.c,v 1.2 2005/03/30 19:11:46 realtech Exp $ $Id$
All routines dealing with the manipulation of UNITRK streams All routines dealing with the manipulation of UNITRK streams
@ -37,7 +37,7 @@
/* Unibuffer chunk size */ /* Unibuffer chunk size */
#define BUFPAGE 128 #define BUFPAGE 128
UWORD unioperands[UNI_LAST]={ const UWORD unioperands[UNI_LAST] = {
0, /* not used */ 0, /* not used */
1, /* UNI_NOTE */ 1, /* UNI_NOTE */
1, /* UNI_INSTRUMENT */ 1, /* UNI_INSTRUMENT */
@ -236,7 +236,7 @@ void UniWriteWord(UWORD data)
} }
} }
static int MyCmp(UBYTE* a,UBYTE* b,UWORD l) static int MyCmp(const UBYTE* a,const UBYTE* b,UWORD l)
{ {
UWORD t; UWORD t;
@ -275,15 +275,15 @@ void UniNewline(void)
stream. */ stream. */
UBYTE* UniDup(void) UBYTE* UniDup(void)
{ {
UBYTE *d; void *d;
if (!UniExpand(unitt-unipc)) return NULL; if (!UniExpand(unipc-unitt)) return NULL;
unibuf[unitt] = 0; unibuf[unitt] = 0;
if(!(d=(UBYTE *)MikMod_malloc(unipc))) return NULL; if(!(d=MikMod_malloc(unipc))) return NULL;
memcpy(d,unibuf,unipc); memcpy(d,unibuf,unipc);
return d; return (UBYTE *)d;
} }
int UniInit(void) int UniInit(void)
@ -296,7 +296,7 @@ int UniInit(void)
void UniCleanup(void) void UniCleanup(void)
{ {
if(unibuf) MikMod_free(unibuf); MikMod_free(unibuf);
unibuf = NULL; unibuf = NULL;
} }

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: npertab.c,v 1.2 2005/03/30 19:11:47 realtech Exp $ $Id$
MOD format period table. Used by both the MOD and M15 (15-inst mod) Loaders. MOD format period table. Used by both the MOD and M15 (15-inst mod) Loaders.
@ -32,7 +32,7 @@
#include "mikmod_internals.h" #include "mikmod_internals.h"
UWORD npertab[7 * OCTAVE] = { const UWORD npertab[7 * OCTAVE] = {
/* Octaves 6 -> 0 */ /* Octaves 6 -> 0 */
/* C C# D D# E F F# G G# A A# B */ /* C C# D D# E F F# G G# A A# B */
0x6b0,0x650,0x5f4,0x5a0,0x54c,0x500,0x4b8,0x474,0x434,0x3f8,0x3c0,0x38a, 0x6b0,0x650,0x5f4,0x5a0,0x54c,0x500,0x4b8,0x474,0x434,0x3f8,0x3c0,0x38a,

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: sloader.c,v 1.3 2007/12/06 17:46:08 denis111 Exp $ $Id$
Routines for loading samples. The sample loader utilizes the routines Routines for loading samples. The sample loader utilizes the routines
provided by the "registered" sample loader. provided by the "registered" sample loader.
@ -56,7 +56,7 @@ typedef struct ITPACK {
int SL_Init(SAMPLOAD* s) int SL_Init(SAMPLOAD* s)
{ {
if(!sl_buffer) if(!sl_buffer)
if(!(sl_buffer=MikMod_malloc(SLBUFSIZE*sizeof(SWORD)))) return 0; if(!(sl_buffer=(SWORD*)MikMod_malloc(SLBUFSIZE*sizeof(SWORD)))) return 0;
sl_rlength = s->length; sl_rlength = s->length;
if(s->infmt & SF_16BITS) sl_rlength>>=1; if(s->infmt & SF_16BITS) sl_rlength>>=1;
@ -68,16 +68,15 @@ int SL_Init(SAMPLOAD* s)
void SL_Exit(SAMPLOAD *s) void SL_Exit(SAMPLOAD *s)
{ {
if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR); if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR);
if(sl_buffer) {
MikMod_free(sl_buffer); MikMod_free(sl_buffer);
sl_buffer=NULL; sl_buffer=NULL;
}
} }
/* unpack a 8bit IT packed sample */ /* unpack a 8bit IT packed sample */
static int read_itcompr8(ITPACK* status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt) static int read_itcompr8(ITPACK* status,MREADER *reader,SWORD *out,UWORD count,UWORD* incnt)
{ {
SWORD *dest=sl_buffer,*end=sl_buffer+count; SWORD *dest=out,*end=out+count;
UWORD x,y,needbits,havebits,new_count=0; UWORD x,y,needbits,havebits,new_count=0;
UWORD bits = status->bits; UWORD bits = status->bits;
UWORD bufbits = status->bufbits; UWORD bufbits = status->bufbits;
@ -145,13 +144,13 @@ static int read_itcompr8(ITPACK* status,MREADER *reader,SWORD *sl_buffer,UWORD c
status->bufbits = bufbits; status->bufbits = bufbits;
status->last = last; status->last = last;
status->buf = buf; status->buf = buf;
return (dest-sl_buffer); return (dest-out);
} }
/* unpack a 16bit IT packed sample */ /* unpack a 16bit IT packed sample */
static int read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt) static int read_itcompr16(ITPACK *status,MREADER *reader,SWORD *out,UWORD count,UWORD* incnt)
{ {
SWORD *dest=sl_buffer,*end=sl_buffer+count; SWORD *dest=out,*end=out+count;
SLONG x,y,needbits,havebits,new_count=0; SLONG x,y,needbits,havebits,new_count=0;
UWORD bits = status->bits; UWORD bits = status->bits;
UWORD bufbits = status->bufbits; UWORD bufbits = status->bufbits;
@ -219,7 +218,7 @@ static int read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD
status->bufbits = bufbits; status->bufbits = bufbits;
status->last = last; status->last = last;
status->buf = buf; status->buf = buf;
return (dest-sl_buffer); return (dest-out);
} }
static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor,ULONG length,MREADER* reader,int dither) static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor,ULONG length,MREADER* reader,int dither)
@ -232,8 +231,10 @@ static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor
ITPACK status; ITPACK status;
UWORD incnt = 0; UWORD incnt = 0;
memset(&status, 0, sizeof(status)); /* initialize status */ status.buf = 0;
status.last = 0;
status.bufbits = 0;
status.bits = 0;
while(length) { while(length) {
stodo=(length<SLBUFSIZE)?length:SLBUFSIZE; stodo=(length<SLBUFSIZE)?length:SLBUFSIZE;
@ -261,6 +262,10 @@ static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor
c_block -= stodo; c_block -= stodo;
} else { } else {
if(infmt&SF_16BITS) { if(infmt&SF_16BITS) {
if(_mm_eof(reader)) {
_mm_errno=MMERR_NOT_A_STREAM;/* better error? */
return 1;
}
if(infmt&SF_BIG_ENDIAN) if(infmt&SF_BIG_ENDIAN)
_mm_read_M_SWORDS(sl_buffer,stodo,reader); _mm_read_M_SWORDS(sl_buffer,stodo,reader);
else else
@ -269,6 +274,10 @@ static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor
SBYTE *src; SBYTE *src;
SWORD *dest; SWORD *dest;
if(_mm_eof(reader)) {
_mm_errno=MMERR_NOT_A_STREAM;/* better error? */
return 1;
}
reader->Read(reader,sl_buffer,sizeof(SBYTE)*stodo); reader->Read(reader,sl_buffer,sizeof(SBYTE)*stodo);
src = (SBYTE*)sl_buffer; src = (SBYTE*)sl_buffer;
dest = sl_buffer; dest = sl_buffer;
@ -417,7 +426,7 @@ static int DitherSamples(SAMPLOAD* samplist,int type)
if(!samplist) return 0; if(!samplist) return 0;
if((maxsize=MD_SampleSpace(type)*1024)) if((maxsize=MD_SampleSpace(type)*1024) != 0)
while(SampleTotal(samplist,type)>maxsize) { while(SampleTotal(samplist,type)>maxsize) {
/* First Pass - check for any 16 bit samples */ /* First Pass - check for any 16 bit samples */
s = samplist; s = samplist;
@ -473,15 +482,15 @@ static int DitherSamples(SAMPLOAD* samplist,int type)
int SL_LoadSamples(void) int SL_LoadSamples(void)
{ {
int ok; int rc;
_mm_critical = 0; _mm_critical = 0;
if((!musiclist)&&(!sndfxlist)) return 0; if((!musiclist)&&(!sndfxlist)) return 0;
ok=DitherSamples(musiclist,MD_MUSIC)||DitherSamples(sndfxlist,MD_SNDFX); rc=DitherSamples(musiclist,MD_MUSIC)||DitherSamples(sndfxlist,MD_SNDFX);
musiclist=sndfxlist=NULL; musiclist=sndfxlist=NULL;
return ok; return rc;
} }
void SL_Sample16to8(SAMPLOAD* s) void SL_Sample16to8(SAMPLOAD* s)
@ -518,5 +527,4 @@ void SL_HalveSample(SAMPLOAD* s,int factor)
s->sample->loopend = s->loopend / s->scalefactor; s->sample->loopend = s->loopend / s->scalefactor;
} }
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -20,7 +20,7 @@
/*============================================================================== /*==============================================================================
$Id: virtch.c,v 1.4 2005/05/18 13:42:23 raphassenat Exp $ $Id$
Sample mixing routines, using a 32 bits mixing buffer. Sample mixing routines, using a 32 bits mixing buffer.
@ -33,22 +33,17 @@
(b) Interpolation of sample data during mixing (b) Interpolation of sample data during mixing
(c) Dolby Surround Sound (c) Dolby Surround Sound
*/ */
#if 0
#include <assert.h>
#endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include <stddef.h>
#ifdef HAVE_MEMORY_H #ifdef HAVE_MEMORY_H
#include <memory.h> #include <memory.h>
#endif #endif
#include <string.h> #include <string.h>
#include "mikmod_internals.h" #include "mikmod_internals.h"
#include "mikmod.h"
/* /*
Constant definitions Constant definitions
@ -130,38 +125,43 @@ static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL,
#else #else
#define NATIVE SLONG #define NATIVE SLONG
#endif #endif
#if defined HAVE_SSE2 || defined HAVE_ALTIVEC #if defined HAVE_SSE2 || defined HAVE_ALTIVEC
static size_t MixSIMDMonoNormal(const SWORD* srce,SLONG* dest,size_t index, size_t increment,size_t todo) # if !defined(NATIVE_64BIT_INT)
static SINTPTR_T MixSIMDMonoNormal(const SWORD* srce,SLONG* dest,SINTPTR_T idx,SINTPTR_T increment,SINTPTR_T todo)
{ {
// TODO: /* TODO: */
SWORD sample; SWORD sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
} }
return index; return idx;
} }
# endif /* !NATIVE_64BIT_INT */
static size_t MixSIMDStereoNormal(const SWORD* srce, SLONG* dest, size_t index, size_t increment,size_t todo) static SINTPTR_T MixSIMDStereoNormal(const SWORD* srce,SLONG* dest,SINTPTR_T idx,SINTPTR_T increment,SINTPTR_T todo)
{ {
SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel}; SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel};
SWORD sample; SWORD sample;
SLONG remain = todo; SLONG remain = todo;
// Dest can be misaligned ... /* Dest can be misaligned */
while(!IS_ALIGNED_16(dest)) { while(!IS_ALIGNED_16(dest)) {
sample=srce[(index += increment) >> FRACBITS]; sample=srce[idx >> FRACBITS];
idx += increment;
*dest++ += vol[0] * sample; *dest++ += vol[0] * sample;
*dest++ += vol[1] * sample; *dest++ += vol[1] * sample;
todo--; todo--;
if(!todo) return idx;
} }
// Srce is always aligned ... /* Srce is always aligned */
#if defined HAVE_SSE2 #if defined HAVE_SSE2
remain = todo&3; remain = todo&3;
@ -172,10 +172,10 @@ static size_t MixSIMDStereoNormal(const SWORD* srce, SLONG* dest, size_t index,
0, vol[0]); 0, vol[0]);
for(todo>>=2;todo; todo--) for(todo>>=2;todo; todo--)
{ {
SWORD s0 = srce[(index += increment) >> FRACBITS]; SWORD s0 = srce[idx >> FRACBITS];
SWORD s1 = srce[(index += increment) >> FRACBITS]; SWORD s1 = srce[(idx += increment) >> FRACBITS];
SWORD s2 = srce[(index += increment) >> FRACBITS]; SWORD s2 = srce[(idx += increment) >> FRACBITS];
SWORD s3 = srce[(index += increment) >> FRACBITS]; SWORD s3 = srce[(idx += increment) >> FRACBITS];
__m128i v1 = _mm_set_epi16(0, s1, 0, s1, 0, s0, 0, s0); __m128i v1 = _mm_set_epi16(0, s1, 0, s1, 0, s0, 0, s0);
__m128i v2 = _mm_set_epi16(0, s3, 0, s3, 0, s2, 0, s2); __m128i v2 = _mm_set_epi16(0, s3, 0, s3, 0, s2, 0, s2);
__m128i v3 = _mm_load_si128((__m128i*)(dest+0)); __m128i v3 = _mm_load_si128((__m128i*)(dest+0));
@ -183,86 +183,94 @@ static size_t MixSIMDStereoNormal(const SWORD* srce, SLONG* dest, size_t index,
_mm_store_si128((__m128i*)(dest+0), _mm_add_epi32(v3, _mm_madd_epi16(v0, v1))); _mm_store_si128((__m128i*)(dest+0), _mm_add_epi32(v3, _mm_madd_epi16(v0, v1)));
_mm_store_si128((__m128i*)(dest+4), _mm_add_epi32(v4, _mm_madd_epi16(v0, v2))); _mm_store_si128((__m128i*)(dest+4), _mm_add_epi32(v4, _mm_madd_epi16(v0, v2)));
dest+=8; dest+=8;
idx += increment;
} }
} }
#elif defined HAVE_ALTIVEC #elif defined HAVE_ALTIVEC
remain = todo&3; remain = todo&3;
{ {
vector signed short r0 = vec_ld(0, vol);
vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, // l
0, 1, // l
2, 3, // r
2, 1, // r
0, 1, // l
0, 1, // l
2, 3, // r
2, 3 // r
));
SWORD s[8]; SWORD s[8];
vector signed short r0 = vec_ld(0, vol);
vector signed short v0 = vec_perm(r0, r0, (vector unsigned char)(0, 1, /* l */
0, 1, /* l */
2, 3, /* r */
2, 1, /* r */
0, 1, /* l */
0, 1, /* l */
2, 3, /* r */
2, 3 /* r */
));
for(todo>>=2;todo; todo--) for(todo>>=2;todo; todo--)
{ {
// Load constants vector short int r1;
s[0] = srce[(index += increment) >> FRACBITS]; vector signed short v1, v2;
s[1] = srce[(index += increment) >> FRACBITS]; vector signed int v3, v4, v5, v6;
s[2] = srce[(index += increment) >> FRACBITS];
s[3] = srce[(index += increment) >> FRACBITS]; /* Load constants */
s[0] = srce[idx >> FRACBITS];
s[1] = srce[(idx += increment) >> FRACBITS];
s[2] = srce[(idx += increment) >> FRACBITS];
s[3] = srce[(idx += increment) >> FRACBITS];
s[4] = 0; s[4] = 0;
vector short int r1 = vec_ld(0, s); r1 = vec_ld(0, s);
vector signed short v1 = vec_perm(r1, r1, (vector unsigned char)(0*2, 0*2+1, // s0 v1 = vec_perm(r1, r1, (vector unsigned char)
4*2, 4*2+1, // 0 (0*2, 0*2+1, /* s0 */
0*2, 0*2+1, // s0 4*2, 4*2+1, /* 0 */
4*2, 4*2+1, // 0 0*2, 0*2+1, /* s0 */
1*2, 1*2+1, // s1 4*2, 4*2+1, /* 0 */
4*2, 4*2+1, // 0 1*2, 1*2+1, /* s1 */
1*2, 1*2+1, // s1 4*2, 4*2+1, /* 0 */
4*2, 4*2+1 // 0 1*2, 1*2+1, /* s1 */
)); 4*2, 4*2+1 /* 0 */
) );
v2 = vec_perm(r1, r1, (vector unsigned char)
(2*2, 2*2+1, /* s2 */
4*2, 4*2+1, /* 0 */
2*2, 2*2+1, /* s2 */
4*2, 4*2+1, /* 0 */
3*2, 3*2+1, /* s3 */
4*2, 4*2+1, /* 0 */
3*2, 3*2+1, /* s3 */
4*2, 4*2+1 /* 0 */
) );
vector signed short v2 = vec_perm(r1, r1, (vector unsigned char)(2*2, 2*2+1, // s2 v3 = vec_ld(0, dest);
4*2, 4*2+1, // 0 v4 = vec_ld(0, dest + 4);
2*2, 2*2+1, // s2 v5 = vec_mule(v0, v1);
4*2, 4*2+1, // 0 v6 = vec_mule(v0, v2);
3*2, 3*2+1, // s3
4*2, 4*2+1, // 0
3*2, 3*2+1, // s3
4*2, 4*2+1 // 0
));
vector signed int v3 = vec_ld(0, dest);
vector signed int v4 = vec_ld(0, dest + 4);
vector signed int v5 = vec_mule(v0, v1);
vector signed int v6 = vec_mule(v0, v2);
vec_st(vec_add(v3, v5), 0, dest); vec_st(vec_add(v3, v5), 0, dest);
vec_st(vec_add(v4, v6), 0x10, dest); vec_st(vec_add(v4, v6), 0x10, dest);
dest+=8; dest+=8;
idx += increment;
} }
} }
#endif // HAVE_ALTIVEC #endif /* HAVE_ALTIVEC */
// Remaining bits ... /* Remaining bits */
while(remain--) { while(remain--) {
sample=srce[(index += increment) >> FRACBITS]; sample=srce[idx >> FRACBITS];
idx += increment;
*dest++ += vol[0] * sample; *dest++ += vol[0] * sample;
*dest++ += vol[1] * sample; *dest++ += vol[1] * sample;
} }
return index; return idx;
} }
#endif #endif
/*========== 32 bit sample mixers - only for 32 bit platforms */ /*========== 32 bit sample mixers - only for 32 bit platforms */
#ifndef NATIVE_64BIT_INT #ifndef NATIVE_64BIT_INT
static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
{ {
#if defined HAVE_ALTIVEC || defined HAVE_SSE2 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
if (md_mode & DMODE_SIMDMIXER) if (md_mode & DMODE_SIMDMIXER) {
{ return MixSIMDMonoNormal(srce, dest, idx, increment, todo);
return MixSIMDMonoNormal(srce, dest, index, increment, todo);
} }
else else
#endif #endif
@ -271,23 +279,22 @@ static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG inc
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
} }
} }
return index; return idx;
} }
// FIXME: This mixer should works also on 64-bit platform /* FIXME: This mixer should works also on 64-bit platform */
// Hint : changes SLONG / SLONGLONG mess with size_t /* Hint : changes SLONG / SLONGLONG mess with intptr */
static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
{ {
#if defined HAVE_ALTIVEC || defined HAVE_SSE2 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
if (md_mode & DMODE_SIMDMIXER) if (md_mode & DMODE_SIMDMIXER) {
{ return MixSIMDStereoNormal(srce, dest, idx, increment, todo);
return MixSIMDStereoNormal(srce, dest, index, increment, todo);
} }
else else
#endif #endif
@ -297,17 +304,17 @@ static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG i
SLONG rvolsel = vnf->rvolsel; SLONG rvolsel = vnf->rvolsel;
while(todo--) { while(todo--) {
sample=srce[(index += increment) >> FRACBITS]; sample=srce[idx >> FRACBITS];
idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
*dest++ += rvolsel * sample; *dest++ += rvolsel * sample;
} }
} }
return index; return idx;
} }
static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
{ {
SWORD sample; SWORD sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -315,25 +322,26 @@ static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG
if (lvolsel>=rvolsel) { if (lvolsel>=rvolsel) {
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel*sample; *dest++ += lvolsel*sample;
*dest++ -= lvolsel*sample; *dest++ -= lvolsel*sample;
} }
} else { }
else {
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ -= rvolsel*sample; *dest++ -= rvolsel*sample;
*dest++ += rvolsel*sample; *dest++ += rvolsel*sample;
} }
} }
return index; return idx;
} }
static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -342,10 +350,10 @@ static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG inc
if (rampvol) { if (rampvol) {
SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldlvol = vnf->oldlvol - lvolsel;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -354,21 +362,21 @@ static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG inc
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
} }
return index; return idx;
} }
static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -379,10 +387,10 @@ static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG i
SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldlvol = vnf->oldlvol - lvolsel;
SLONG oldrvol = vnf->oldrvol - rvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -393,22 +401,22 @@ static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG i
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
*dest++ += rvolsel * sample; *dest++ += rvolsel * sample;
} }
return index; return idx;
} }
static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -427,10 +435,10 @@ static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG
if (rampvol) { if (rampvol) {
oldvol -= vol; oldvol -= vol;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
sample=((vol << CLICK_SHIFT) + oldvol * rampvol) sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -442,55 +450,55 @@ static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += vol*sample; *dest++ += vol*sample;
*dest++ -= vol*sample; *dest++ -= vol*sample;
} }
return index; return idx;
} }
#endif #endif
/*========== 64 bit sample mixers - all platforms */ /*========== 64 bit sample mixers - all platforms */
static SLONGLONG MixMonoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixMonoNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SWORD sample; SWORD sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
} }
return index; return idx;
} }
static SLONGLONG MixStereoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixStereoNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SWORD sample; SWORD sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
SLONG rvolsel = vnf->rvolsel; SLONG rvolsel = vnf->rvolsel;
while(todo--) { while(todo--) {
sample=srce[index >> FRACBITS]; sample=srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
*dest++ += rvolsel * sample; *dest++ += rvolsel * sample;
} }
return index; return idx;
} }
static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SWORD sample; SWORD sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -498,25 +506,26 @@ static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG index
if(vnf->lvolsel>=vnf->rvolsel) { if(vnf->lvolsel>=vnf->rvolsel) {
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ += lvolsel*sample; *dest++ += lvolsel*sample;
*dest++ -= lvolsel*sample; *dest++ -= lvolsel*sample;
} }
} else { }
else {
while(todo--) { while(todo--) {
sample = srce[index >> FRACBITS]; sample = srce[idx >> FRACBITS];
index += increment; idx += increment;
*dest++ -= rvolsel*sample; *dest++ -= rvolsel*sample;
*dest++ += rvolsel*sample; *dest++ += rvolsel*sample;
} }
} }
return index; return idx;
} }
static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -525,10 +534,10 @@ static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLO
if (rampvol) { if (rampvol) {
SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldlvol = vnf->oldlvol - lvolsel;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -537,21 +546,21 @@ static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLO
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
} }
return index; return idx;
} }
static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -562,10 +571,10 @@ static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,S
SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldlvol = vnf->oldlvol - lvolsel;
SLONG oldrvol = vnf->oldrvol - rvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) *dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -576,22 +585,22 @@ static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,S
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += lvolsel * sample; *dest++ += lvolsel * sample;
*dest++ += rvolsel * sample; *dest++ += rvolsel * sample;
} }
return index; return idx;
} }
static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo)
{ {
SLONG sample; SLONG sample;
SLONG lvolsel = vnf->lvolsel; SLONG lvolsel = vnf->lvolsel;
@ -610,10 +619,10 @@ static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index
if (rampvol) { if (rampvol) {
oldvol -= vol; oldvol -= vol;
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
sample=((vol << CLICK_SHIFT) + oldvol * rampvol) sample=((vol << CLICK_SHIFT) + oldvol * rampvol)
* sample >> CLICK_SHIFT; * sample >> CLICK_SHIFT;
@ -624,19 +633,19 @@ static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index
} }
vnf->rampvol = rampvol; vnf->rampvol = rampvol;
if (todo < 0) if (todo < 0)
return index; return idx;
} }
while(todo--) { while(todo--) {
sample=(SLONG)srce[index>>FRACBITS]+ sample=(SLONG)srce[idx>>FRACBITS]+
((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS])
*(index&FRACMASK)>>FRACBITS); *(idx&FRACMASK)>>FRACBITS);
index += increment; idx += increment;
*dest++ += vol*sample; *dest++ += vol*sample;
*dest++ -= vol*sample; *dest++ -= vol*sample;
} }
return index; return idx;
} }
static void (*MixReverb)(SLONG* srce,NATIVE count); static void (*MixReverb)(SLONG* srce,NATIVE count);
@ -839,57 +848,55 @@ static void Mix32To8(SBYTE* dste,const SLONG *srce,NATIVE count)
#if defined HAVE_ALTIVEC || defined HAVE_SSE2 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
// Mix 32bit input to floating point. 32 samples per iteration /* Mix 32bit input to floating point. 32 samples per iteration */
// PC: ?, Mac OK /* PC: ?, Mac OK */
static void Mix32ToFP_SIMD(float* dste,SLONG* srce,NATIVE count) static void Mix32ToFP_SIMD(float* dste,const SLONG* srce,NATIVE count)
{ {
const float k = ((1.0f / 32768.0f) / (1 << FP_SHIFT));
int remain=count; int remain=count;
simd_m128 x1, x2, xk;
while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce)) while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce))
{ {
float x1; float xf;
EXTRACT_SAMPLE_FP(x1,FP_SHIFT); EXTRACT_SAMPLE_FP(xf,FP_SHIFT);
CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(xf,1.0f);
PUT_SAMPLE_FP(x1); PUT_SAMPLE_FP(xf);
count--; count--;
if (!count) if (!count) return;
{
return;
}
} }
remain = count&7; remain = count&7;
const float k = ((1.0f / 32768.0f) / (1 << FP_SHIFT)); xk = LOAD_PS1_SIMD(&k); /* Scale factor */
simd_m128 x1, x2;
simd_m128 xk = LOAD_PS1_SIMD(&k); // Scale factor
for(count>>=3;count;count--) { for(count>>=3;count;count--) {
EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); // Load 4 samples EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); /* Load 4 samples */
EXTRACT_SAMPLE_SIMD_F(srce+4, x2, FP_SHIFT, xk); // Load 4 samples EXTRACT_SAMPLE_SIMD_F(srce+4, x2, FP_SHIFT, xk); /* Load 4 samples */
PUT_SAMPLE_SIMD_F(dste, x1); // Store 4 samples PUT_SAMPLE_SIMD_F(dste, x1); /* Store 4 samples */
PUT_SAMPLE_SIMD_F(dste+4, x2); // Store 4 samples PUT_SAMPLE_SIMD_F(dste+4, x2); /* Store 4 samples */
srce+=8; srce+=8;
dste+=8; dste+=8;
} }
if (remain&4) { if (remain&4) {
EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); // Load 4 samples EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); /* Load 4 samples */
PUT_SAMPLE_SIMD_F(dste, x1); // Store 4 samples PUT_SAMPLE_SIMD_F(dste, x1); /* Store 4 samples */
srce+=4; srce+=4;
dste+=4; dste+=4;
remain &= 3; remain &= 3;
} }
while(remain--) { while(remain--) {
float x1; float xf;
EXTRACT_SAMPLE_FP(x1,FP_SHIFT); EXTRACT_SAMPLE_FP(xf,FP_SHIFT);
CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(xf,1.0f);
PUT_SAMPLE_FP(x1); PUT_SAMPLE_FP(xf);
} }
} }
// PC: Ok, Mac Ok
static void Mix32To16_SIMD(SWORD* dste,SLONG* srce,NATIVE count) /* PC: Ok, Mac Ok */
static void Mix32To16_SIMD(SWORD* dste,const SLONG* srce,NATIVE count)
{ {
int remain = count; int remain = count;
@ -900,10 +907,7 @@ static void Mix32To16_SIMD(SWORD* dste,SLONG* srce,NATIVE count)
CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x1,32768);
PUT_SAMPLE(x1); PUT_SAMPLE(x1);
count--; count--;
if (!count) if (!count) return;
{
return;
}
} }
remain = count&7; remain = count&7;
@ -911,9 +915,9 @@ static void Mix32To16_SIMD(SWORD* dste,SLONG* srce,NATIVE count)
for(count>>=3;count;count--) for(count>>=3;count;count--)
{ {
simd_m128i x1,x2; simd_m128i x1,x2;
EXTRACT_SAMPLE_SIMD_16(srce, x1); // Load 4 samples EXTRACT_SAMPLE_SIMD_16(srce, x1); /* Load 4 samples */
EXTRACT_SAMPLE_SIMD_16(srce+4, x2); // Load 4 samples EXTRACT_SAMPLE_SIMD_16(srce+4, x2); /* Load 4 samples */
PUT_SAMPLE_SIMD_W(dste, x1, x2); // Store 8 samples PUT_SAMPLE_SIMD_W(dste, x1, x2); /* Store 8 samples */
srce+=8; srce+=8;
dste+=8; dste+=8;
} }
@ -922,9 +926,9 @@ static void Mix32To16_SIMD(SWORD* dste,SLONG* srce,NATIVE count)
Mix32To16(dste, srce, remain); Mix32To16(dste, srce, remain);
} }
// Mix 32bit input to 8bit. 128 samples per iteration /* Mix 32bit input to 8bit. 128 samples per iteration */
// PC:OK, Mac: Ok /* PC:OK, Mac: Ok */
static void Mix32To8_SIMD(SBYTE* dste,SLONG* srce,NATIVE count) static void Mix32To8_SIMD(SBYTE* dste,const SLONG* srce,NATIVE count)
{ {
int remain=count; int remain=count;
@ -935,24 +939,22 @@ static void Mix32To8_SIMD(SBYTE* dste,SLONG* srce,NATIVE count)
CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x1,128);
PUT_SAMPLE(x1+128); PUT_SAMPLE(x1+128);
count--; count--;
if (!count) if (!count) return;
{
return;
}
} }
remain = count&15; remain = count&15;
for(count>>=4;count;count--) { for(count>>=4;count;count--) {
simd_m128i x1,x2,x3,x4; simd_m128i x1,x2,x3,x4;
EXTRACT_SAMPLE_SIMD_8(srce, x1); // Load 4 samples EXTRACT_SAMPLE_SIMD_8(srce, x1); /* Load 4 samples */
EXTRACT_SAMPLE_SIMD_8(srce+4, x2); // Load 4 samples EXTRACT_SAMPLE_SIMD_8(srce+4, x2); /* Load 4 samples */
EXTRACT_SAMPLE_SIMD_8(srce+8, x3); // Load 4 samples EXTRACT_SAMPLE_SIMD_8(srce+8, x3); /* Load 4 samples */
EXTRACT_SAMPLE_SIMD_8(srce+12, x4); // Load 4 samples EXTRACT_SAMPLE_SIMD_8(srce+12, x4); /* Load 4 samples */
PUT_SAMPLE_SIMD_B(dste, x1, x2, x3, x4); // Store 16 samples PUT_SAMPLE_SIMD_B(dste, x1, x2, x3, x4); /* Store 16 samples */
srce+=16; srce+=16;
dste+=16; dste+=16;
} }
if (remain) if (remain)
Mix32To8(dste, srce, remain); Mix32To8(dste, srce, remain);
} }
@ -960,7 +962,6 @@ static void Mix32To8_SIMD(SBYTE* dste,SLONG* srce,NATIVE count)
#endif #endif
static void AddChannel(SLONG* ptr,NATIVE todo) static void AddChannel(SLONG* ptr,NATIVE todo)
{ {
SLONGLONG end,done; SLONGLONG end,done;
@ -1067,7 +1068,6 @@ static void AddChannel(SLONG* ptr,NATIVE todo)
if (md_mode & DMODE_SIMDMIXER) if (md_mode & DMODE_SIMDMIXER)
vnf->current=MixSIMDStereoNormal vnf->current=MixSIMDStereoNormal
(s,ptr,vnf->current,vnf->increment,done); (s,ptr,vnf->current,vnf->increment,done);
else else
#endif #endif
vnf->current=Mix32StereoNormal vnf->current=Mix32StereoNormal
@ -1076,7 +1076,8 @@ static void AddChannel(SLONG* ptr,NATIVE todo)
} else } else
vnf->current=Mix32MonoNormal vnf->current=Mix32MonoNormal
(s,ptr,vnf->current,vnf->increment,done); (s,ptr,vnf->current,vnf->increment,done);
} else }
else
#endif #endif
{ {
if((md_mode & DMODE_INTERP)) { if((md_mode & DMODE_INTERP)) {
@ -1100,7 +1101,6 @@ static void AddChannel(SLONG* ptr,NATIVE todo)
if (md_mode & DMODE_SIMDMIXER) if (md_mode & DMODE_SIMDMIXER)
vnf->current=MixSIMDStereoNormal vnf->current=MixSIMDStereoNormal
(s,ptr,vnf->current,vnf->increment,done); (s,ptr,vnf->current,vnf->increment,done);
else else
#endif #endif
vnf->current=MixStereoNormal vnf->current=MixStereoNormal
@ -1119,6 +1119,33 @@ static void AddChannel(SLONG* ptr,NATIVE todo)
} }
} }
#ifdef NO_HQMIXER
#define VC_SetupPointers() do{}while(0)
#define VC1_Init VC_Init
#define VC1_Exit VC_Exit
#define VC1_PlayStart VC_PlayStart
#define VC1_PlayStop VC_PlayStop
#define VC1_SampleLength VC_SampleLength
#define VC1_SampleSpace VC_SampleSpace
#define VC1_SampleLoad VC_SampleLoad
#define VC1_SampleUnload VC_SampleUnload
#define VC1_SetNumVoices VC_SetNumVoices
#define VC1_SilenceBytes VC_SilenceBytes
#define VC1_VoicePlay VC_VoicePlay
#define VC1_VoiceStop VC_VoiceStop
#define VC1_VoiceGetFrequency VC_VoiceGetFrequency
#define VC1_VoiceGetPanning VC_VoiceGetPanning
#define VC1_VoiceGetPosition VC_VoiceGetPosition
#define VC1_VoiceGetVolume VC_VoiceGetVolume
#define VC1_VoiceRealVolume VC_VoiceRealVolume
#define VC1_VoiceSetFrequency VC_VoiceSetFrequency
#define VC1_VoiceSetPanning VC_VoiceSetPanning
#define VC1_VoiceSetVolume VC_VoiceSetVolume
#define VC1_VoiceStopped VC_VoiceStopped
#define VC1_WriteBytes VC_WriteBytes
#define VC1_WriteSamples VC_WriteSamples
#endif
#define _IN_VIRTCH_ #define _IN_VIRTCH_
#include "virtch_common.c" #include "virtch_common.c"
#undef _IN_VIRTCH_ #undef _IN_VIRTCH_
@ -1190,7 +1217,6 @@ void VC1_WriteSamples(SBYTE* buf,ULONG todo)
vc_callback((unsigned char*)vc_tickbuf, portion); vc_callback((unsigned char*)vc_tickbuf, portion);
} }
#if defined HAVE_ALTIVEC || defined HAVE_SSE2 #if defined HAVE_ALTIVEC || defined HAVE_SSE2
if (md_mode & DMODE_SIMDMIXER) if (md_mode & DMODE_SIMDMIXER)
{ {
@ -1219,20 +1245,23 @@ void VC1_WriteSamples(SBYTE* buf,ULONG todo)
int VC1_Init(void) int VC1_Init(void)
{ {
#ifndef NO_HQMIXER
VC_SetupPointers(); VC_SetupPointers();
//if (md_mode&DMODE_HQMIXER) if (md_mode&DMODE_HQMIXER)
// return VC2_Init(); return VC2_Init();
#endif
if(!(Samples=(SWORD**)MikMod_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) { if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) {
_mm_errno = MMERR_INITIALIZING_MIXER; _mm_errno = MMERR_INITIALIZING_MIXER;
return 1; return 1;
} }
if(!vc_tickbuf) if(!vc_tickbuf) {
if(!(vc_tickbuf=(SLONG*)MikMod_malloc((TICKLSIZE+32)*sizeof(SLONG)))) { if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) {
_mm_errno = MMERR_INITIALIZING_MIXER; _mm_errno = MMERR_INITIALIZING_MIXER;
return 1; return 1;
} }
}
MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal; MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal;
MixLowPass=(md_mode&DMODE_STEREO)?MixLowPass_Stereo:MixLowPass_Normal; MixLowPass=(md_mode&DMODE_STEREO)?MixLowPass_Stereo:MixLowPass_Normal;
@ -1264,6 +1293,8 @@ int VC1_PlayStart(void)
if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1;
if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1;
/* allocate reverb buffers for the right channel if in stereo mode only. */
if (vc_mode & DMODE_STEREO) {
if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1;
if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1;
if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1;
@ -1272,6 +1303,7 @@ int VC1_PlayStart(void)
if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1;
if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1;
if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1;
}
RVRindex = 0; RVRindex = 0;
return 0; return 0;
@ -1279,23 +1311,23 @@ int VC1_PlayStart(void)
void VC1_PlayStop(void) void VC1_PlayStop(void)
{ {
if(RVbufL1) MikMod_free(RVbufL1); MikMod_free(RVbufL1);
if(RVbufL2) MikMod_free(RVbufL2); MikMod_free(RVbufL2);
if(RVbufL3) MikMod_free(RVbufL3); MikMod_free(RVbufL3);
if(RVbufL4) MikMod_free(RVbufL4); MikMod_free(RVbufL4);
if(RVbufL5) MikMod_free(RVbufL5); MikMod_free(RVbufL5);
if(RVbufL6) MikMod_free(RVbufL6); MikMod_free(RVbufL6);
if(RVbufL7) MikMod_free(RVbufL7); MikMod_free(RVbufL7);
if(RVbufL8) MikMod_free(RVbufL8); MikMod_free(RVbufL8);
RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL;
if(RVbufR1) MikMod_free(RVbufR1); MikMod_free(RVbufR1);
if(RVbufR2) MikMod_free(RVbufR2); MikMod_free(RVbufR2);
if(RVbufR3) MikMod_free(RVbufR3); MikMod_free(RVbufR3);
if(RVbufR4) MikMod_free(RVbufR4); MikMod_free(RVbufR4);
if(RVbufR5) MikMod_free(RVbufR5); MikMod_free(RVbufR5);
if(RVbufR6) MikMod_free(RVbufR6); MikMod_free(RVbufR6);
if(RVbufR7) MikMod_free(RVbufR7); MikMod_free(RVbufR7);
if(RVbufR8) MikMod_free(RVbufR8); MikMod_free(RVbufR8);
RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL;
} }
@ -1305,8 +1337,8 @@ int VC1_SetNumVoices(void)
if(!(vc_softchn=md_softchn)) return 0; if(!(vc_softchn=md_softchn)) return 0;
if(vinf) MikMod_free(vinf); MikMod_free(vinf);
if(!(vinf= MikMod_calloc(sizeof(VINFO),vc_softchn))) return 1; if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1;
for(t=0;t<vc_softchn;t++) { for(t=0;t<vc_softchn;t++) {
vinf[t].frq=10000; vinf[t].frq=10000;

File diff suppressed because it is too large Load diff

View file

@ -20,90 +20,96 @@
/*============================================================================== /*==============================================================================
$Id: virtch_common.c,v 1.2 2005/03/30 19:11:50 realtech Exp $ $Id$
Common source parts between the two software mixers. Common source parts between the two software mixers.
This file is probably the ugliest part of libmikmod... This file is probably the ugliest part of libmikmod...
==============================================================================*/ ==============================================================================*/
#ifndef _IN_VIRTCH_ #if defined(HAVE_CONFIG_H) && !defined(_IN_VIRTCH_) /* config.h isn't guarded */
#include "config.h"
#endif
#include "mikmod_internals.h" #include "mikmod_internals.h"
extern int VC1_Init(void); #ifndef NO_HQMIXER
//extern int VC2_Init(void); extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
static int (*VC_Init_ptr)(void)=VC1_Init; extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
extern void VC1_Exit(void); extern void VC1_Exit(void);
//extern void VC2_Exit(void); extern void VC2_Exit(void);
extern UWORD VC1_VoiceGetVolume(UBYTE);
extern UWORD VC2_VoiceGetVolume(UBYTE);
extern ULONG VC1_VoiceGetPanning(UBYTE);
extern ULONG VC2_VoiceGetPanning(UBYTE);
extern void VC1_VoiceSetFrequency(UBYTE,ULONG);
extern void VC2_VoiceSetFrequency(UBYTE,ULONG);
extern ULONG VC1_VoiceGetFrequency(UBYTE);
extern ULONG VC2_VoiceGetFrequency(UBYTE);
extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
extern void VC1_VoiceStop(UBYTE);
extern void VC2_VoiceStop(UBYTE);
extern int VC1_VoiceStopped(UBYTE);
extern int VC2_VoiceStopped(UBYTE);
extern SLONG VC1_VoiceGetPosition(UBYTE);
extern SLONG VC2_VoiceGetPosition(UBYTE);
extern void VC1_VoiceSetVolume(UBYTE,UWORD);
extern void VC2_VoiceSetVolume(UBYTE,UWORD);
extern void VC1_VoiceSetPanning(UBYTE,ULONG);
extern void VC2_VoiceSetPanning(UBYTE,ULONG);
extern void VC1_SampleUnload(SWORD);
extern void VC2_SampleUnload(SWORD);
extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
extern ULONG VC1_SampleSpace(int);
extern ULONG VC2_SampleSpace(int);
extern ULONG VC1_SampleLength(int,SAMPLE*);
extern ULONG VC2_SampleLength(int,SAMPLE*);
extern ULONG VC1_VoiceRealVolume(UBYTE);
extern ULONG VC2_VoiceRealVolume(UBYTE);
#endif
#ifndef _IN_VIRTCH_
#ifndef NO_HQMIXER
extern int VC1_Init(void);
extern int VC2_Init(void);
static int (*VC_Init_ptr)(void)=VC1_Init;
static void (*VC_Exit_ptr)(void)=VC1_Exit; static void (*VC_Exit_ptr)(void)=VC1_Exit;
extern int VC1_SetNumVoices(void); extern int VC1_SetNumVoices(void);
//extern int VC2_SetNumVoices(void); extern int VC2_SetNumVoices(void);
static int (*VC_SetNumVoices_ptr)(void); static int (*VC_SetNumVoices_ptr)(void);
extern ULONG VC1_SampleSpace(int);
//extern ULONG VC2_SampleSpace(int);
static ULONG (*VC_SampleSpace_ptr)(int); static ULONG (*VC_SampleSpace_ptr)(int);
extern ULONG VC1_SampleLength(int,SAMPLE*);
//extern ULONG VC2_SampleLength(int,SAMPLE*);
static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*); static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*);
extern int VC1_PlayStart(void); extern int VC2_PlayStart(void);
//extern int VC2_PlayStart(void);
static int (*VC_PlayStart_ptr)(void); static int (*VC_PlayStart_ptr)(void);
extern void VC1_PlayStop(void);
extern void VC2_PlayStop(void); extern void VC2_PlayStop(void);
static void (*VC_PlayStop_ptr)(void); static void (*VC_PlayStop_ptr)(void);
extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
//extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int); static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int);
extern void VC1_SampleUnload(SWORD);
//extern void VC2_SampleUnload(SWORD);
static void (*VC_SampleUnload_ptr)(SWORD); static void (*VC_SampleUnload_ptr)(SWORD);
extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
//extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG); static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG);
extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
//extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG); static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG);
extern void VC1_VoiceSetVolume(UBYTE,UWORD);
//extern void VC2_VoiceSetVolume(UBYTE,UWORD);
static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD); static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD);
extern UWORD VC1_VoiceGetVolume(UBYTE);
//extern UWORD VC2_VoiceGetVolume(UBYTE);
static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE); static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE);
extern void VC1_VoiceSetFrequency(UBYTE,ULONG);
//extern void VC2_VoiceSetFrequency(UBYTE,ULONG);
static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG); static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG);
extern ULONG VC1_VoiceGetFrequency(UBYTE);
//extern ULONG VC2_VoiceGetFrequency(UBYTE);
static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE); static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE);
extern void VC1_VoiceSetPanning(UBYTE,ULONG);
//extern void VC2_VoiceSetPanning(UBYTE,ULONG);
static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG); static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG);
extern ULONG VC1_VoiceGetPanning(UBYTE);
//extern ULONG VC2_VoiceGetPanning(UBYTE);
static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE); static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE);
extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
//extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
extern void VC1_VoiceStop(UBYTE);
//extern void VC2_VoiceStop(UBYTE);
static void (*VC_VoiceStop_ptr)(UBYTE); static void (*VC_VoiceStop_ptr)(UBYTE);
extern int VC1_VoiceStopped(UBYTE);
//extern int VC2_VoiceStopped(UBYTE);
static int (*VC_VoiceStopped_ptr)(UBYTE); static int (*VC_VoiceStopped_ptr)(UBYTE);
extern SLONG VC1_VoiceGetPosition(UBYTE);
//extern SLONG VC2_VoiceGetPosition(UBYTE);
static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE); static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE);
extern ULONG VC1_VoiceRealVolume(UBYTE);
//extern ULONG VC2_VoiceRealVolume(UBYTE);
static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE); static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE);
#if defined __STDC__ || defined _MSC_VER || defined MPW_C #if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
#define VC_PROC0(suffix) \ #define VC_PROC0(suffix) \
MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); } MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); }
@ -121,7 +127,9 @@ MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
#define VC_FUNC2(suffix,ret,typ1,typ2) \ #define VC_FUNC2(suffix,ret,typ1,typ2) \
MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); } MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
#else #else
#define VC_PROC0(suffix) \ #define VC_PROC0(suffix) \
MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); } MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); }
@ -159,8 +167,9 @@ VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE)
VC_PROC2(VoiceSetPanning,UBYTE,ULONG) VC_PROC2(VoiceSetPanning,UBYTE,ULONG)
VC_FUNC1(VoiceGetPanning,ULONG,UBYTE) VC_FUNC1(VoiceGetPanning,ULONG,UBYTE)
void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g) void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g) {
{ VC_VoicePlay_ptr(a,b,c,d,e,f,g); } VC_VoicePlay_ptr(a,b,c,d,e,f,g);
}
VC_PROC1(VoiceStop,UBYTE) VC_PROC1(VoiceStop,UBYTE)
VC_FUNC1(VoiceStopped,int,UBYTE) VC_FUNC1(VoiceStopped,int,UBYTE)
@ -169,7 +178,6 @@ VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
void VC_SetupPointers(void) void VC_SetupPointers(void)
{ {
/*
if (md_mode&DMODE_HQMIXER) { if (md_mode&DMODE_HQMIXER) {
VC_Init_ptr=VC2_Init; VC_Init_ptr=VC2_Init;
VC_Exit_ptr=VC2_Exit; VC_Exit_ptr=VC2_Exit;
@ -194,7 +202,6 @@ void VC_SetupPointers(void)
VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition; VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition;
VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume; VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume;
} else { } else {
*/
VC_Init_ptr=VC1_Init; VC_Init_ptr=VC1_Init;
VC_Exit_ptr=VC1_Exit; VC_Exit_ptr=VC1_Exit;
VC_SetNumVoices_ptr=VC1_SetNumVoices; VC_SetNumVoices_ptr=VC1_SetNumVoices;
@ -217,10 +224,11 @@ void VC_SetupPointers(void)
VC_VoiceStopped_ptr=VC1_VoiceStopped; VC_VoiceStopped_ptr=VC1_VoiceStopped;
VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition; VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition;
VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume; VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume;
//} }
} }
#endif/* !NO_HQMIXER */
#else #else /* _IN_VIRTCH_ */
#ifndef _VIRTCH_COMMON_ #ifndef _VIRTCH_COMMON_
#define _VIRTCH_COMMON_ #define _VIRTCH_COMMON_
@ -248,9 +256,7 @@ ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
todo=samples2bytes(bytes2samples(todo)); todo=samples2bytes(bytes2samples(todo));
/* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */ /* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
if(vc_mode & DMODE_FLOAT) if(vc_mode &(DMODE_16BITS|DMODE_FLOAT))
memset(buf,0,todo);
else if(vc_mode & DMODE_16BITS)
memset(buf,0,todo); memset(buf,0,todo);
else else
memset(buf,0x80,todo); memset(buf,0x80,todo);
@ -276,9 +282,9 @@ ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
void VC1_Exit(void) void VC1_Exit(void)
{ {
if(vc_tickbuf) MikMod_free(vc_tickbuf); MikMod_free(vinf);
if(vinf) MikMod_free(vinf); MikMod_afree(vc_tickbuf);
if(Samples) MikMod_free(Samples); MikMod_afree(Samples);
vc_tickbuf = NULL; vc_tickbuf = NULL;
vinf = NULL; vinf = NULL;
@ -353,9 +359,8 @@ void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
void VC1_SampleUnload(SWORD handle) void VC1_SampleUnload(SWORD handle)
{ {
if (handle<MAXSAMPLEHANDLES) { if (Samples && (handle < MAXSAMPLEHANDLES)) {
if (Samples[handle]) MikMod_afree(Samples[handle]);
MikMod_free(Samples[handle]);
Samples[handle]=NULL; Samples[handle]=NULL;
} }
} }
@ -364,10 +369,15 @@ SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
{ {
SAMPLE *s = sload->sample; SAMPLE *s = sload->sample;
int handle; int handle;
ULONG t, length,loopstart,loopend; ULONG t, length,loopstart,loopend,looplen;
if(type==MD_HARDWARE) return -1; if(type==MD_HARDWARE) return -1;
if(s->length > MAX_SAMPLE_SIZE) {
_mm_errno = MMERR_NOT_A_STREAM; /* better error? */
return -1;
}
/* Find empty slot to put sample address in */ /* Find empty slot to put sample address in */
for(handle=0;handle<MAXSAMPLEHANDLES;handle++) for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
if(!Samples[handle]) break; if(!Samples[handle]) break;
@ -390,22 +400,26 @@ SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
SL_SampleSigned(sload); SL_SampleSigned(sload);
SL_Sample8to16(sload); SL_Sample8to16(sload);
if(!(Samples[handle]=(SWORD*)MikMod_malloc((length+20)<<1))) { if(!(Samples[handle]=(SWORD*)MikMod_amalloc((length+20)<<1))) {
_mm_errno = MMERR_SAMPLE_TOO_BIG; _mm_errno = MMERR_SAMPLE_TOO_BIG;
return -1; return -1;
} }
/* read sample into buffer */ /* read sample into buffer */
if (SL_Load(Samples[handle],sload,length)) if (SL_Load(Samples[handle],sload,length)) {
MikMod_afree(Samples[handle]);
Samples[handle]=NULL;
return -1; return -1;
}
/* Unclick sample */ /* Unclick sample */
if(s->flags & SF_LOOP) { if(s->flags & SF_LOOP) {
looplen = loopend - loopstart;/* handle short samples */
if(s->flags & SF_BIDI) if(s->flags & SF_BIDI)
for(t=0;t<16;t++) for(t=0;t<16 && t<looplen;t++)
Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1]; Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
else else
for(t=0;t<16;t++) for(t=0;t<16 && t<looplen;t++)
Samples[handle][loopend+t]=Samples[handle][t+loopstart]; Samples[handle][loopend+t]=Samples[handle][t+loopstart];
} else } else
for(t=0;t<16;t++) for(t=0;t<16;t++)
@ -456,11 +470,8 @@ ULONG VC1_VoiceRealVolume(UBYTE voice)
return abs(k-j); return abs(k-j);
} }
#endif /* _VIRTCH_COMMON_ */
#endif #endif /* _IN_VIRTCH_ */
MikMod_callback_t vc_callback;
#endif
/* ex:set ts=4: */ /* ex:set ts=4: */

View file

@ -44,7 +44,6 @@ asy,viewers/mikmod,7
dsm,viewers/mikmod,7 dsm,viewers/mikmod,7
far,viewers/mikmod,7 far,viewers/mikmod,7
gdm,viewers/mikmod,7 gdm,viewers/mikmod,7
gt2,viewers/mikmod,7
imf,viewers/mikmod,7 imf,viewers/mikmod,7
it,viewers/mikmod,7 it,viewers/mikmod,7
m15,viewers/mikmod,7 m15,viewers/mikmod,7
@ -57,6 +56,7 @@ stm,viewers/mikmod,7
stx,viewers/mikmod,7 stx,viewers/mikmod,7
ult,viewers/mikmod,7 ult,viewers/mikmod,7
uni,viewers/mikmod,7 uni,viewers/mikmod,7
umx,viewers/mikmod,7
xm,viewers/mikmod,7 xm,viewers/mikmod,7
pd,viewers/pdbox,2 pd,viewers/pdbox,2
rsp,viewers/searchengine,8 rsp,viewers/searchengine,8