From b4e70422a3455e327433a7471c929ef100ef3b10 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 8 Aug 2020 21:56:15 -0400 Subject: 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 --- apps/lang/english.lang | 40 + apps/plugins/mikmod/SOURCES | 3 +- apps/plugins/mikmod/load_669.c | 30 +- apps/plugins/mikmod/load_amf.c | 72 +- apps/plugins/mikmod/load_asy.c | 91 ++- apps/plugins/mikmod/load_dsm.c | 29 +- apps/plugins/mikmod/load_far.c | 38 +- apps/plugins/mikmod/load_gdm.c | 33 +- apps/plugins/mikmod/load_gt2.c | 375 --------- apps/plugins/mikmod/load_imf.c | 71 +- apps/plugins/mikmod/load_it.c | 184 +++-- apps/plugins/mikmod/load_m15.c | 107 +-- apps/plugins/mikmod/load_med.c | 74 +- apps/plugins/mikmod/load_mod.c | 27 +- apps/plugins/mikmod/load_mtm.c | 34 +- apps/plugins/mikmod/load_okt.c | 21 +- apps/plugins/mikmod/load_s3m.c | 50 +- apps/plugins/mikmod/load_stm.c | 40 +- apps/plugins/mikmod/load_stx.c | 26 +- apps/plugins/mikmod/load_ult.c | 40 +- apps/plugins/mikmod/load_umx.c | 476 +++++++++++ apps/plugins/mikmod/load_uni.c | 163 ++-- apps/plugins/mikmod/load_xm.c | 129 +-- apps/plugins/mikmod/mdreg.c | 66 +- apps/plugins/mikmod/mdriver.c | 189 ++--- apps/plugins/mikmod/mikmod.c | 133 +++- apps/plugins/mikmod/mikmod.h | 895 +++++++++++---------- apps/plugins/mikmod/mikmod_internals.h | 789 +++++++++--------- apps/plugins/mikmod/mikmod_supp.h | 3 + apps/plugins/mikmod/mloader.c | 319 +++++--- apps/plugins/mikmod/mlreg.c | 5 +- apps/plugins/mikmod/mlutil.c | 44 +- apps/plugins/mikmod/mmalloc.c | 207 ++--- apps/plugins/mikmod/mmerror.c | 150 +++- apps/plugins/mikmod/mmio.c | 304 ++++--- apps/plugins/mikmod/mplayer.c | 410 +++++----- apps/plugins/mikmod/munitrk.c | 22 +- apps/plugins/mikmod/npertab.c | 8 +- apps/plugins/mikmod/sloader.c | 60 +- apps/plugins/mikmod/virtch.c | 652 +++++++-------- apps/plugins/mikmod/virtch2.c | 1370 ++++++++++++++++++++++++++++++++ apps/plugins/mikmod/virtch_common.c | 193 ++--- apps/plugins/viewers.config | 2 +- 43 files changed, 5122 insertions(+), 2852 deletions(-) delete mode 100644 apps/plugins/mikmod/load_gt2.c create mode 100644 apps/plugins/mikmod/load_umx.c create mode 100644 apps/plugins/mikmod/virtch2.c diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 8079884426..5937df64c0 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -15351,6 +15351,46 @@ swcodec: "Surround" + + id: LANG_MIKMOD_HQMIXER + desc: in mikmod settings menu + user: core + + *: none + lowmem: none + swcodec: "HQ Mixer" + + + *: none + lowmem: none + swcodec: "HQ Mixer" + + + *: none + lowmem: none + swcodec: "High Quality Mixer" + + + + id: LANG_MIKMOD_SAMPLERATE + desc: in mikmod settings menu + user: core + + *: none + lowmem: none + swcodec: "Sample Rate" + + + *: none + lowmem: none + swcodec: "Sample Rate" + + + *: none + lowmem: none + swcodec: "Sample Rate" + + id: LANG_CPU_BOOST desc: in mikmod settings menu diff --git a/apps/plugins/mikmod/SOURCES b/apps/plugins/mikmod/SOURCES index 1de5bb2149..bea10f9a29 100644 --- a/apps/plugins/mikmod/SOURCES +++ b/apps/plugins/mikmod/SOURCES @@ -5,7 +5,6 @@ load_asy.c load_dsm.c load_far.c load_gdm.c -load_gt2.c load_imf.c load_it.c load_m15.c @@ -17,6 +16,7 @@ load_s3m.c load_stm.c load_stx.c load_ult.c +load_umx.c load_uni.c load_xm.c mdreg.c @@ -34,6 +34,7 @@ sloader.c strdup.c strstr.c virtch.c +virtch2.c virtch_common.c mikmod.c diff --git a/apps/plugins/mikmod/load_669.c b/apps/plugins/mikmod/load_669.c index 000e51d985..0872043f65 100644 --- a/apps/plugins/mikmod/load_669.c +++ b/apps/plugins/mikmod/load_669.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_669.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id: $ Composer 669 module loader @@ -49,11 +49,11 @@ extern int fprintf(FILE *, const char *, ...); /*========== Module structure */ /* header */ -typedef struct S69HEADER { +typedef struct S69HEADER { UBYTE marker[2]; CHAR message[108]; UBYTE nos; - UBYTE rbnop; + UBYTE RBnop; UBYTE looporder; UBYTE orders[0x80]; UBYTE tempos[0x80]; @@ -81,7 +81,7 @@ static S69NOTE* s69pat=NULL; static S69HEADER* mh=NULL; /* file type identification */ -static CHAR* S69_Version[]={ +static const CHAR* S69_Version[]={ "Composer 669", "Extended 669" }; @@ -134,6 +134,8 @@ static void S69_Cleanup(void) { MikMod_free(s69pat); MikMod_free(mh); + mh=NULL; + s69pat=NULL; } static int S69_LoadPatterns(void) @@ -142,7 +144,7 @@ static int S69_LoadPatterns(void) UBYTE note,inst,vol,effect,lastfx,lastval; S69NOTE *cur; int tracks=0; - + if(!AllocPatterns()) return 0; if(!AllocTracks()) return 0; @@ -226,7 +228,7 @@ static int S69_LoadPatterns(void) case 5: /* set speed */ if (effect) UniPTEffect(0xf,effect); - else + else if(mh->marker[0]!=0x69) { #ifdef MIKMOD_DEBUG fprintf(stderr,"\r669: unsupported super fast tempo at pat=%d row=%d chan=%d\n", @@ -250,13 +252,13 @@ static int S69_Load(int curious) int i; SAMPLE *current; S69SAMPLE sample; - (void)curious; + (void)curious; /* module header */ _mm_read_UBYTES(mh->marker,2,modreader); _mm_read_UBYTES(mh->message,108,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); _mm_read_UBYTES(mh->orders,0x80,modreader); for(i=0;i<0x80;i++) @@ -281,9 +283,9 @@ static int S69_Load(int curious) of.initspeed=4; of.inittempo=78; 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.numpat=mh->rbnop; + of.numpat=mh->RBnop; of.numins=of.numsmp=mh->nos; of.numtrk=of.numchn*of.numpat; 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=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0; 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); strcat(of.comment,"\r"); 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; 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.numpos=i; diff --git a/apps/plugins/mikmod/load_amf.c b/apps/plugins/mikmod/load_amf.c index 32067602f2..ba1f59a5be 100644 --- a/apps/plugins/mikmod/load_amf.c +++ b/apps/plugins/mikmod/load_amf.c @@ -6,12 +6,12 @@ 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 @@ -20,8 +20,6 @@ /*============================================================================== - $Id: load_amf.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ - DMP Advanced Module Format loader ==============================================================================*/ @@ -112,9 +110,11 @@ static void AMF_Cleanup(void) { MikMod_free(mh); MikMod_free(track); + mh=NULL; + track=NULL; } -static int AMF_UnpackTrack(MREADER* modreader) +static int AMF_UnpackTrack(MREADER* r) { ULONG tracksize; UBYTE row,cmd; @@ -124,20 +124,20 @@ static int AMF_UnpackTrack(MREADER* modreader) memset(track,0,64*sizeof(AMFNOTE)); /* read packed track */ - if (modreader) { - tracksize=_mm_read_I_UWORD(modreader); - tracksize+=((ULONG)_mm_read_UBYTE(modreader))<<16; + if (r) { + tracksize=_mm_read_I_UWORD(r); + tracksize+=((ULONG)_mm_read_UBYTE(r))<<16; if (tracksize) while(tracksize--) { - row=_mm_read_UBYTE(modreader); - cmd=_mm_read_UBYTE(modreader); - arg=_mm_read_SBYTE(modreader); + row=_mm_read_UBYTE(r); + cmd=_mm_read_UBYTE(r); + arg=_mm_read_SBYTE(r); /* unexpected end of track */ if(!tracksize) { if((row==0xff)&&(cmd==0xff)&&(arg==-1)) break; /* the last triplet should be FF FF FF, but this is not - always the case... maybe a bug in m2amf ? + always the case... maybe a bug in m2amf ? else return 0; */ @@ -164,7 +164,7 @@ static int AMF_UnpackTrack(MREADER* modreader) if (cmd==0x83) { /* volume without note */ track[row].volume=(UBYTE)arg+1; - } else + } else if (cmd==0xff) { /* apparently, some M2AMF version fail to estimate the size of the compressed patterns correctly, and end @@ -322,7 +322,7 @@ static UBYTE* AMF_ConvertTrack(void) of.flags |= UF_PANNING; break; } - + } if (track[row].volume) UniVolEffect(VOL_VOLUME,track[row].volume-1); UniNewline(); @@ -333,13 +333,13 @@ static UBYTE* AMF_ConvertTrack(void) static int AMF_Load(int curious) { int u,defaultpanning; - unsigned int t,realtrackcnt,realsmpcnt; + unsigned int t,realtrackcnt,realsmpcnt; AMFSAMPLE s; SAMPLE *q; UWORD *track_remap; - ULONG samplepos; + ULONG samplepos, fileend; int channel_remap[16]; - (void)curious; + (void)curious; /* try to read module header */ _mm_read_UBYTES(mh->id,3,modreader); @@ -386,7 +386,7 @@ static int AMF_Load(int curious) of.inittempo = mh->songbpm; AMF_Version[AMFTEXTLEN-3]='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.numtrk = mh->numorders*mh->numchannels; if (mh->numtracks>of.numtrk) @@ -400,7 +400,7 @@ static int AMF_Load(int curious) /* XXX whenever possible, we should try to determine the original format. Here we assume it was S3M-style wrt bpmlimit... */ of.bpmlimit = 32; - + /* * Play with the panning table. Although the AMF format embeds a * panning table, if the module was a MOD or an S3M with default @@ -466,7 +466,10 @@ static int AMF_Load(int curious) s.c2spd =_mm_read_I_UWORD(modreader); if(s.c2spd==8368) s.c2spd=8363; 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.repend =_mm_read_I_ULONG(modreader); } else { @@ -475,7 +478,7 @@ static int AMF_Load(int curious) } if(_mm_eof(modreader)) { - _mm_errno = MMERR_LOADING_SAMPLEINFO; + _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } @@ -493,7 +496,7 @@ static int AMF_Load(int curious) } /* 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; _mm_read_I_UWORDS(track_remap+1,mh->numtracks,modreader); if(_mm_eof(modreader)) { @@ -505,9 +508,14 @@ static int AMF_Load(int curious) for(realtrackcnt=t=0;t<=mh->numtracks;t++) if (realtrackcnt (int)mh->numtracks) { + MikMod_free(track_remap); + _mm_errno=MMERR_NOT_A_MODULE; + return 0; + } for(t=0;tnumtracks)? - track_remap[of.patterns[t]]-1:(int)realtrackcnt; + track_remap[of.patterns[t]]-1:(int)realtrackcnt; MikMod_free(track_remap); @@ -531,18 +539,32 @@ static int AMF_Load(int curious) for(t=realtrackcnt;tseekpos!=t) q++; + u=0; + while(q->seekpos!=t) { + if(++u==of.numsmp) + goto fail; + q++; + } q->seekpos=samplepos; samplepos+=q->length; } - + if(samplepos>fileend) + goto fail; + return 1; +fail: + _mm_errno = MMERR_LOADING_SAMPLEINFO; + return 0; } static CHAR *AMF_LoadTitle(void) diff --git a/apps/plugins/mikmod/load_asy.c b/apps/plugins/mikmod/load_asy.c index 46e899f6bd..48d746c8e8 100644 --- a/apps/plugins/mikmod/load_asy.c +++ b/apps/plugins/mikmod/load_asy.c @@ -6,12 +6,12 @@ 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 @@ -20,15 +20,15 @@ /*============================================================================== - $Id: load_asy.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id$ ASYLUM Music Format v1.0 (.amf) loader adapted from load_mod.c by Raphael Assenat , with the help of the AMF2MOD utility sourcecode, written to convert crusader's amf files into 8 channels mod file in 1995 by Mr. P / Powersource - mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca - + mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca + ==============================================================================*/ @@ -76,8 +76,9 @@ typedef struct MODNOTE { /* This table is taken from AMF2MOD.C * written in 1995 by Mr. P / Powersource - * mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */ -UWORD periodtable[]={6848,6464,6096,5760,5424,5120,4832,4560,4304, + * mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */ +static const UWORD periodtable[] = { + 6848,6464,6096,5760,5424,5120,4832,4560,4304, 4064,3840,3628,3424,3232,3048,2880,2712,2560, 2416,2280,2152,2032,1920,1814,1712,1616,1524, 1440,1356,1280,1208,1140,1076,1016, 960, 907, @@ -108,7 +109,7 @@ static int ASY_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr) modtype = 1; return 1; } - + return 0; } @@ -140,14 +141,16 @@ static void ASY_Cleanup(void) { MikMod_free(mh); MikMod_free(patbuf); + mh = NULL; + patbuf = NULL; } -static void ConvertNote(MODNOTE *n) +static int ConvertNote(MODNOTE *n) { UBYTE instrument, effect, effdat, note; UWORD period; UBYTE lastnote = 0; - + instrument = n->b&0x1f; effect = n->c; effdat = n->d; @@ -158,10 +161,10 @@ static void ConvertNote(MODNOTE *n) } else { period = 0; } - + /* Convert the period to a note number */ note = 0; - if (period) + if (period) { for (note = 0; note < 7 * OCTAVE; note++) if (period >= npertab[note]) @@ -186,8 +189,8 @@ static void ConvertNote(MODNOTE *n) UniInstrument(instrument - 1); /* ...otherwise, only adjust volume... */ else { - /* ...unless an effect was specified, - * which forces a new note to be + /* ...unless an effect was specified, + * which forces a new note to be * played */ if (effect || effdat) { UniInstrument(instrument - 1); @@ -218,7 +221,15 @@ static void ConvertNote(MODNOTE *n) if ((effect == 0xa) && (effdat & 0xf) && (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); + return 0; } static UBYTE *ConvertTrack(MODNOTE *n) @@ -227,7 +238,8 @@ static UBYTE *ConvertTrack(MODNOTE *n) UniReset(); for (t = 0; t < 64; t++) { - ConvertNote(n); + if (ConvertNote(n) < 0) + return NULL; UniNewline(); 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. */ static int ML_LoadPatterns(void) { - int t, tracks = 0; - unsigned int s; + unsigned int t, s, tracks = 0; if (!AllocPatterns()) { return 0; @@ -246,7 +257,7 @@ static int ML_LoadPatterns(void) if (!AllocTracks()) { return 0; } - + /* Allocate temporary buffer for loading and converting the patterns */ if (!(patbuf = (MODNOTE *)MikMod_calloc(64U * of.numchn, sizeof(MODNOTE)))) return 0; @@ -278,31 +289,31 @@ static int ASY_Load(int curious) MSAMPINFO *s; CHAR *descr=asylum; ULONG seekpos; - (void)curious; + (void)curious; - // no title in asylum amf files :( - strcpy(mh->songname, ""); + /* no title in asylum amf files :( */ + mh->songname[0] = '\0'; _mm_fseek(modreader, 0x23, SEEK_SET); mh->num_patterns = _mm_read_UBYTE(modreader); mh->num_orders = _mm_read_UBYTE(modreader); - - // skip unknown byte - (void)_mm_read_UBYTE(modreader); + + /* skip unknown byte */ + _mm_skip_BYTE(modreader); _mm_read_UBYTES(mh->positions, 256, modreader); - + /* read samples headers*/ for (t = 0; t < 64; t++) { s = &mh->samples[t]; - + _mm_fseek(modreader, 0x126 + (t*37), SEEK_SET); - + _mm_read_string(s->samplename, 22, modreader); s->samplename[21] = 0; /* just in case */ - + s->finetune = _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->reppos = _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.numtrk = of.numpat * of.numchn; - /* Copy positions (orders) */ if (!AllocPositions(of.numpos)) return 0; for (t = 0; t < of.numpos; 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 */ @@ -343,7 +358,7 @@ static int ASY_Load(int curious) for (t = 0; t < of.numins; t++) { /* convert the samplename */ q->samplename = DupStr(s->samplename, 23, 1); - + /* init the sampleinfo variables */ q->speed = finetune[s->finetune & 0xf]; q->volume = s->volume & 0x7f; @@ -351,16 +366,16 @@ static int ASY_Load(int curious) q->loopstart = (ULONG)s->reppos; q->loopend = (ULONG)q->loopstart + (s->replen); q->length = (ULONG)s->length; - + q->flags = SF_SIGNED; - + q->seekpos = seekpos; seekpos += q->length; - + if ((s->replen) > 2) { q->flags |= SF_LOOP; } - + /* fix replen if repend > length */ if (q->loopend > q->length) q->loopend = q->length; @@ -369,7 +384,7 @@ static int ASY_Load(int curious) q++; } - of.modtype = StrDup(descr); + of.modtype = MikMod_strdup(descr); if (!ML_LoadPatterns()) return 0; @@ -379,9 +394,7 @@ static int ASY_Load(int curious) static CHAR *ASY_LoadTitle(void) { - CHAR *s = ""; // no titles - - return (DupStr(s, 21, 1)); + return MikMod_strdup(""); } /*========== Loader information */ diff --git a/apps/plugins/mikmod/load_dsm.c b/apps/plugins/mikmod/load_dsm.c index 59abf0bcfe..e995f7dfad 100644 --- a/apps/plugins/mikmod/load_dsm.c +++ b/apps/plugins/mikmod/load_dsm.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -89,9 +89,9 @@ typedef struct DSMNOTE { /*========== Loader variables */ -static CHAR* SONGID="SONG"; -static CHAR* INSTID="INST"; -static CHAR* PATTID="PATT"; +static const CHAR* SONGID="SONG"; +static const CHAR* INSTID="INST"; +static const CHAR* PATTID="PATT"; static UBYTE blockid[4]; static ULONG blockln; @@ -101,7 +101,7 @@ static DSMNOTE* dsmbuf=NULL; 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 */ @@ -126,6 +126,8 @@ static void DSM_Cleanup(void) { MikMod_free(dsmbuf); MikMod_free(mh); + dsmbuf = NULL; + mh = NULL; } static int GetBlockHeader(void) @@ -133,7 +135,7 @@ static int GetBlockHeader(void) /* make sure we're at the right position for reading the next riff block, no matter how many bytes read */ _mm_fseek(modreader, blocklp+blockln, SEEK_SET); - + while(1) { _mm_read_UBYTES(blockid,4,modreader); blockln=_mm_read_I_ULONG(modreader); @@ -237,7 +239,7 @@ static int DSM_Load(int curious) DSMINST s; SAMPLE *q; int cursmp=0,curpat=0,track=0; - (void)curious; + (void)curious; blocklp=0; blockln=12; @@ -266,7 +268,7 @@ static int DSM_Load(int curious) /* set module variables */ of.initspeed=mh->speed; of.inittempo=mh->bpm; - of.modtype=StrDup(DSM_Version); + of.modtype=MikMod_strdup(DSM_Version); of.numchn=mh->numtrk; of.numpat=mh->numpat; of.numtrk=of.numchn*of.numpat; @@ -286,6 +288,11 @@ static int DSM_Load(int curious) for(t=0;tnumord;t++) { int order=mh->orders[t]; 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; if(mh->orders[t]<254) of.numpos++; } @@ -344,7 +351,7 @@ static CHAR *DSM_LoadTitle(void) _mm_fseek(modreader,12,SEEK_SET); if(!_mm_read_UBYTES(s,28,modreader)) return NULL; - + return(DupStr(s,28,1)); } diff --git a/apps/plugins/mikmod/load_far.c b/apps/plugins/mikmod/load_far.c index 2a1a44eda9..643cf15d49 100644 --- a/apps/plugins/mikmod/load_far.c +++ b/apps/plugins/mikmod/load_far.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_far.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id$ Farandole (FAR) module loader @@ -92,7 +92,7 @@ static FARHEADER1 *mh1 = NULL; static FARHEADER2 *mh2 = 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 */ @@ -119,6 +119,9 @@ static void FAR_Cleanup(void) MikMod_free(mh1); MikMod_free(mh2); MikMod_free(pat); + mh1 = NULL; + mh2 = NULL; + pat = NULL; } static UBYTE *FAR_ConvertTrack(FARNOTE* n,int rows) @@ -180,7 +183,7 @@ static int FAR_Load(int curious) FARSAMPLE s; FARNOTE *crow; UBYTE smap[8]; - (void)curious; + (void)curious; /* try to read module header (first part) */ _mm_read_UBYTES(mh1->id,4,modreader); @@ -196,7 +199,7 @@ static int FAR_Load(int curious) mh1->stlen = _mm_read_I_UWORD (modreader); /* init modfile data */ - of.modtype = StrDup(FAR_Version); + of.modtype = MikMod_strdup(FAR_Version); of.songname = DupStr(mh1->songname,40,1); of.numchn = 16; of.initspeed = mh1->speed; @@ -207,7 +210,12 @@ static int FAR_Load(int curious) /* read songtext into comment field */ 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) */ _mm_read_UBYTES(mh2->orders,256,modreader); @@ -238,12 +246,14 @@ static int FAR_Load(int curious) if(!AllocPatterns()) return 0; for(t=0;tpatsiz[t]) { rows = _mm_read_UBYTE(modreader); - /* tempo = */ (void)_mm_read_UBYTE(modreader); + tempo = _mm_read_UBYTE(modreader); + (void)tempo; /* unused */ crow = pat; /* file often allocates 64 rows even if there are less in pattern */ @@ -284,7 +294,7 @@ static int FAR_Load(int curious) of.numins = 0; for(t=0;t<64;t++) if(smap[t>>3]&(1<<(t&7))) of.numins=t+1; - of.numsmp = of.numins; + of.numsmp = of.numins; /* alloc sample structs */ if(!AllocSamples()) return 0; @@ -314,8 +324,8 @@ static int FAR_Load(int curious) q->seekpos = _mm_ftell(modreader); _mm_fseek(modreader,q->length,SEEK_CUR); - } else - q->samplename = DupStr(NULL,0,0); + } else + q->samplename = MikMod_strdup(""); q++; } return 1; @@ -327,8 +337,8 @@ static CHAR *FAR_LoadTitle(void) _mm_fseek(modreader,4,SEEK_SET); if(!_mm_read_UBYTES(s,40,modreader)) return NULL; - - return(DupStr(s,40,1)); + + return (DupStr(s,40,1)); } /*========== Loader information */ diff --git a/apps/plugins/mikmod/load_gdm.c b/apps/plugins/mikmod/load_gdm.c index 694d534236..5f06f9c70b 100644 --- a/apps/plugins/mikmod/load_gdm.c +++ b/apps/plugins/mikmod/load_gdm.c @@ -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 @@ -114,7 +114,7 @@ typedef struct GDMSAMPLE { static GDMHEADER *mh=NULL; /* pointer to GDM header */ 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) { @@ -146,36 +146,45 @@ static void GDM_Cleanup(void) { MikMod_free(mh); MikMod_free(gdmbuf); + mh=NULL; + gdmbuf=NULL; } static int GDM_ReadPattern(void) { - int pos,flag,ch,i,maxch; + int pos,flag,ch,i; GDMNOTE n; - UWORD length,x=0; + SLONG length,x=0; /* get pattern length */ - length=_mm_read_I_UWORD(modreader)-2; + length=(SLONG)_mm_read_I_UWORD(modreader); + length-=2; /* clear pattern data */ memset(gdmbuf,255,32*64*sizeof(GDMNOTE)); pos=0; - maxch=0; while (xmaxch) maxch=ch; + if (ch > of.numchn) + return 0; + if (!flag) { pos++; + if (x==length) { + if (pos > 64) + return 0; + } else { + if (pos >= 64) + return 0; + } continue; } if (flag&0x60) { @@ -343,7 +352,7 @@ static int GDM_Load(int curious) SAMPLE *q; GDMSAMPLE s; ULONG position; - (void)curious; + (void)curious; /* read header */ _mm_read_string(mh->id1,4,modreader); @@ -390,7 +399,7 @@ static int GDM_Load(int curious) } /* now we fill */ - of.modtype=StrDup(GDM_Version); + of.modtype=MikMod_strdup(GDM_Version); of.modtype[18]=mh->majorver+'0'; of.modtype[20]=mh->minorver/10+'0'; of.modtype[21]=mh->minorver%10+'0'; diff --git a/apps/plugins/mikmod/load_gt2.c b/apps/plugins/mikmod/load_gt2.c deleted file mode 100644 index 26b4d1f59a..0000000000 --- a/apps/plugins/mikmod/load_gt2.c +++ /dev/null @@ -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 -#endif - -#include -#include -#ifdef HAVE_MEMORY_H -#include -#endif -#include - -#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 -}; - - - diff --git a/apps/plugins/mikmod/load_imf.c b/apps/plugins/mikmod/load_imf.c index 9c93d97e23..39cdf5464d 100644 --- a/apps/plugins/mikmod/load_imf.c +++ b/apps/plugins/mikmod/load_imf.c @@ -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 @@ -127,12 +127,36 @@ static IMFHEADER *mh=NULL; static int IMF_Test(void) { - UBYTE id[4]; + UBYTE buf[512], *p; + int t, chn; _mm_fseek(modreader,0x3c,SEEK_SET); - if(!_mm_read_UBYTES(id,4,modreader)) return 0; - if(!memcmp(id,"IM10",4)) return 1; - return 0; + if (!_mm_read_UBYTES(buf,4,modreader)) return 0; + 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; + } + } + if(!chn) return 0; /* no channels found */ + + return 1; } static int IMF_Init(void) @@ -149,6 +173,8 @@ static void IMF_Cleanup(void) MikMod_free(imfpat); MikMod_free(mh); + imfpat=NULL; + mh=NULL; } static int IMF_ReadPattern(SLONG size,UWORD rows) @@ -388,7 +414,7 @@ static int IMF_Load(int curious) ULONG *nextwav=NULL; UWORD wavcnt=0; UBYTE id[4]; - (void)curious; + (void)curious; /* try to read the module header */ _mm_read_string(mh->songname,32,modreader); @@ -410,7 +436,7 @@ static int IMF_Load(int curious) /* set module variables */ of.songname=DupStr(mh->songname,31,1); - of.modtype=StrDup(IMF_Version); + of.modtype=MikMod_strdup(IMF_Version); of.numpat=mh->patnum; of.numins=mh->insnum; of.reppos=0; @@ -467,6 +493,13 @@ static int IMF_Load(int curious) if(!AllocPositions(of.numpos)) return 0; for(t=u=0;tordnum;t++) if(mh->orders[t]!=0xff) of.positions[u++]=mh->orders[t]; + for(t=0;tof.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 */ 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.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) \ ih. name##pts=_mm_read_UBYTE(modreader); \ ih. name##sus=_mm_read_UBYTE(modreader); \ ih. name##beg=_mm_read_UBYTE(modreader); \ ih. name##end=_mm_read_UBYTE(modreader); \ ih. name##flg=_mm_read_UBYTE(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) #else #define IMF_FinishLoadingEnvelope(name) \ 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/**/end=_mm_read_UBYTE(modreader); \ ih. name/**/flg=_mm_read_UBYTE(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) #endif IMF_FinishLoadingEnvelope(vol); @@ -541,7 +574,7 @@ static int IMF_Load(int curious) _mm_read_UBYTES(id,4,modreader); /* Looks like Imago Orpheus forgets the signature for empty instruments following a multi-sample instrument... */ - if(memcmp(id,"II10",4) && + if(memcmp(id,"II10",4) && (oldnumsmp && memcmp(id,"\x0\x0\x0\x0",4))) { if(nextwav) MikMod_free(nextwav); if(wh) MikMod_free(wh); @@ -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->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) \ for (u = 0; u < (IMFENVCNT >> 1); u++) { \ 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 */ if(of.numsmp+u==wavcnt) { 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); _mm_errno=MMERR_OUT_OF_MEMORY; return 0; } - if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) { + if(!(wh=(IMFWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) { MikMod_free(nextwav); _mm_errno=MMERR_OUT_OF_MEMORY; return 0; @@ -627,7 +660,7 @@ static int IMF_Load(int curious) } _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->loopstart =_mm_read_I_ULONG(modreader); s->loopend =_mm_read_I_ULONG(modreader); diff --git a/apps/plugins/mikmod/load_it.c b/apps/plugins/mikmod/load_it.c index c48d126f77..c1e257fd97 100644 --- a/apps/plugins/mikmod/load_it.c +++ b/apps/plugins/mikmod/load_it.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -45,7 +45,6 @@ #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); -extern int toupper(int); #endif /*========== Module structure */ @@ -67,7 +66,7 @@ typedef struct ITHEADER { UBYTE initspeed; UBYTE inittempo; UBYTE pansep; /* panning separation between channels */ - UBYTE zerobyte; + UBYTE zerobyte; UWORD msglength; ULONG msgoffset; UBYTE blank02[4]; @@ -107,19 +106,19 @@ typedef struct ITINSTHEADER { CHAR filename[12]; /* (char) Instrument filename */ UBYTE zerobyte; /* (byte) Instrument type (always 0) */ UBYTE volflg; - UBYTE volpts; + UBYTE volpts; UBYTE volbeg; /* (byte) Volume loop start (node) */ UBYTE volend; /* (byte) Volume loop end (node) */ UBYTE volsusbeg; /* (byte) Volume sustain begin (node) */ UBYTE volsusend; /* (byte) Volume Sustain end (node) */ UBYTE panflg; - UBYTE panpts; + UBYTE panpts; UBYTE panbeg; /* (byte) channel loop start (node) */ UBYTE panend; /* (byte) channel loop end (node) */ UBYTE pansusbeg; /* (byte) channel sustain begin (node) */ UBYTE pansusend; /* (byte) channel Sustain end (node) */ UBYTE pitflg; - UBYTE pitpts; + UBYTE pitpts; UBYTE pitbeg; /* (byte) pitch loop start (node) */ UBYTE pitend; /* (byte) pitch loop end (node) */ UBYTE pitsusbeg; /* (byte) pitch sustain begin (node) */ @@ -149,7 +148,7 @@ typedef struct ITINSTHEADER { UWORD pantick[ITENVCNT]; /* tick value of panning nodes */ SBYTE pitnode[ITENVCNT]; /* pitchenv - node points */ UWORD pittick[ITENVCNT]; /* tick value of pitch nodes */ -} ITINSTHEADER; +} ITINSTHEADER; /* unpacked note */ @@ -166,8 +165,8 @@ static UBYTE *mask=NULL; /* arrays allocated to 64 elements and used for */ static ITNOTE *last=NULL; /* uncompressing IT's pattern information */ static int numtrk=0; static unsigned int old_effect; /* if set, use S3M old-effects stuffs */ - -static CHAR* IT_Version[]={ + +static const CHAR* IT_Version[]={ "ImpulseTracker . ", "Compressed ImpulseTracker . ", "ImpulseTracker 2.14p3", @@ -177,7 +176,7 @@ static CHAR* IT_Version[]={ }; /* 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 */ @@ -212,40 +211,48 @@ static void IT_Cleanup(void) MikMod_free(last); MikMod_free(paraptr); 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 only use far less (usually from 8 to 24 still), I had to make this function, which determines the number of channels that are actually USED by a pattern. - + 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) { int row=0,flag,ch; do { - if((flag=_mm_read_UBYTE(modreader))==EOF) { + if(_mm_eof(modreader)) { _mm_errno=MMERR_LOADING_PATTERN; - return 1; + return 0; } + flag=_mm_read_UBYTE(modreader); if(!flag) row++; else { ch=(flag-1)&63; remap[ch]=0; if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader); - if(mask[ch]&1) (void)_mm_read_UBYTE(modreader); - if(mask[ch]&2) (void)_mm_read_UBYTE(modreader); - if(mask[ch]&4) (void)_mm_read_UBYTE(modreader); - if(mask[ch]&8) { (void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader); } + if(mask[ch]&1) _mm_skip_BYTE(modreader); + if(mask[ch]&2) _mm_skip_BYTE(modreader); + if(mask[ch]&4) _mm_skip_BYTE(modreader); + if(mask[ch]&8) { _mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader); } } } while(row ite) { /* malformed file */ + _mm_errno = MMERR_NOT_A_MODULE; + return 0; + } + } else + { n=l=&dummy; + blah = 0; + m=(UBYTE*)&blah; + } - if(flag&128) mask[ch]=_mm_read_UBYTE(modreader); - if(mask[ch]&1) + if(flag&128) *m=_mm_read_UBYTE(modreader); + if(*m&1) /* 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; - if(mask[ch]&2) + if(*m&2) l->ins=n->ins=_mm_read_UBYTE(modreader); - if(mask[ch]&4) + if(*m&4) l->volpan=n->volpan=_mm_read_UBYTE(modreader); - if(mask[ch]&8) { + if(*m&8) { l->cmd=n->cmd=_mm_read_UBYTE(modreader); l->inf=n->inf=_mm_read_UBYTE(modreader); } - if(mask[ch]&16) + if(*m&16) n->note=l->note; - if(mask[ch]&32) + if(*m&32) n->ins=l->ins; - if(mask[ch]&64) + if(*m&64) n->volpan=l->volpan; - if(mask[ch]&128) { + if(*m&128) { n->cmd=l->cmd; n->inf=l->inf; } @@ -379,38 +399,39 @@ static int IT_ReadPattern(UWORD patrows) 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); - cur=last=dest; + memset(dest,0,33*sizeof(CHAR));/* caller sends midiline[33] */ + _mm_read_UBYTES(dest,32,r); + curp=lastp=dest; /* remove blanks and uppercase all */ - while(*last) { - if(isalnum((int)*last)) *(cur++)=toupper((int)*last); - last++; + while(*lastp) { + if(isalnum((int)*lastp)) *(curp++)=toupper((int)*lastp); + lastp++; } - *cur=0; + *curp=0; } /* Load embedded midi information for resonant filters */ -static void IT_LoadMidiConfiguration(MREADER* modreader) +static void IT_LoadMidiConfiguration(MREADER* r) { int i; memset(filtermacros,0,sizeof(filtermacros)); memset(filtersettings,0,sizeof(filtersettings)); - if (modreader) { /* information is embedded in file */ + if (r) { /* information is embedded in file */ UWORD dat; CHAR midiline[33]; - dat=_mm_read_I_UWORD(modreader); - _mm_fseek(modreader,8*dat+0x120,SEEK_CUR); + dat=_mm_read_I_UWORD(r); + _mm_fseek(r,8*dat+0x120,SEEK_CUR); /* read midi macros */ for(i=0;iordnum > 256 || mh->insnum > 255 || mh->smpnum > 255 || mh->patnum > 255) { + _mm_errno=MMERR_NOT_A_MODULE; + return 0; + } /* set module variables */ 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.15 : IT 2.14p3 (improved compression) */ 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) - of.modtype=StrDup(IT_Version[mh->cmwt<0x214?2:3]); + of.modtype=MikMod_strdup(IT_Version[mh->cmwt<0x214?2:3]); 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?17:28] = ((mh->cwt>>4)&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 */ 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;tordnum;t++) { origpositions[t]=_mm_read_UBYTE(modreader); @@ -672,14 +697,14 @@ static int IT_Load(int curious) if(s.flag&2) q->flags|=SF_16BITS; if((s.flag&8)&&(mh->cwt>=0x214)) { q->flags|=SF_ITPACKED; - /* compressed=1; */ + /*compressed=1;*/ } if(s.flag&16) q->flags|=SF_LOOP; if(s.flag&64) q->flags|=SF_BIDI; if(mh->cwt>=0x200) { if(s.convert&1) q->flags|=SF_SIGNED; - if(s.convert&4) q->flags|=SF_DELTA; + if(s.convert&4) q->flags|=SF_DELTA; } q++; } @@ -726,7 +751,7 @@ static int IT_Load(int curious) ih.trkvers = _mm_read_I_UWORD(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_UBYTES(ih.blank01,6,modreader); _mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader); @@ -736,13 +761,15 @@ static int IT_Load(int curious) for(lp=0;lp ITENVCNT) \ + ih. name##pts = ITENVCNT; \ ih. name##beg =_mm_read_UBYTE(modreader); \ ih. name##end =_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##tick[lp]=_mm_read_I_UWORD(modreader); \ } \ - (void)_mm_read_UBYTE(modreader) + _mm_skip_BYTE(modreader) #else #define IT_LoadEnvelope(name,type) \ ih. name/**/flg =_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/**/end =_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/**/tick[lp]=_mm_read_I_UWORD(modreader); \ } \ - (void)_mm_read_UBYTE(modreader) + _mm_skip_BYTE(modreader) #endif IT_LoadEnvelope(vol,UBYTE); @@ -772,7 +801,7 @@ static int IT_Load(int curious) IT_LoadEnvelope(pit,SBYTE); #undef IT_LoadEnvelope } - + if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; @@ -791,10 +820,10 @@ static int IT_Load(int curious) if(ih.volflg&1) d->volflg|=EF_ON; if(ih.volflg&2) d->volflg|=EF_LOOP; - if(ih.volflg&4) d->volflg|=EF_SUSTAIN; + if(ih.volflg&4) d->volflg|=EF_SUSTAIN; /* XM conversion of IT envelope Array */ - d->volbeg = ih.volbeg; + d->volbeg = ih.volbeg; d->volend = ih.volend; d->volsusbeg = ih.volsusbeg; d->volsusend = ih.volsusend; @@ -807,7 +836,7 @@ static int IT_Load(int curious) d->volpts++; } else break; - } + } } else { d->panning=((ih.chanpan&127)==64)?255:(ih.chanpan&127)<<2; if(!(ih.chanpan&128)) d->flags|=IF_OWNPAN; @@ -827,7 +856,7 @@ static int IT_Load(int curious) 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) \ if(ih. name##flg&1) d-> name##flg|=EF_ON; \ if(ih. name##flg&2) d-> name##flg|=EF_LOOP; \ @@ -862,11 +891,7 @@ static int IT_Load(int curious) #endif IT_ProcessEnvelope(vol); - - // Secunia SA37775 - if (ih.volpts>= ENVPOINTS) - ih.volpts = ENVPOINTS-1; - + for(u=0;uvolenv[u].val=(ih.volnode[u]<<2); @@ -887,7 +912,7 @@ static int IT_Load(int curious) #ifdef MIKMOD_DEBUG { static int warn=0; - + if(!warn) fprintf(stderr, "\rFilter envelopes not supported yet\n"); warn=1; @@ -908,7 +933,7 @@ static int IT_Load(int curious) } } - d++; + d++; } } else if(of.flags & UF_LINEAR) { if(!AllocInstruments()) return 0; @@ -946,12 +971,12 @@ static int IT_Load(int curious) return 0; } _mm_read_I_ULONG(modreader); - if(IT_GetNumChannels(packlen)) return 0; + if(!IT_GetNumChannels(packlen)) return 0; } } /* give each of them a different number */ - for(t=0;tinsnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */ of.pattrows[t]=64; @@ -975,7 +1002,8 @@ static int IT_Load(int curious) } } else { _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); _mm_read_I_ULONG(modreader); if(!IT_ReadPattern(of.pattrows[t])) return 0; @@ -991,7 +1019,7 @@ static CHAR *IT_LoadTitle(void) _mm_fseek(modreader,4,SEEK_SET); if(!_mm_read_UBYTES(s,26,modreader)) return NULL; - + return(DupStr(s,26,0)); } diff --git a/apps/plugins/mikmod/load_m15.c b/apps/plugins/mikmod/load_m15.c index b5d5329bf0..2359175bb3 100644 --- a/apps/plugins/mikmod/load_m15.c +++ b/apps/plugins/mikmod/load_m15.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_m15.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id$ 15 instrument MOD loader 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 */ #define REJECT 2 -static char *signatures[REJECT]={ +static const char *signatures[REJECT]={ "CAKEWALK", /* cakewalk midi files */ "SZDD" /* Microsoft compressed files */ }; -static int siglen[REJECT]={8,4}; +static const int siglen[REJECT]={8,4}; /*========== Loader code */ -static int LoadModuleHeader(MODULEHEADER *mh) +static int LoadModuleHeader(MODULEHEADER *h) { int t,u; - _mm_read_string(mh->songname,20,modreader); - mh->songname[20]=0; /* just in case */ + _mm_read_string(h->songname,20,modreader); /* sanity check : title should contain printable characters and a bunch of null chars */ for(t=0;t<20;t++) - if((mh->songname[t])&&(mh->songname[t]<32)) return 0; - for(t=0;(mh->songname[t])&&(t<20);t++); - if(t<20) for(;t<20;t++) if(mh->songname[t]) return 0; + if((h->songname[t])&&(h->songname[t]<32)) return 0; + for(t=0;(h->songname[t])&&(t<20);t++); + if(t<20) for(;t<20;t++) if(h->songname[t]) return 0; for(t=0;t<15;t++) { - MSAMPINFO *s=&mh->samples[t]; + MSAMPINFO *s=&h->samples[t]; _mm_read_string(s->samplename,22,modreader); - s->samplename[22]=0; /* just in case */ s->length =_mm_read_M_UWORD(modreader); s->finetune =_mm_read_UBYTE(modreader); s->volume =_mm_read_UBYTE(modreader); @@ -123,26 +121,26 @@ static int LoadModuleHeader(MODULEHEADER *mh) if(s->finetune>>4) return 0; } - mh->songlength =_mm_read_UBYTE(modreader); - mh->magic1 =_mm_read_UBYTE(modreader); /* should be 127 */ + h->songlength =_mm_read_UBYTE(modreader); + h->magic1 =_mm_read_UBYTE(modreader); /* should be 127 */ /* 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 */ - 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 */ for(t=0;t<128;t++) - if(mh->positions[t]>63) return 0; + if(h->positions[t]>63) return 0; return(!_mm_eof(modreader)); } /* Checks the patterns in the modfile for UST / 15-inst indications. - For example, if an effect 3xx is found, it is assumed that the song - is 15-inst. If a 1xx effect has dat greater than 0x20, it is UST. + For example, if an effect 3xx is found, it is assumed that the song + is 15-inst. If a 1xx effect has dat greater than 0x20, it is UST. Returns: 0 indecisive; 1 = UST; 2 = 15-inst */ static int CheckPatternType(int numpat) @@ -152,7 +150,7 @@ static int CheckPatternType(int numpat) for(t=0;t127) return 0; - if((!mh.songlength)||(mh.songlength>mh.magic1)) return 0; + if(h.magic1>127) return 0; + if((!h.songlength)||(h.songlength>h.magic1)) return 0; for(t=0;t<15;t++) { /* all finetunes should be zero */ - if(mh.samples[t].finetune) return 0; + if(h.samples[t].finetune) return 0; /* 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 */ - if((mh.samples[t].samplename[0]=='s')|| - (mh.samples[t].samplename[0]=='S')) { - if((memcmp(mh.samples[t].samplename,"st-",3)) && - (memcmp(mh.samples[t].samplename,"ST-",3)) && - (*mh.samples[t].samplename)) + if((h.samples[t].samplename[0]=='s')|| + (h.samples[t].samplename[0]=='S')) { + if((memcmp(h.samples[t].samplename,"st-",3)) && + (memcmp(h.samples[t].samplename,"ST-",3)) && + (*h.samples[t].samplename)) ust_loader = 1; } else - if(!isdigit((int)mh.samples[t].samplename[0])) + if(!isdigit((int)h.samples[t].samplename[0])) 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; - 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, this is likely to be an ust-style module */ - if((mh.samples[t].reppos+mh.samples[t].replen>mh.samples[t].length)&& - (mh.samples[t].reppos+mh.samples[t].replen<(mh.samples[t].length<<1))){ + if((h.samples[t].reppos+h.samples[t].replen>h.samples[t].length)&& + (h.samples[t].reppos+h.samples[t].replen<(h.samples[t].length<<1))) { ust_loader = 1; return 1; } - if(!ust_loader) return 1; + if(!ust_loader) return 1; } - for(numpat=0,t=0;tnumpat) - numpat = mh.positions[t]; + for(numpat=0,t=0;tnumpat) + numpat = h.positions[t]; numpat++; switch(CheckPatternType(numpat)) { case 0: /* indecisive, so check more clues... */ @@ -242,7 +241,7 @@ static int M15_Test(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; } @@ -250,6 +249,8 @@ static void M15_Cleanup(void) { MikMod_free(mh); MikMod_free(patbuf); + mh=NULL; + patbuf=NULL; } /* @@ -331,7 +332,7 @@ static UBYTE M15_ConvertNote(MODNOTE* n, UBYTE lasteffect) case 1: UniPTEffect(0,effdat); break; - case 2: + case 2: if(effdat&0xf) UniPTEffect(1,effdat&0xf); else if(effdat>>2) UniPTEffect(2,effdat>>2); break; @@ -351,7 +352,7 @@ static UBYTE M15_ConvertNote(MODNOTE* n, UBYTE lasteffect) } if (effect == 8) of.flags |= UF_PANNING; - + return effect; } @@ -372,8 +373,7 @@ static UBYTE *M15_ConvertTrack(MODNOTE* n) /* Loads all patterns of a modfile and converts them into the 3 byte format. */ static int M15_LoadPatterns(void) { - int t,tracks=0; - unsigned int s; + unsigned int t,s,tracks=0; if(!AllocPatterns()) return 0; if(!AllocTracks()) return 0; @@ -398,9 +398,10 @@ static int M15_LoadPatterns(void) static int M15_Load(int curious) { - int t,scan; + unsigned int t,scan; SAMPLE *q; MSAMPINFO *s; + (void)curious; /* try to read module header */ if(!LoadModuleHeader(mh)) { @@ -409,14 +410,14 @@ static int M15_Load(int curious) } if(ust_loader) - of.modtype = StrDup("Ultimate Soundtracker"); + of.modtype = MikMod_strdup("Ultimate Soundtracker"); else - of.modtype = StrDup("Soundtracker"); + of.modtype = MikMod_strdup("Soundtracker"); /* set module variables */ of.initspeed = 6; of.inittempo = 125; - of.numchn = 4; + of.numchn = 4; of.songname = DupStr(mh->songname,21,1); of.numpos = mh->songlength; of.reppos = 0; @@ -467,7 +468,7 @@ static int M15_Load(int curious) q->length = s->length<<1; q->flags = SF_SIGNED; - if(ust_loader) q->flags |= SF_UST_LOOP; + if(ust_loader) q->flags |= SF_UST_LOOP; if(s->replen>2) q->flags |= SF_LOOP; s++; diff --git a/apps/plugins/mikmod/load_med.c b/apps/plugins/mikmod/load_med.c index aafb6602a6..a6af8c06cb 100644 --- a/apps/plugins/mikmod/load_med.c +++ b/apps/plugins/mikmod/load_med.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_med.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id$ Amiga MED module loader @@ -189,6 +189,12 @@ static void MED_Cleanup(void) MikMod_free(ba); MikMod_free(mmd0pat); MikMod_free(mmd1pat); + me = NULL; + mh = NULL; + ms = NULL; + ba = NULL; + mmd0pat = NULL; + mmd1pat = NULL; } static void EffectCvt(UBYTE eff, UBYTE dat) @@ -338,7 +344,13 @@ static int LoadMEDPatterns(void) of.numchn = numtracks; if (numlines > maxlines) 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; if (!AllocTracks()) @@ -346,10 +358,8 @@ static int LoadMEDPatterns(void) if (!AllocPatterns()) return 0; - if (! - (mmd0pat = - (MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), - sizeof(MMD0NOTE)))) return 0; + if (!(mmd0pat = (MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD0NOTE)))) + return 0; /* second read: read and convert patterns */ for (t = 0; t < of.numpat; t++) { @@ -388,7 +398,15 @@ static int LoadMMD1Patterns(void) of.numchn = numtracks; if (numlines > maxlines) 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; if (!AllocTracks()) @@ -396,10 +414,8 @@ static int LoadMMD1Patterns(void) if (!AllocPatterns()) return 0; - if (! - (mmd1pat = - (MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), - sizeof(MMD1NOTE)))) return 0; + if (!(mmd1pat = (MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD1NOTE)))) + return 0; /* second read: really read and convert patterns */ 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->songlen = _mm_read_M_UWORD(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->playtransp = _mm_read_SBYTE(modreader); ms->flags = _mm_read_UBYTE(modreader); @@ -479,6 +500,11 @@ static int MED_Load(int curious) _mm_read_UBYTES(ms->trkvol, 16, modreader); ms->mastervol = _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 */ if (_mm_eof(modreader)) { @@ -505,6 +531,14 @@ static int MED_Load(int curious) me->songname = _mm_read_M_ULONG(modreader); me->songnamelen = _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 */ @@ -526,8 +560,14 @@ static int MED_Load(int curious) /* copy song positions */ if (!AllocPositions(ms->songlen)) return 0; - for (t = 0; t < ms->songlen; t++) + for (t = 0; t < ms->songlen; 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; bpmtempos = (ms->flags2 & 0x20) ? 1 : 0; @@ -571,7 +611,7 @@ static int MED_Load(int curious) of.flags |= UF_HIGHBPM; } MED_Version[12] = mh->id; - of.modtype = StrDup(MED_Version); + of.modtype = MikMod_strdup(MED_Version); of.numchn = 0; /* will be counted later */ of.numpat = ms->numblocks; of.numpos = ms->songlen; @@ -582,7 +622,7 @@ static int MED_Load(int curious) char *name; _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); of.songname = DupStr(name, me->songnamelen, 1); MikMod_free(name); @@ -684,17 +724,17 @@ static CHAR *MED_LoadTitle(void) { ULONG posit, namelen; CHAR *name, *retvalue = NULL; - + _mm_fseek(modreader, 0x20, SEEK_SET); posit = _mm_read_M_ULONG(modreader); - + if (posit) { _mm_fseek(modreader, posit + 0x2C, SEEK_SET); posit = _mm_read_M_ULONG(modreader); namelen = _mm_read_M_ULONG(modreader); _mm_fseek(modreader, posit, SEEK_SET); - name = MikMod_malloc(namelen); + name = (CHAR*) MikMod_malloc(namelen); _mm_read_UBYTES(name, namelen, modreader); retvalue = DupStr(name, namelen, 1); MikMod_free(name); diff --git a/apps/plugins/mikmod/load_mod.c b/apps/plugins/mikmod/load_mod.c index 6075e9c7e1..0fe0dcd595 100644 --- a/apps/plugins/mikmod/load_mod.c +++ b/apps/plugins/mikmod/load_mod.c @@ -6,12 +6,12 @@ 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 @@ -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) @@ -108,7 +108,7 @@ static int MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr) *numchn = 4; return 1; } - + /* Star Tracker */ if (((!memcmp(id, "FLT", 3)) || (!memcmp(id, "EXO", 3))) && (isdigit(id[3]))) { @@ -190,6 +190,8 @@ static void MOD_Cleanup(void) { MikMod_free(mh); MikMod_free(patbuf); + mh=NULL; + patbuf=NULL; } /* @@ -277,7 +279,7 @@ static UBYTE ConvertNote(MODNOTE *n, UBYTE lasteffect) /* Handle ``heavy'' volumes correctly */ if ((effect == 0xc) && (effdat > 0x40)) effdat = 0x40; - + /* An isolated 100, 200 or 300 effect should be ignored (no "standalone" porta memory in mod files). However, a sequence such as 1XX, 100, 100, 100 is fine. */ @@ -288,7 +290,7 @@ static UBYTE ConvertNote(MODNOTE *n, UBYTE lasteffect) UniPTEffect(effect, effdat); if (effect == 8) of.flags |= UF_PANNING; - + return effect; } @@ -309,14 +311,13 @@ static UBYTE *ConvertTrack(MODNOTE *n, int numchn) /* Loads all patterns of a modfile and converts them into the 3 byte format. */ static int ML_LoadPatterns(void) { - int t, tracks = 0; - unsigned int s; + unsigned int t, s, tracks = 0; if (!AllocPatterns()) return 0; if (!AllocTracks()) return 0; - + /* Allocate temporary buffer for loading and converting the patterns */ if (!(patbuf = (MODNOTE *)MikMod_calloc(64U * of.numchn, sizeof(MODNOTE)))) return 0; @@ -385,10 +386,10 @@ static int MOD_Load(int curious) mh->songlength = _mm_read_UBYTE(modreader); - /* this fixes mods which declare more than 128 positions. + /* this fixes mods which declare more than 128 positions. * eg: beatwave.mod */ if (mh->songlength > 128) { mh->songlength = 128; } - + mh->magic1 = _mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->positions, 128, modreader); _mm_read_UBYTES(mh->magic2, 4, modreader); @@ -477,11 +478,11 @@ static int MOD_Load(int curious) q++; } - of.modtype = StrDup(descr); + of.modtype = MikMod_strdup(descr); if (!ML_LoadPatterns()) return 0; - + return 1; } diff --git a/apps/plugins/mikmod/load_mtm.c b/apps/plugins/mikmod/load_mtm.c index 6c9fb30846..5620575a10 100644 --- a/apps/plugins/mikmod/load_mtm.c +++ b/apps/plugins/mikmod/load_mtm.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_mtm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + $Id$ MTM module loader @@ -108,6 +108,8 @@ static void MTM_Cleanup(void) { MikMod_free(mtmtrk); MikMod_free(mh); + mtmtrk=NULL; + mh=NULL; } static UBYTE* MTM_Convert(void) @@ -145,7 +147,7 @@ static int MTM_Load(int curious) int t,u; MTMSAMPLE s; SAMPLE *q; - (void)curious; + (void)curious; /* try to read module header */ _mm_read_UBYTES(mh->id,3,modreader); @@ -169,7 +171,7 @@ static int MTM_Load(int curious) /* set module variables */ of.initspeed = 6; of.inittempo = 125; - of.modtype = StrDup(MTM_Version); + of.modtype = MikMod_strdup(MTM_Version); of.numchn = mh->numchannels; of.numtrk = mh->numtracks+1; /* get number of channels */ of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ @@ -193,7 +195,7 @@ static int MTM_Load(int curious) s.attribute =_mm_read_UBYTE(modreader); if(_mm_eof(modreader)) { - _mm_errno = MMERR_LOADING_SAMPLEINFO; + _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } @@ -218,9 +220,15 @@ static int MTM_Load(int curious) } if(!AllocPositions(of.numpos)) return 0; - for(t=0;tof.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)) { _mm_errno = MMERR_LOADING_HEADER; return 0; @@ -231,12 +239,12 @@ static int MTM_Load(int curious) of.tracks[0]=MTM_Convert(); /* track 0 is empty */ for(t=1;tchannels[ch]<32) remap[ch] = 0; - if(flag&32) {(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader);} - if(flag&64) (void)_mm_read_UBYTE(modreader); - if(flag&128){(void)_mm_read_UBYTE(modreader);(void)_mm_read_UBYTE(modreader);} + if(flag&32) {_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);} + if(flag&64) _mm_skip_BYTE(modreader); + if(flag&128){_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);} } else row++; } - return 0; -} + return 1; +} static int S3M_ReadPattern(void) { @@ -282,6 +287,10 @@ static int S3M_Load(int curious) _mm_errno = MMERR_LOADING_HEADER; 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 */ tracker=mh->tracker>>12; @@ -294,7 +303,7 @@ static int S3M_Load(int curious) tracker=NUMTRACKERS; /* IT 2.14p3 */ else tracker--; } - of.modtype = StrDup(S3M_Version[tracker]); + of.modtype = MikMod_strdup(S3M_Version[tracker]); if(trackertracker>>8) &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 */ 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;tordnum;t++) { origpositions[t]=_mm_read_UBYTE(modreader); @@ -374,7 +383,8 @@ static int S3M_Load(int curious) _mm_read_string(s.scrs,4,modreader); /* 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; if(_mm_eof(modreader)) { @@ -388,7 +398,7 @@ static int S3M_Load(int curious) q->loopstart = s.loopbeg; q->loopend = s.loopend; 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&4) q->flags |= SF_16BITS; @@ -406,16 +416,16 @@ static int S3M_Load(int curious) for(t=0;tchannels[t]<32)&&(remap[t]!=-1)) { if(mh->channels[t]<8) of.panning[remap[t]]=0x30; diff --git a/apps/plugins/mikmod/load_stm.c b/apps/plugins/mikmod/load_stm.c index 994b0e5355..c62a6d7f36 100644 --- a/apps/plugins/mikmod/load_stm.c +++ b/apps/plugins/mikmod/load_stm.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -74,7 +74,7 @@ typedef struct STMHEADER { UBYTE ver_minor; UBYTE inittempo; /* initspeed= stm inittempo>>4 */ UBYTE numpat; /* number of patterns */ - UBYTE globalvol; + UBYTE globalvol; UBYTE reserved[13]; STMSAMPLE sample[31]; /* STM sample data */ UBYTE patorder[128]; /* Docs say 64 - actually 128 */ @@ -90,7 +90,7 @@ static STMNOTE *stmbuf = NULL; static STMHEADER *mh = NULL; /* tracker identifiers */ -static CHAR* STM_Version[STM_NTRACKERS] = { +static const CHAR * STM_Version[STM_NTRACKERS] = { "Screamtracker 2", "Converted by MOD2STM (STM format)", "Wuzamod (STM format)" @@ -103,6 +103,7 @@ static int STM_Test(void) UBYTE str[44]; int t; + memset(str,0,44); _mm_fseek(modreader,20,SEEK_SET); _mm_read_UBYTES(str,44,modreader); if(str[9]!=2) return 0; /* STM Module = filetype 2 */ @@ -110,7 +111,7 @@ static int STM_Test(void) /* Prevent false positives for S3M files */ if(!memcmp(str+40,"SCRM",4)) return 0; - + for (t=0;tsongname,20,modreader); @@ -272,6 +274,10 @@ static int STM_Load(int curious) mh->numpat =_mm_read_UBYTE(modreader); mh->globalvol =_mm_read_UBYTE(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++) { STMSAMPLE *s=&mh->sample[t]; /* STM sample data */ @@ -299,9 +305,7 @@ static int STM_Load(int curious) /* set module variables */ for(t=0;ttrackername,STM_Signatures[t],8)) break; - if(t == STM_NTRACKERS) - return 0; - of.modtype = StrDup(STM_Version[t]); + of.modtype = MikMod_strdup(STM_Version[t]); of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ of.numpat = mh->numpat; of.inittempo = 125; /* mh->inittempo+0x1c; */ @@ -316,7 +320,10 @@ static int STM_Load(int curious) /* 99 terminates the patorder list */ while((mh->patorder[t]<=99)&&(mh->patorder[t]numpat)) { of.positions[t]=mh->patorder[t]; - t++; + if(++t == 0x80) { + _mm_errno = MMERR_NOT_A_MODULE; + return 0; + } } if(mh->patorder[t]<=99) t++; of.numpos=t; @@ -334,7 +341,7 @@ static int STM_Load(int curious) q->speed = (mh->sample[t].c2spd * 8363) / 8448; q->volume = mh->sample[t].volume; 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->loopend = mh->sample[t].loopend; q->seekpos = MikMod_ISA; @@ -374,5 +381,4 @@ MIKMODAPI MLOADER load_stm={ STM_LoadTitle }; - /* ex:set ts=4: */ diff --git a/apps/plugins/mikmod/load_stx.c b/apps/plugins/mikmod/load_stx.c index ac6e51f4c7..db25813342 100644 --- a/apps/plugins/mikmod/load_stx.c +++ b/apps/plugins/mikmod/load_stx.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -114,13 +114,14 @@ static int STX_Test(void) UBYTE id[8]; int t; + memset(id,0,8); _mm_fseek(modreader,0x3C,SEEK_SET); if(!_mm_read_UBYTES(id,4,modreader)) return 0; if(memcmp(id,"SCRM",4)) return 0; _mm_fseek(modreader,0x14,SEEK_SET); if(!_mm_read_UBYTES(id,8,modreader)) return 0; - + for(t=0;tordnum > 256 || !mh->insnum || mh->insnum > 256 || + mh->patnum > 254 || !mh->patnum) { + _mm_errno = MMERR_NOT_A_MODULE; + return 0; + } /* set module variables */ of.songname = DupStr(mh->songname,20,1); @@ -323,10 +333,10 @@ static int STX_Load(int curious) version=_mm_read_I_UWORD(modreader); if(version==mh->patsize) { version = 0x10; - of.modtype = StrDup("STMIK 0.2 (STM2STX 1.0)"); + of.modtype = MikMod_strdup("STMIK 0.2 (STM2STX 1.0)"); } else { 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 */ @@ -343,7 +353,7 @@ static int STX_Load(int curious) if(order==255) order=LAST_PATTERN; of.positions[of.numpos]=order; poslookup[t]=of.numpos; /* bug fix for freaky S3Ms */ - if(of.positions[t]<254) of.numpos++; + if(of.positions[t]<254) of.numpos++; else /* special end of song pattern */ if((order==LAST_PATTERN)&&(!curious)) break; @@ -389,7 +399,7 @@ static int STX_Load(int curious) q->loopstart = s.loopbeg; q->loopend = s.loopend; 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; if(s.flags&1) q->flags |= SF_LOOP; diff --git a/apps/plugins/mikmod/load_ult.c b/apps/plugins/mikmod/load_ult.c index f56c2df06b..1d4e5cf72b 100644 --- a/apps/plugins/mikmod/load_ult.c +++ b/apps/plugins/mikmod/load_ult.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_ult.c,v 1.3 2010/01/12 03:30:32 realtech Exp $ + $Id$ Ultratracker (ULT) module loader @@ -80,7 +80,7 @@ typedef struct ULTEVENT { #define ULTS_REVERSE 16 #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; @@ -130,8 +130,8 @@ static int ULT_Load(int curious) SAMPLE *q; ULTSAMPLE s; ULTHEADER mh; - UBYTE nos,noc,rbnop; - (void)curious; + UBYTE nos,noc,RBnop; + (void)curious; /* try to read module header */ _mm_read_string(mh.id,15,modreader); @@ -207,29 +207,37 @@ static int ULT_Load(int curious) if(!AllocPositions(256)) return 0; for(t=0;t<256;t++) 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) { of.positions[t]=LAST_PATTERN; 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; - 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(!AllocPatterns()) return 0; for(u=0;u=UF_MAXCHAN) of.numchn=UF_MAXCHAN - 1; - + /* read pan position table for v1.5 and higher */ if(mh.id[14]>='3') { for(t=0;t + * + * 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 , 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 +#include +#include + +#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: */ diff --git a/apps/plugins/mikmod/load_uni.c b/apps/plugins/mikmod/load_uni.c index 7bedd8f16c..834fd3a85a 100644 --- a/apps/plugins/mikmod/load_uni.c +++ b/apps/plugins/mikmod/load_uni.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -94,18 +94,18 @@ static UNISMP05 *wh=NULL,*s=NULL; /*========== Loader code */ -static char* readstring(void) +static char * readstring(void) { - char *s=NULL; + char *str=NULL; UWORD len; - + len=_mm_read_I_UWORD(modreader); if(len) { - s=MikMod_malloc(len+1); - _mm_read_UBYTES(s,len,modreader); - s[len]=0; + str=(char *) MikMod_malloc(len+1); + _mm_read_UBYTES(str,len,modreader); + str[len]=0; } - return s; + return str; } static int UNI_Test(void) @@ -133,7 +133,7 @@ static int UNI_Init(void) static void UNI_Cleanup(void) { MikMod_free(wh); - s=NULL; + wh = s = NULL; } static UBYTE* readtrack(void) @@ -148,7 +148,7 @@ static UBYTE* readtrack(void) len=_mm_read_I_UWORD(modreader); 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); /* Check if the track is correct */ @@ -221,65 +221,65 @@ static UBYTE* readtrack(void) static int loadsmp6(void) { int t; - SAMPLE *s; + SAMPLE *sptr; - s=of.samples; - for(t=0;tflags=0; - if(flags&0x0004) s->flags|=SF_STEREO; - if(flags&0x0002) s->flags|=SF_SIGNED; - if(flags&0x0001) s->flags|=SF_16BITS; + sptr->flags=0; + if(flags&0x0004) sptr->flags|=SF_STEREO; + if(flags&0x0002) sptr->flags|=SF_SIGNED; + if(flags&0x0001) sptr->flags|=SF_16BITS; /* convert flags */ if(universion>=0x104) { - if(flags&0x2000) s->flags|=SF_UST_LOOP; - if(flags&0x1000) s->flags|=SF_OWNPAN; - if(flags&0x0800) s->flags|=SF_SUSTAIN; - if(flags&0x0400) s->flags|=SF_REVERSE; - if(flags&0x0200) s->flags|=SF_BIDI; - if(flags&0x0100) s->flags|=SF_LOOP; - if(flags&0x0020) s->flags|=SF_ITPACKED; - if(flags&0x0010) s->flags|=SF_DELTA; - if(flags&0x0008) s->flags|=SF_BIG_ENDIAN; + if(flags&0x2000) sptr->flags|=SF_UST_LOOP; + if(flags&0x1000) sptr->flags|=SF_OWNPAN; + if(flags&0x0800) sptr->flags|=SF_SUSTAIN; + if(flags&0x0400) sptr->flags|=SF_REVERSE; + if(flags&0x0200) sptr->flags|=SF_BIDI; + if(flags&0x0100) sptr->flags|=SF_LOOP; + if(flags&0x0020) sptr->flags|=SF_ITPACKED; + if(flags&0x0010) sptr->flags|=SF_DELTA; + if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN; } else if(universion>=0x102) { - if(flags&0x0800) s->flags|=SF_UST_LOOP; - if(flags&0x0400) s->flags|=SF_OWNPAN; - if(flags&0x0200) s->flags|=SF_SUSTAIN; - if(flags&0x0100) s->flags|=SF_REVERSE; - if(flags&0x0080) s->flags|=SF_BIDI; - if(flags&0x0040) s->flags|=SF_LOOP; - if(flags&0x0020) s->flags|=SF_ITPACKED; - if(flags&0x0010) s->flags|=SF_DELTA; - if(flags&0x0008) s->flags|=SF_BIG_ENDIAN; + if(flags&0x0800) sptr->flags|=SF_UST_LOOP; + if(flags&0x0400) sptr->flags|=SF_OWNPAN; + if(flags&0x0200) sptr->flags|=SF_SUSTAIN; + if(flags&0x0100) sptr->flags|=SF_REVERSE; + if(flags&0x0080) sptr->flags|=SF_BIDI; + if(flags&0x0040) sptr->flags|=SF_LOOP; + if(flags&0x0020) sptr->flags|=SF_ITPACKED; + if(flags&0x0010) sptr->flags|=SF_DELTA; + if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN; } else { - if(flags&0x400) s->flags|=SF_UST_LOOP; - if(flags&0x200) s->flags|=SF_OWNPAN; - if(flags&0x100) s->flags|=SF_REVERSE; - if(flags&0x080) s->flags|=SF_SUSTAIN; - if(flags&0x040) s->flags|=SF_BIDI; - if(flags&0x020) s->flags|=SF_LOOP; - if(flags&0x010) s->flags|=SF_BIG_ENDIAN; - if(flags&0x008) s->flags|=SF_DELTA; + if(flags&0x400) sptr->flags|=SF_UST_LOOP; + if(flags&0x200) sptr->flags|=SF_OWNPAN; + if(flags&0x100) sptr->flags|=SF_REVERSE; + if(flags&0x080) sptr->flags|=SF_SUSTAIN; + if(flags&0x040) sptr->flags|=SF_BIDI; + if(flags&0x020) sptr->flags|=SF_LOOP; + if(flags&0x010) sptr->flags|=SF_BIG_ENDIAN; + if(flags&0x008) sptr->flags|=SF_DELTA; } - s->speed = _mm_read_M_ULONG(modreader); - s->volume = _mm_read_UBYTE(modreader); - s->panning = _mm_read_M_UWORD(modreader); - s->length = _mm_read_M_ULONG(modreader); - s->loopstart = _mm_read_M_ULONG(modreader); - s->loopend = _mm_read_M_ULONG(modreader); - s->susbegin = _mm_read_M_ULONG(modreader); - s->susend = _mm_read_M_ULONG(modreader); - s->globvol = _mm_read_UBYTE(modreader); - s->vibflags = _mm_read_UBYTE(modreader); - s->vibtype = _mm_read_UBYTE(modreader); - s->vibsweep = _mm_read_UBYTE(modreader); - s->vibdepth = _mm_read_UBYTE(modreader); - s->vibrate = _mm_read_UBYTE(modreader); - - s->samplename=readstring(); + sptr->speed = _mm_read_M_ULONG(modreader); + sptr->volume = _mm_read_UBYTE(modreader); + sptr->panning = _mm_read_M_UWORD(modreader); + sptr->length = _mm_read_M_ULONG(modreader); + sptr->loopstart = _mm_read_M_ULONG(modreader); + sptr->loopend = _mm_read_M_ULONG(modreader); + sptr->susbegin = _mm_read_M_ULONG(modreader); + sptr->susend = _mm_read_M_ULONG(modreader); + sptr->globvol = _mm_read_UBYTE(modreader); + sptr->vibflags = _mm_read_UBYTE(modreader); + sptr->vibtype = _mm_read_UBYTE(modreader); + sptr->vibsweep = _mm_read_UBYTE(modreader); + sptr->vibdepth = _mm_read_UBYTE(modreader); + sptr->vibrate = _mm_read_UBYTE(modreader); + + sptr->samplename=readstring(); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; @@ -308,7 +308,7 @@ static int loadinstr6(void) i->rpanvar = _mm_read_UBYTE(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) \ i-> name##flg=_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++) 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) \ i-> name##flg=_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 */ if(of.numsmp+u==wavcnt) { 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; return 0; } @@ -447,7 +447,7 @@ static int loadinstr5(void) /* sanity check */ if(!of.numsmp) { - if(wh) { MikMod_free(wh);wh=NULL; } + MikMod_free(wh);wh=NULL; _mm_errno=MMERR_LOADING_SAMPLEINFO; return 0; } @@ -504,8 +504,8 @@ static int UNI_Load(int curious) char *modtype,*oldtype=NULL; INSTRUMENT *d; SAMPLE *q; - (void)curious; - + (void)curious; + /* read module header */ _mm_read_UBYTES(mh.id,4,modreader); if(mh.id[3]!='N') @@ -514,11 +514,11 @@ static int UNI_Load(int curious) universion=0x100; if(universion>=6) { - if (universion==6) - (void)_mm_read_UBYTE(modreader); - else + if (universion==6) { + _mm_skip_BYTE(modreader); + } else { universion=_mm_read_M_UWORD(modreader); - + } mh.flags =_mm_read_M_UWORD(modreader); mh.numchn =_mm_read_UBYTE(modreader); mh.numvoices =_mm_read_UBYTE(modreader); @@ -556,7 +556,7 @@ static int UNI_Load(int curious) mh.flags &= UF_XMPERIODS | UF_LINEAR; mh.flags |= UF_INST | UF_NOWRAP | UF_PANNING; } - + /* set module parameters */ of.flags =mh.flags; of.numchn =mh.numchn; @@ -578,21 +578,21 @@ static int UNI_Load(int curious) oldtype=readstring(); if(oldtype) { size_t len=strlen(oldtype)+20; - if(!(modtype=MikMod_malloc(len))) return 0; + if(!(modtype=(char*)MikMod_malloc(len))) return 0; #ifdef HAVE_SNPRINTF snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); #else sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype); #endif } else { - if(!(modtype=MikMod_malloc(10))) return 0; + if(!(modtype=(char*)MikMod_malloc(10))) return 0; #ifdef HAVE_SNPRINTF snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); #else sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3"); #endif } - of.modtype=StrDup(modtype); + of.modtype=MikMod_strdup(modtype); MikMod_free(modtype);MikMod_free(oldtype); of.comment=readstring(); @@ -624,9 +624,14 @@ static int UNI_Load(int curious) for(t=0;tof.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 */ if(universion>=6) { @@ -642,7 +647,7 @@ static int UNI_Load(int curious) if(!AllocInstruments()) return 0; if(!loadinstr5()) return 0; if(!AllocSamples()) { - if(wh) { MikMod_free(wh);wh=NULL; } + MikMod_free(wh);wh=NULL; return 0; } if(!loadsmp5()) return 0; diff --git a/apps/plugins/mikmod/load_xm.c b/apps/plugins/mikmod/load_xm.c index ffbd6dff4d..3eb0803668 100644 --- a/apps/plugins/mikmod/load_xm.c +++ b/apps/plugins/mikmod/load_xm.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: load_xm.c,v 1.5 2008/02/29 18:49:03 denis111 Exp $ + $Id$ Fasttracker (XM) module loader @@ -59,7 +59,7 @@ typedef struct XMHEADER { UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */ UWORD numpat; /* Number of patterns (max 256) */ UWORD numins; /* Number of instruments (max 128) */ - UWORD flags; + UWORD flags; UWORD tempo; /* Default tempo */ UWORD bpm; /* Default BPM */ UBYTE orders[256]; /* Pattern order table */ @@ -129,7 +129,7 @@ typedef struct XMNOTE { static XMNOTE *xmpat=NULL; static XMHEADER *mh=NULL; -/* increment unit for sample array MikMod_reallocation */ +/* increment unit for sample array reallocation */ #define XM_SMPINCR 64 static ULONG *nextwav=NULL; static XMWAVHEADER *wh=NULL,*s=NULL; @@ -155,6 +155,7 @@ static int XM_Init(void) static void XM_Cleanup(void) { MikMod_free(mh); + mh=NULL; } static int XM_ReadNote(XMNOTE* n) @@ -359,8 +360,8 @@ static int LoadPatterns(int dummypat) return 0; /* when packsize is 0, don't try to load a pattern.. it's empty. */ - if(ph.packsize) - for(u=0;u=_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 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((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) { - if(nextwav) { MikMod_free(nextwav);nextwav=NULL; } - if(wh) { MikMod_free(wh);wh=NULL; } + MikMod_free(nextwav);nextwav=NULL; + MikMod_free(wh);wh=NULL; _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } @@ -519,7 +527,7 @@ static int LoadInstruments(void) d->samplenumber[u]=pth.what[u]+of.numsmp; 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) \ for (u = 0; u < (XMENVCNT >> 1); u++) { \ d-> name##env[u].pos = pth. name##env[u << 1]; \ @@ -560,7 +568,7 @@ static int LoadInstruments(void) \ if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \ d-> name/**/flg&=~EF_ON -#endif +#endif XM_ProcessEnvelope(vol); XM_ProcessEnvelope(pan); @@ -577,15 +585,23 @@ static int LoadInstruments(void) everything over */ if(mh->version>0x0103) next = 0; for(u=0;ufilend) { + 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 */ if(of.numsmp+u==wavcnt) { wavcnt+=XM_SMPINCR; - if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){ - if(wh) { MikMod_free(wh);wh=NULL; } + if(!(nextwav=(ULONG*)MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){ + MikMod_free(wh);wh=NULL; _mm_errno = MMERR_OUT_OF_MEMORY; return 0; } - if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) { + if(!(wh=(XMWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) { MikMod_free(nextwav);nextwav=NULL; _mm_errno = MMERR_OUT_OF_MEMORY; return 0; @@ -610,13 +626,6 @@ static int LoadInstruments(void) nextwav[of.numsmp+u]=next; 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) { @@ -628,15 +637,15 @@ static int LoadInstruments(void) } else { /* read the remainder of the header */ ck = _mm_ftell(modreader); - _mm_fseek(modreader,0,SEEK_END); - if ((headend<0) || (_mm_ftell(modreader)version<0x0104 || tid,17,modreader); _mm_read_string(mh->songname,21,modreader); _mm_read_string(mh->trackername,20,modreader); mh->version =_mm_read_I_UWORD(modreader); - if((mh->version<0x102)||(mh->version>0x104)) { - _mm_errno=MMERR_NOT_A_MODULE; - return 0; - } + if(mh->version < 0x102 || mh->version > 0x104) + goto bad_xm; mh->headersize =_mm_read_I_ULONG(modreader); mh->songlength =_mm_read_I_UWORD(modreader); mh->restart =_mm_read_I_UWORD(modreader); @@ -684,23 +691,25 @@ static int XM_Load(int curious) mh->flags =_mm_read_I_UWORD(modreader); mh->tempo =_mm_read_I_UWORD(modreader); mh->bpm =_mm_read_I_UWORD(modreader); - if(!mh->bpm) { - _mm_errno=MMERR_NOT_A_MODULE; - return 0; - } - _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader); - - if(_mm_eof(modreader)) { - _mm_errno = MMERR_LOADING_HEADER; - return 0; - } + if(mh->numchn > 64) goto bad_xm; + if(mh->tempo > 32 || mh->bpm < 32 || mh->bpm > 255) + goto bad_xm; + if(mh->songlength > 256 || mh->headersize < 20 || mh->headersize > 20+256) + goto bad_xm; + if(mh->numpat > 256 || mh->numins > 255 || mh->restart > 255) + goto bad_xm; +/* _mm_read_UBYTES(mh->orders,256,modreader);*/ +/* _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 */ - of.initspeed = mh->tempo; + of.initspeed = mh->tempo; of.inittempo = mh->bpm; strncpy(tracker,mh->trackername,20);tracker[20]=0; - for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0; - + for(t=20;(t>=0)&&(tracker[t]<=' ');t--) tracker[t]=0; + /* some modules have the tracker name empty */ if (!tracker[0]) strcpy(tracker,"Unknown tracker"); @@ -712,7 +721,7 @@ static int XM_Load(int curious) sprintf(modtype,"%s (XM format %d.%02d)", tracker,mh->version>>8,mh->version&0xff); #endif - of.modtype = StrDup(modtype); + of.modtype = MikMod_strdup(modtype); of.numchn = mh->numchn; of.numpat = mh->numpat; 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.reppos = mh->restartsonglength?mh->restart:0; of.numins = mh->numins; - of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | - UF_PANNING; + of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | UF_PANNING; if(mh->flags&1) of.flags |= UF_LINEAR; of.bpmlimit = 32; @@ -802,16 +810,19 @@ static int XM_Load(int curious) MikMod_free(wh);MikMod_free(nextwav); wh=NULL;nextwav=NULL; 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) { - CHAR s[21]; + CHAR str[21]; _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 */ diff --git a/apps/plugins/mikmod/mdreg.c b/apps/plugins/mikmod/mdreg.c index 6cbaad2932..ff5d803000 100644 --- a/apps/plugins/mikmod/mdreg.c +++ b/apps/plugins/mikmod/mdreg.c @@ -6,12 +6,12 @@ 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 @@ -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. ==============================================================================*/ @@ -34,12 +32,13 @@ static void _mm_registeralldrivers(void) { -#if 0 - /* Register network drivers */ #ifdef DRV_AF _mm_registerdriver(&drv_AF); #endif +#ifdef DRV_PULSEAUDIO + _mm_registerdriver(&drv_pulseaudio); +#endif #ifdef DRV_ESD _mm_registerdriver(&drv_esd); #endif @@ -51,8 +50,22 @@ static void _mm_registeralldrivers(void) #ifdef DRV_ULTRA _mm_registerdriver(&drv_ultra); #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 _mm_registerdriver(&drv_aix); #endif @@ -62,6 +75,9 @@ static void _mm_registeralldrivers(void) #ifdef DRV_HP _mm_registerdriver(&drv_hp); #endif +#ifdef DRV_SNDIO + _mm_registerdriver(&drv_sndio); +#endif #ifdef DRV_OSS _mm_registerdriver(&drv_oss); #endif @@ -77,6 +93,9 @@ static void _mm_registeralldrivers(void) #ifdef DRV_OS2 _mm_registerdriver(&drv_os2); #endif +#ifdef DRV_XAUDIO2 + _mm_registerdriver(&drv_xaudio2); +#endif #ifdef DRV_DS _mm_registerdriver(&drv_ds); #endif @@ -89,39 +108,54 @@ static void _mm_registeralldrivers(void) #ifdef DRV_OSX _mm_registerdriver(&drv_osx); #endif +#ifdef DRV_DC + _mm_registerdriver(&drv_dc); +#endif #ifdef DRV_GP32 _mm_registerdriver(&drv_gp32); #endif - - /* dos drivers */ +#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 - wss first, since some cards emulate sb */ #ifdef DRV_WSS - /* wss first, since some cards emulate sb */ _mm_registerdriver(&drv_wss); #endif #ifdef DRV_SB _mm_registerdriver(&drv_sb); #endif - + /* Register disk writers */ - _mm_registerdriver(&drv_raw); +#ifdef DRV_WAV _mm_registerdriver(&drv_wav); +#endif #ifdef DRV_AIFF _mm_registerdriver(&drv_aiff); #endif - +#ifdef DRV_RAW + _mm_registerdriver(&drv_raw); +#endif + /* Register other drivers */ #ifdef DRV_PIPE _mm_registerdriver(&drv_pipe); #endif -#ifndef macintosh +#if defined(DRV_STDOUT) && !defined(macintosh) _mm_registerdriver(&drv_stdout); #endif -#endif + /* Register 'nosound' driver */ _mm_registerdriver(&drv_nos); } -void MikMod_RegisterAllDrivers(void) +MIKMODAPI void MikMod_RegisterAllDrivers(void) { MUTEX_LOCK(lists); _mm_registeralldrivers(); diff --git a/apps/plugins/mikmod/mdriver.c b/apps/plugins/mikmod/mdriver.c index 2e8e9b5e41..2e1f8063b9 100644 --- a/apps/plugins/mikmod/mdriver.c +++ b/apps/plugins/mikmod/mdriver.c @@ -1,17 +1,17 @@ /* MikMod sound library - (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS - for complete list. + (c) 1998-2014 Miodrag Vallat and others - see file AUTHORS + for a 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 @@ -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. ==============================================================================*/ @@ -34,54 +32,59 @@ #include #endif -#if 0 -#if defined unix || (defined __APPLE__ && defined __MACH__) -#include -#include -#endif -#endif - #include -#ifdef HAVE_STRINGS_H -#include -#endif #include "mikmod_internals.h" +#if (MIKMOD_UNIX) +#include +#include +#endif + #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif -static MDRIVER *firstdriver=NULL; -MIKMODAPI MDRIVER *md_driver=NULL; extern MODULE *pf; /* modfile being played */ +/* EXPORTED GLOBALS */ +MIKMODAPI MDRIVER *md_driver = NULL; + /* Initial global settings */ -MIKMODAPI UWORD md_device = 0; /* autodetect */ -MIKMODAPI UWORD md_mixfreq = 44100; -MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS | - DMODE_SURROUND |DMODE_SOFT_MUSIC | - DMODE_SOFT_SNDFX; -MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ -MIKMODAPI UBYTE md_reverb = 0; /* no reverb */ -MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */ -MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */ -MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */ - UWORD md_bpm = 125; /* tempo */ - -/* Do not modify the numchn variables yourself! use MD_SetVoices() */ - UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0; - UBYTE md_hardchn=0,md_softchn=0; - - void (*md_player)(void) = Player_HandleTick; -static volatile int isplaying=0, initialized = 0; -static UBYTE *sfxinfo; -static int sfxpool; - -static SAMPLE **md_sample = NULL; +MIKMODAPI UWORD md_device = 0; /* autodetect */ +MIKMODAPI ULONG md_mixfreq = 44100; +MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS | + DMODE_SURROUND | + DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; +MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ +MIKMODAPI UBYTE md_reverb = 0; /* no reverb */ +MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */ +MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */ +MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */ + +/* INTERNAL GLOBALS */ +UWORD md_bpm = 125; /* tempo */ + +/* 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; + +static UBYTE *sfxinfo; +static int sfxpool; + +static SAMPLE **md_sample = NULL; /* Previous driver in use */ -static SWORD olddevice = -1; +static SWORD olddevice = -1; /* Limits the number of hardware voices to the specified amount. This function should only be used by the low-level drivers. */ @@ -183,17 +186,18 @@ MIKMODAPI CHAR* MikMod_InfoDriver(void) MUTEX_LOCK(lists); /* compute size of buffer */ - for(l=firstdriver;l;l=l->next) - len+=4+(l->next?1:0)+strlen(l->Version); + for(l = firstdriver; l; l = l->next) + len += 4 + (l->next ? 1 : 0) + strlen(l->Version); if(len) - if((list=MikMod_malloc(len*sizeof(CHAR)))) { - list[0]=0; - /* list all registered device drivers : */ - for(t=1,l=firstdriver;l;l=l->next,t++) - sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s", - list,t,l->Version); + if((list=(CHAR*)MikMod_malloc(len*sizeof(CHAR))) != NULL) { + CHAR *list_end = list; + list[0] = 0; + /* list all registered device drivers : */ + for(t = 1, l = firstdriver; l; l = l->next, t++) { + list_end += sprintf(list_end, "%2d %s%s", t, l->Version, (l->next)? "\n" : ""); } + } MUTEX_UNLOCK(lists); return list; } @@ -214,7 +218,7 @@ void _mm_registerdriver(struct MDRIVER* drv) } cruise->next = drv; } else - firstdriver = drv; + firstdriver = drv; } } @@ -230,7 +234,7 @@ MIKMODAPI void MikMod_RegisterDriver(struct MDRIVER* drv) MUTEX_UNLOCK(lists); } -MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias) +MIKMODAPI int MikMod_DriverFromAlias(const CHAR *alias) { int rank=1; MDRIVER *cruise; @@ -252,18 +256,17 @@ MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias) MIKMODAPI MDRIVER *MikMod_DriverByOrdinal(int ordinal) { - MDRIVER *cruise; + MDRIVER *cruise; - /* Allow only driver ordinals > 0 */ - if (!ordinal) - return 0; + /* Allow only driver ordinals > 0 */ + if (!ordinal) return NULL; - MUTEX_LOCK(lists); - cruise = firstdriver; - while (cruise && --ordinal) - cruise = cruise->next; - MUTEX_UNLOCK(lists); - return cruise; + MUTEX_LOCK(lists); + cruise = firstdriver; + while (cruise && --ordinal) + cruise = cruise->next; + MUTEX_UNLOCK(lists); + return cruise; } SWORD MD_SampleLoad(SAMPLOAD* s, int type) @@ -496,14 +499,12 @@ MIKMODAPI ULONG Voice_RealVolume(SBYTE voice) return result; } -extern MikMod_callback_t vc_callback; - MIKMODAPI void VC_SetCallback(MikMod_callback_t callback) { vc_callback = callback; } -static int _mm_init(CHAR *cmdline) +static int _mm_init(const CHAR *cmdline) { UWORD t; @@ -561,7 +562,7 @@ static int _mm_init(CHAR *cmdline) return 0; } -MIKMODAPI int MikMod_Init(CHAR *cmdline) +MIKMODAPI int MikMod_Init(const CHAR *cmdline) { int result; @@ -581,8 +582,8 @@ void MikMod_Exit_internal(void) md_numchn = md_sfxchn = md_sngchn = 0; md_driver = &drv_nos; - if(sfxinfo) MikMod_free(sfxinfo); - if(md_sample) MikMod_free(md_sample); + MikMod_free(sfxinfo); + MikMod_free(md_sample); md_sample = NULL; sfxinfo = NULL; @@ -598,14 +599,14 @@ MIKMODAPI void MikMod_Exit(void) MUTEX_UNLOCK(vars); } -/* 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. */ -static int _mm_reset(CHAR *cmdline) +static int _mm_reset(const CHAR *cmdline) { int wasplaying = 0; if(!initialized) return _mm_init(cmdline); - + if (isplaying) { wasplaying = 1; md_driver->PlayStop(); @@ -629,12 +630,12 @@ static int _mm_reset(CHAR *cmdline) return 1; } } - - if (wasplaying) md_driver->PlayStart(); + + if (wasplaying) return md_driver->PlayStart(); return 0; } -MIKMODAPI int MikMod_Reset(CHAR *cmdline) +MIKMODAPI int MikMod_Reset(const CHAR *cmdline) { int result; @@ -661,8 +662,8 @@ int MikMod_SetNumVoices_internal(int music, int sfx) resume = 1; } - if(sfxinfo) MikMod_free(sfxinfo); - if(md_sample) MikMod_free(md_sample); + MikMod_free(sfxinfo); + MikMod_free(md_sample); md_sample = NULL; sfxinfo = NULL; @@ -764,7 +765,7 @@ MIKMODAPI int MikMod_Active(void) allocated for use as sound effects (loops through voices, skipping all active criticals). - Returns the voice that the sound is being played on. */ + Returns the voice that the sound is being played on. */ static SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags) { int orig=sfxpool;/* for cases where all channels are critical */ @@ -825,12 +826,15 @@ MIKMODAPI long MikMod_GetVersion(void) #ifdef HAVE_PTHREAD #define INIT_MUTEX(name) \ pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER + #elif defined(__OS2__)||defined(__EMX__) #define INIT_MUTEX(name) \ HMTX _mm_mutex_##name -#elif defined(WIN32) + +#elif defined(_WIN32) #define INIT_MUTEX(name) \ HANDLE _mm_mutex_##name + #else #define INIT_MUTEX(name) \ void *_mm_mutex_##name = NULL @@ -842,8 +846,8 @@ INIT_MUTEX(lists); MIKMODAPI int MikMod_InitThreads(void) { static int firstcall=1; - static int result=0; - + static int result = 0; + if (firstcall) { firstcall=0; #ifdef HAVE_PTHREAD @@ -855,9 +859,9 @@ MIKMODAPI int MikMod_InitThreads(void) result=0; } else result=1; -#elif defined(WIN32) - if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))|| - (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)")))) +#elif defined(_WIN32) + if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,TEXT("libmikmod(lists)"))))|| + (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,TEXT("libmikmod(vars)"))))) result=0; else result=1; @@ -880,24 +884,24 @@ MIKMODAPI void MikMod_Lock(void) /*========== 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; if(cmdline) { - CHAR *buf=strstr(cmdline,atomname); + const CHAR *buf=strstr(cmdline,atomname); if((buf)&&((buf==cmdline)||(*(buf-1)==','))) { - CHAR *ptr=buf+strlen(atomname); + const CHAR *ptr=buf+strlen(atomname); if(*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) strncpy(ret,buf,ptr-buf); } else if((*ptr==',')||(!*ptr)) { if(implicit) { - ret=MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); + ret=(CHAR *)MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); if(ret) strncpy(ret,buf,ptr-buf); } @@ -907,8 +911,7 @@ CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,int implicit) return ret; } -#if 0 -#if defined unix || (defined __APPLE__ && defined __MACH__) +#if (MIKMOD_UNIX) /*========== 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. The goal is to prevent a setuid root libmikmod application from overriding files like /etc/passwd with digital sound... */ -int MD_Access(CHAR *filename) +int MD_Access(const CHAR * filename) { struct stat buf; @@ -934,7 +937,7 @@ int MD_Access(CHAR *filename) } else if(!(buf.st_mode&S_IWOTH)) return 0; } - + return 1; } @@ -961,5 +964,5 @@ int MD_DropPrivileges(void) } #endif -#endif -/* ex:set ts=4: */ + +/* ex:set ts=8: */ diff --git a/apps/plugins/mikmod/mikmod.c b/apps/plugins/mikmod/mikmod.c index 688baed56c..0eba320f18 100644 --- a/apps/plugins/mikmod/mikmod.c +++ b/apps/plugins/mikmod/mikmod.c @@ -25,7 +25,7 @@ /* Persistent configuration */ #define MIKMOD_CONFIGFILE "mikmod.cfg" #define MIKMOD_SETTINGS_MINVERSION 1 -#define MIKMOD_SETTINGS_VERSION 1 +#define MIKMOD_SETTINGS_VERSION 2 #ifdef USETHREADS #define EV_EXIT 9999 @@ -161,7 +161,6 @@ static bool mod_ext(const char ext[]) !rb->strcasecmp(ext,".dsm") || !rb->strcasecmp(ext,".far") || !rb->strcasecmp(ext,".gdm") || - !rb->strcasecmp(ext,".gt2") || !rb->strcasecmp(ext,".imf") || !rb->strcasecmp(ext,".it") || !rb->strcasecmp(ext,".m15") || @@ -174,6 +173,7 @@ static bool mod_ext(const char ext[]) !rb->strcasecmp(ext,".stx") || !rb->strcasecmp(ext,".ult") || !rb->strcasecmp(ext,".uni") || + !rb->strcasecmp(ext,".umx") || !rb->strcasecmp(ext,".xm") ) return true; else @@ -305,7 +305,7 @@ static void showinfo(void) rb->lcd_putsxy(1, 1, statustext); sprintf(statustext, "Type: %s", module->modtype); rb->lcd_putsxy(1, 11, statustext); - + sprintf(statustext, "Samples: %d", module->numsmp); rb->lcd_putsxy(1, 21, statustext); @@ -315,25 +315,25 @@ static void showinfo(void) rb->lcd_putsxy(1, 31, statustext); } - sprintf(statustext, "pat: %03d/%03d %2.2X", + sprintf(statustext, "pat: %03d/%03d %2.2X", module->sngpos, module->numpos - 1, module->patpos); rb->lcd_putsxy(1, 51, statustext); - sprintf(statustext, "spd: %d/%d", + sprintf(statustext, "spd: %d/%d", module->sngspd, module->bpm); rb->lcd_putsxy(1, 61, statustext); sprintf(statustext, "vol: %ddB", rb->global_settings->volume); rb->lcd_putsxy(1, 71, statustext); - sprintf(statustext, "time: %d:%02d", + sprintf(statustext, "time: %d:%02d", (playingtime / 60) % 60, playingtime % 60); rb->lcd_putsxy(1, 81, statustext); if (module->flags & UF_NNA) { sprintf(statustext, "chn: %d/%d+%d->%d", - module->realchn, module->numchn, + module->realchn, module->numchn, module->totalchn - module->realchn, module->totalchn); } @@ -465,32 +465,44 @@ struct mikmod_settings { int pansep; int reverb; + int sample_rate; bool interp; bool reverse; bool surround; + bool hqmixer; +#ifdef HAVE_ADJUSTABLE_CPU_FREQ bool boost; +#endif }; static struct mikmod_settings settings = { - 128, - 0, - 0, - 0, - 1, - 1 + .pansep = 128, + .reverb = 0, + .sample_rate = -1, + .interp = 0, + .reverse = 0, + .surround = 1, + .hqmixer = 0, +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + .boost = 1, +#endif }; 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, 15, { .int_p = &settings.reverb }, "Reverberation", 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.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}, +#endif }; static void applysettings(void) @@ -498,6 +510,7 @@ static void applysettings(void) md_pansep = settings.pansep; md_reverb = settings.reverb; md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; + if ( settings.interp ) { md_mode |= DMODE_INTERP; @@ -510,6 +523,21 @@ static void applysettings(void) { 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 if ( Player_Active() ) { @@ -518,6 +546,21 @@ static void applysettings(void) #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 */ @@ -531,6 +574,8 @@ static int settings_menu(void) ID2P(LANG_INTERPOLATION), ID2P(LANG_SWAP_CHANNELS), ID2P(LANG_MIKMOD_SURROUND), + ID2P(LANG_MIKMOD_HQMIXER), + ID2P(LANG_MIKMOD_SAMPLERATE), #ifdef HAVE_ADJUSTABLE_CPU_FREQ ID2P(LANG_CPU_BOOST) #endif @@ -571,9 +616,22 @@ static int settings_menu(void) break; 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)); applysettings(); break; +#endif case MENU_ATTACHED_USB: return PLUGIN_USB_CONNECTED; @@ -675,13 +733,12 @@ static int playfile(char* filename) } #ifdef HAVE_ADJUSTABLE_CPU_FREQ - if ( settings.boost ) - rb->cpu_boost(true); + rb->cpu_boost(settings.boost); #endif #ifdef USETHREADS rb->queue_init(&thread_q, true); if ((thread_id = rb->create_thread(thread, thread_stack, - sizeof(thread_stack), 0, "render buffering thread" + sizeof(thread_stack), 0, "render buffering thread" IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU))) == 0) { @@ -830,11 +887,11 @@ static int playfile(char* filename) rb->lcd_setfont(FONT_SYSFIXED); screenupdated = false; break; - + case ACTION_WPS_STOP: quit = true; break; - + default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { @@ -850,20 +907,19 @@ static int playfile(char* filename) rb->queue_delete(&thread_q); #endif #ifdef HAVE_ADJUSTABLE_CPU_FREQ - if ( settings.boost ) - rb->cpu_boost(false); + rb->cpu_boost(false); #endif Player_Stop(); Player_Free(module); - + memset(gmbuf, '\0', sizeof(gmbuf)); - + if ( retval == PLUGIN_OK && entries > 1 && !quit ) { retval = change_filename(DIR_NEXT); } - + return retval; } @@ -891,10 +947,9 @@ enum plugin_status plugin_start(const void* parameter) rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); #endif - rb->mixer_set_frequency(SAMPLE_RATE); audio_buffer = rb->plugin_get_audio_buffer((size_t *)&audio_buffer_free); - + rb->strcpy(np_file, parameter); get_mod_list(); if(!entries) { @@ -903,16 +958,29 @@ enum plugin_status plugin_start(const void* parameter) //add_pool(audio_buffer, audio_buffer_free); init_memory_pool(audio_buffer_free, audio_buffer); - + MikMod_RegisterDriver(&drv_nos); MikMod_RegisterAllLoaders(); MikMod_RegisterErrorHandler(mm_errorhandler); - md_mixfreq = SAMPLE_RATE; - configfile_load(MIKMOD_CONFIGFILE, config, ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION); 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(); if (MikMod_Init("")) @@ -934,14 +1002,13 @@ enum plugin_status plugin_start(const void* parameter) if (retval == PLUGIN_OK) { - rb->splash(0, "Saving Settings"); if (rb->memcmp(&settings, &old_settings, sizeof (settings))) { - configfile_save(MIKMOD_CONFIGFILE, config, - ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION); + configfile_save(MIKMOD_CONFIGFILE, config, + ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION); } } - + destroy_memory_pool(audio_buffer); return retval; diff --git a/apps/plugins/mikmod/mikmod.h b/apps/plugins/mikmod/mikmod.h index a1c201f6d2..8256299451 100644 --- a/apps/plugins/mikmod/mikmod.h +++ b/apps/plugins/mikmod/mikmod.h @@ -1,30 +1,28 @@ -/* MikMod sound library - (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS - for complete list. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. +/* MikMod sound library + (c) 1998-2014 Miodrag Vallat and others - see the AUTHORS file + 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: mikmod.h.in,v 1.3 2005/03/30 19:09:21 realtech Exp $ - MikMod sound library include file -==============================================================================*/ + ==============================================================================*/ #ifndef _MIKMOD_H_ #define _MIKMOD_H_ @@ -40,163 +38,221 @@ extern "C" { /* * ========== 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 _DLL -#ifdef DLL_EXPORTS -#define MIKMODAPI __declspec(dllexport) -#else -#define MIKMODAPI __declspec(dllimport) -#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(MIKMOD_BUILD) && defined(DLL_EXPORT) /* building libmikmod as a dll for windows */ +# 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 -#define MIKMODAPI +# define MIKMODAPI #endif /* - * ========== Library version + * ========== Library version */ #define LIBMIKMOD_VERSION_MAJOR 3L -#define LIBMIKMOD_VERSION_MINOR 2L -#define LIBMIKMOD_REVISION 0L +#define LIBMIKMOD_VERSION_MINOR 3L +#define LIBMIKMOD_REVISION 11L #define LIBMIKMOD_VERSION \ - ((LIBMIKMOD_VERSION_MAJOR<<16)| \ - (LIBMIKMOD_VERSION_MINOR<< 8)| \ - (LIBMIKMOD_REVISION)) + ((LIBMIKMOD_VERSION_MAJOR<<16)| \ + (LIBMIKMOD_VERSION_MINOR<< 8)| \ + (LIBMIKMOD_REVISION)) 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 +#endif #include #include #include +#define _MIKMOD_WIN32 +#endif + +#if defined(__DJGPP__) || defined(MSDOS) || defined(__MSDOS__) || defined(__DOS__) +#define _MIKMOD_DOS #endif -#if defined(__OS2__)||defined(__EMX__) +#if defined(__OS2__) || defined(__EMX__) #define INCL_DOSSEMAPHORES #include -#else -typedef char CHAR; +#include +#define _MIKMOD_OS2 +#endif + +#if defined(__MORPHOS__) || defined(__AROS__) || defined(_AMIGA) || defined(__AMIGA__) || defined(__amigaos__) || defined(AMIGAOS) +#include +#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; #endif -typedef char CHAR; +/* 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 +/* 1 byte, signed and unsigned: */ +typedef signed char SBYTE; +#ifndef _MIKMOD_AMIGA +typedef unsigned char UBYTE; +#endif -#if defined(__arch64__) || defined(__alpha) || defined(__x86_64) || defined(__powerpc64__) -/* 64 bit architectures */ +/* 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 -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 int SLONG; /* 4 bytes, signed */ -typedef unsigned int ULONG; /* 4 bytes, unsigned */ -//typedef int BOOL; /* 0=false, <>0 true */ +/* 4 bytes, signed and unsigned: */ +#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 -#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 */ +#else /* 32 bit architectures: */ +typedef signed long int SLONG; +#if !(defined(_MIKMOD_OS2) || defined(_MIKMOD_WIN32) || defined(_MIKMOD_AMIGA)) +typedef unsigned long int ULONG; #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 */ enum { - MMERR_OPENING_FILE = 1, - MMERR_OUT_OF_MEMORY, - MMERR_DYNAMIC_LINKING, - - MMERR_SAMPLE_TOO_BIG, - MMERR_OUT_OF_HANDLES, - MMERR_UNKNOWN_WAVE_TYPE, - - MMERR_LOADING_PATTERN, - MMERR_LOADING_TRACK, - MMERR_LOADING_HEADER, - MMERR_LOADING_SAMPLEINFO, - MMERR_NOT_A_MODULE, - MMERR_NOT_A_STREAM, - MMERR_MED_SYNTHSAMPLES, - MMERR_ITPACK_INVALID_DATA, - - MMERR_DETECTING_DEVICE, - MMERR_INVALID_DEVICE, - MMERR_INITIALIZING_MIXER, - MMERR_OPENING_AUDIO, - MMERR_8BIT_ONLY, - MMERR_16BIT_ONLY, - MMERR_STEREO_ONLY, - MMERR_ULAW, - MMERR_NON_BLOCK, - - MMERR_AF_AUDIO_PORT, - - MMERR_AIX_CONFIG_INIT, - MMERR_AIX_CONFIG_CONTROL, - MMERR_AIX_CONFIG_START, - - MMERR_GUS_SETTINGS, - MMERR_GUS_RESET, - MMERR_GUS_TIMER, - - MMERR_HP_SETSAMPLESIZE, - MMERR_HP_SETSPEED, - MMERR_HP_CHANNELS, - MMERR_HP_AUDIO_OUTPUT, - MMERR_HP_AUDIO_DESC, - MMERR_HP_BUFFERSIZE, - - MMERR_OSS_SETFRAGMENT, - MMERR_OSS_SETSAMPLESIZE, - MMERR_OSS_SETSTEREO, - MMERR_OSS_SETSPEED, - - MMERR_SGI_SPEED, - MMERR_SGI_16BIT, - MMERR_SGI_8BIT, - MMERR_SGI_STEREO, - MMERR_SGI_MONO, - - MMERR_SUN_INIT, - - MMERR_OS2_MIXSETUP, - MMERR_OS2_SEMAPHORE, - MMERR_OS2_TIMER, - MMERR_OS2_THREAD, - - MMERR_DS_PRIORITY, - MMERR_DS_BUFFER, - MMERR_DS_FORMAT, - MMERR_DS_NOTIFY, - MMERR_DS_EVENT, - MMERR_DS_THREAD, - MMERR_DS_UPDATE, - - MMERR_WINMM_HANDLE, - MMERR_WINMM_ALLOCATED, - MMERR_WINMM_DEVICEID, - MMERR_WINMM_FORMAT, - MMERR_WINMM_UNKNOWN, - - MMERR_MAC_SPEED, - MMERR_MAC_START, + MMERR_OPENING_FILE = 1, + MMERR_OUT_OF_MEMORY, + MMERR_DYNAMIC_LINKING, + + MMERR_SAMPLE_TOO_BIG, + MMERR_OUT_OF_HANDLES, + MMERR_UNKNOWN_WAVE_TYPE, + + MMERR_LOADING_PATTERN, + MMERR_LOADING_TRACK, + MMERR_LOADING_HEADER, + MMERR_LOADING_SAMPLEINFO, + MMERR_NOT_A_MODULE, + MMERR_NOT_A_STREAM, + MMERR_MED_SYNTHSAMPLES, + MMERR_ITPACK_INVALID_DATA, + + MMERR_DETECTING_DEVICE, + MMERR_INVALID_DEVICE, + MMERR_INITIALIZING_MIXER, + MMERR_OPENING_AUDIO, + MMERR_8BIT_ONLY, + MMERR_16BIT_ONLY, + MMERR_STEREO_ONLY, + MMERR_ULAW, + MMERR_NON_BLOCK, + + MMERR_AF_AUDIO_PORT, + + MMERR_AIX_CONFIG_INIT, + MMERR_AIX_CONFIG_CONTROL, + MMERR_AIX_CONFIG_START, + + MMERR_GUS_SETTINGS, + MMERR_GUS_RESET, + MMERR_GUS_TIMER, + + MMERR_HP_SETSAMPLESIZE, + MMERR_HP_SETSPEED, + MMERR_HP_CHANNELS, + MMERR_HP_AUDIO_OUTPUT, + MMERR_HP_AUDIO_DESC, + MMERR_HP_BUFFERSIZE, + + MMERR_OSS_SETFRAGMENT, + MMERR_OSS_SETSAMPLESIZE, + MMERR_OSS_SETSTEREO, + MMERR_OSS_SETSPEED, + + MMERR_SGI_SPEED, + MMERR_SGI_16BIT, + MMERR_SGI_8BIT, + MMERR_SGI_STEREO, + MMERR_SGI_MONO, + + MMERR_SUN_INIT, + + MMERR_OS2_MIXSETUP, + MMERR_OS2_SEMAPHORE, + MMERR_OS2_TIMER, + MMERR_OS2_THREAD, + + MMERR_DS_PRIORITY, + MMERR_DS_BUFFER, + MMERR_DS_FORMAT, + MMERR_DS_NOTIFY, + MMERR_DS_EVENT, + MMERR_DS_THREAD, + MMERR_DS_UPDATE, + + MMERR_WINMM_HANDLE, + MMERR_WINMM_ALLOCATED, + MMERR_WINMM_DEVICEID, + MMERR_WINMM_FORMAT, + MMERR_WINMM_UNKNOWN, + + MMERR_MAC_SPEED, + MMERR_MAC_START, MMERR_OSX_UNKNOWN_DEVICE, MMERR_OSX_BAD_PROPERTY, @@ -205,16 +261,43 @@ enum { MMERR_OSX_BUFFER_ALLOC, MMERR_OSX_ADD_IO_PROC, MMERR_OSX_DEVICE_START, - MMERR_OSX_PTHREAD, - - MMERR_DOSWSS_STARTDMA, - MMERR_DOSSB_STARTDMA, - - MMERR_MAX + MMERR_OSX_PTHREAD, + + MMERR_DOSWSS_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 }; /* - * ========== Error handling + * ========== Error handling */ typedef void (MikMod_handler)(void); @@ -222,12 +305,12 @@ typedef MikMod_handler *MikMod_handler_t; MIKMODAPI extern int MikMod_errno; 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); /* - * ========== Library initialization and core functions + * ========== Library initialization and core functions */ struct MDRIVER; @@ -236,15 +319,15 @@ MIKMODAPI extern void MikMod_RegisterAllDrivers(void); MIKMODAPI extern CHAR* MikMod_InfoDriver(void); 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 int MikMod_Init(CHAR*); +MIKMODAPI extern int MikMod_Init(const CHAR*); MIKMODAPI extern void MikMod_Exit(void); -MIKMODAPI extern int MikMod_Reset(CHAR*); -MIKMODAPI extern int MikMod_SetNumVoices(int,int); +MIKMODAPI extern int MikMod_Reset(const CHAR*); +MIKMODAPI extern int MikMod_SetNumVoices(int,int); MIKMODAPI extern int MikMod_Active(void); -MIKMODAPI extern int MikMod_EnableOutput(void); +MIKMODAPI extern int MikMod_EnableOutput(void); MIKMODAPI extern void MikMod_DisableOutput(void); MIKMODAPI extern void MikMod_Update(void); @@ -253,33 +336,34 @@ MIKMODAPI extern void MikMod_Lock(void); MIKMODAPI extern void MikMod_Unlock(void); 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_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 */ typedef struct MREADER { - int (*Seek)(struct MREADER*,long,int); - long (*Tell)(struct MREADER*); - int (*Read)(struct MREADER*,void*,size_t); - int (*Get)(struct MREADER*); - int (*Eof)(struct MREADER*); - long iobase; - long prev_iobase; + int (*Seek)(struct MREADER*,long,int); + long (*Tell)(struct MREADER*); + int (*Read)(struct MREADER*,void*,size_t); + int (*Get)(struct MREADER*); + int (*Eof)(struct MREADER*); + long iobase; + long prev_iobase; } MREADER; typedef struct MWRITER { - int (*Seek)(struct MWRITER*,long,int); - long (*Tell)(struct MWRITER*); - int (*Write)(struct MWRITER*,void*,size_t); - int (*Put)(struct MWRITER*,int); + int (*Seek)(struct MWRITER*, long, int); + long (*Tell)(struct MWRITER*); + int (*Write)(struct MWRITER*, const void*, size_t); + int (*Put)(struct MWRITER*, int); } MWRITER; /* - * ========== Samples + * ========== Samples */ /* Sample playback should not be interrupted */ @@ -291,9 +375,9 @@ typedef struct MWRITER { #define SF_SIGNED 0x0004 #define SF_BIG_ENDIAN 0x0008 #define SF_DELTA 0x0010 -#define SF_ITPACKED 0x0020 +#define SF_ITPACKED 0x0020 -#define SF_FORMATMASK 0x003F +#define SF_FORMATMASK 0x003F /* General Playback flags */ @@ -302,61 +386,61 @@ typedef struct MWRITER { #define SF_REVERSE 0x0400 #define SF_SUSTAIN 0x0800 -#define SF_PLAYBACKMASK 0x0C00 +#define SF_PLAYBACKMASK 0x0C00 /* Module-only Playback Flags */ -#define SF_OWNPAN 0x1000 +#define SF_OWNPAN 0x1000 #define SF_UST_LOOP 0x2000 -#define SF_EXTRAPLAYBACKMASK 0x3000 +#define SF_EXTRAPLAYBACKMASK 0x3000 /* Panning constants */ -#define PAN_LEFT 0 -#define PAN_HALFLEFT 64 -#define PAN_CENTER 128 -#define PAN_HALFRIGHT 192 -#define PAN_RIGHT 255 -#define PAN_SURROUND 512 /* panning value for Dolby Surround */ +#define PAN_LEFT 0 +#define PAN_HALFLEFT 64 +#define PAN_CENTER 128 +#define PAN_HALFRIGHT 192 +#define PAN_RIGHT 255 +#define PAN_SURROUND 512 /* panning value for Dolby Surround */ typedef struct SAMPLE { - SWORD panning; /* panning (0-255 or PAN_SURROUND) */ - ULONG speed; /* Base playing speed/frequency of note */ - UBYTE volume; /* volume 0-64 */ - UWORD inflags; /* sample format on disk */ - UWORD flags; /* sample format in memory */ - ULONG length; /* length of sample (in samples!) */ - ULONG loopstart; /* repeat position (relative to start, in samples) */ - ULONG loopend; /* repeat end */ - ULONG susbegin; /* sustain loop begin (in samples) \ Not Supported */ - ULONG susend; /* sustain loop end / Yet! */ - - /* Variables used by the module player only! (ignored for sound effects) */ - UBYTE globvol; /* global volume */ - UBYTE vibflags; /* autovibrato flag stuffs */ - UBYTE vibtype; /* Vibratos moved from INSTRUMENT to SAMPLE */ - UBYTE vibsweep; - UBYTE vibdepth; - UBYTE vibrate; - CHAR* samplename; /* name of the sample */ - - /* Values used internally only */ - UWORD avibpos; /* autovibrato pos [player use] */ - UBYTE divfactor; /* for sample scaling, maintains proper period slides */ - ULONG seekpos; /* seek position in file */ - SWORD handle; /* sample handle used by individual drivers */ - void (*onfree)(void *ctx); /* called from Sample_Free if not NULL */ - void *ctx; /* context passed to previous function*/ + SWORD panning; /* panning (0-255 or PAN_SURROUND) */ + ULONG speed; /* Base playing speed/frequency of note */ + UBYTE volume; /* volume 0-64 */ + UWORD inflags; /* sample format on disk */ + UWORD flags; /* sample format in memory */ + ULONG length; /* length of sample (in samples!) */ + ULONG loopstart; /* repeat position (relative to start, in samples) */ + ULONG loopend; /* repeat end */ + ULONG susbegin; /* sustain loop begin (in samples) \ Not Supported */ + ULONG susend; /* sustain loop end / Yet! */ + + /* Variables used by the module player only! (ignored for sound effects) */ + UBYTE globvol; /* global volume */ + UBYTE vibflags; /* autovibrato flag stuffs */ + UBYTE vibtype; /* Vibratos moved from INSTRUMENT to SAMPLE */ + UBYTE vibsweep; + UBYTE vibdepth; + UBYTE vibrate; + CHAR* samplename; /* name of the sample */ + + /* Values used internally only */ + UWORD avibpos; /* autovibrato pos [player use] */ + UBYTE divfactor; /* for sample scaling, maintains proper period slides */ + ULONG seekpos; /* seek position in file */ + SWORD handle; /* sample handle used by individual drivers */ + void (*onfree)(void *ctx); /* called from Sample_Free if not NULL */ + void *ctx; /* context passed to previous function*/ } SAMPLE; /* 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_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_Load(CHAR*); +MIKMODAPI extern SAMPLE *Sample_Load(const CHAR*); MIKMODAPI extern SAMPLE *Sample_LoadFP(int); MIKMODAPI extern SAMPLE *Sample_LoadMem(const char *buf, int len); MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*); @@ -376,12 +460,12 @@ MIKMODAPI extern SLONG Voice_GetPosition(SBYTE); MIKMODAPI extern ULONG Voice_RealVolume(SBYTE); /* - * ========== Internal module representation (UniMod) + * ========== Internal module representation (UniMod) */ /* - Instrument definition - for information only, the only field which may be - of use in user programs is the name field + Instrument definition - for information only, the only field which may be + of use in user programs is the name field */ /* Instrument note count */ @@ -389,8 +473,8 @@ MIKMODAPI extern ULONG Voice_RealVolume(SBYTE); /* Envelope point */ typedef struct ENVPT { - SWORD pos; - SWORD val; + SWORD pos; + SWORD val; } ENVPT; /* Envelope point count */ @@ -398,154 +482,156 @@ typedef struct ENVPT { /* Instrument structure */ typedef struct INSTRUMENT { - CHAR* insname; - - UBYTE flags; - UWORD samplenumber[INSTNOTES]; - UBYTE samplenote[INSTNOTES]; - - UBYTE nnatype; - UBYTE dca; /* duplicate check action */ - UBYTE dct; /* duplicate check type */ - UBYTE globvol; - UWORD volfade; - SWORD panning; /* instrument-based panning var */ - - UBYTE pitpansep; /* pitch pan separation (0 to 255) */ - UBYTE pitpancenter; /* pitch pan center (0 to 119) */ - UBYTE rvolvar; /* random volume varations (0 - 100%) */ - UBYTE rpanvar; /* random panning varations (0 - 100%) */ - - /* volume envelope */ - UBYTE volflg; /* bit 0: on 1: sustain 2: loop */ - UBYTE volpts; - UBYTE volsusbeg; - UBYTE volsusend; - UBYTE volbeg; - UBYTE volend; - ENVPT volenv[ENVPOINTS]; - /* panning envelope */ - UBYTE panflg; /* bit 0: on 1: sustain 2: loop */ - UBYTE panpts; - UBYTE pansusbeg; - UBYTE pansusend; - UBYTE panbeg; - UBYTE panend; - ENVPT panenv[ENVPOINTS]; - /* pitch envelope */ - UBYTE pitflg; /* bit 0: on 1: sustain 2: loop */ - UBYTE pitpts; - UBYTE pitsusbeg; - UBYTE pitsusend; - UBYTE pitbeg; - UBYTE pitend; - ENVPT pitenv[ENVPOINTS]; + CHAR* insname; + + UBYTE flags; + UWORD samplenumber[INSTNOTES]; + UBYTE samplenote[INSTNOTES]; + + UBYTE nnatype; + UBYTE dca; /* duplicate check action */ + UBYTE dct; /* duplicate check type */ + UBYTE globvol; + UWORD volfade; + SWORD panning; /* instrument-based panning var */ + + UBYTE pitpansep; /* pitch pan separation (0 to 255) */ + UBYTE pitpancenter; /* pitch pan center (0 to 119) */ + UBYTE rvolvar; /* random volume varations (0 - 100%) */ + UBYTE rpanvar; /* random panning varations (0 - 100%) */ + + /* volume envelope */ + UBYTE volflg; /* bit 0: on 1: sustain 2: loop */ + UBYTE volpts; + UBYTE volsusbeg; + UBYTE volsusend; + UBYTE volbeg; + UBYTE volend; + ENVPT volenv[ENVPOINTS]; + /* panning envelope */ + UBYTE panflg; /* bit 0: on 1: sustain 2: loop */ + UBYTE panpts; + UBYTE pansusbeg; + UBYTE pansusend; + UBYTE panbeg; + UBYTE panend; + ENVPT panenv[ENVPOINTS]; + /* pitch envelope */ + UBYTE pitflg; /* bit 0: on 1: sustain 2: loop */ + UBYTE pitpts; + UBYTE pitsusbeg; + UBYTE pitsusend; + UBYTE pitbeg; + UBYTE pitend; + ENVPT pitenv[ENVPOINTS]; } INSTRUMENT; struct MP_CONTROL; struct MP_VOICE; /* - Module definition + Module definition */ /* maximum master channels supported */ -#define UF_MAXCHAN 64 +#define UF_MAXCHAN 64 /* Module flags */ -#define UF_XMPERIODS 0x0001 /* XM periods / finetuning */ -#define UF_LINEAR 0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */ -#define UF_INST 0x0004 /* Instruments are used */ -#define UF_NNA 0x0008 /* IT: NNA used, set numvoices rather - than numchn */ -#define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */ -#define UF_BGSLIDES 0x0020 /* continue volume slides in the background */ -#define UF_HIGHBPM 0x0040 /* MED: can use >255 bpm */ -#define UF_NOWRAP 0x0080 /* XM-type (i.e. illogical) pattern break - semantics */ -#define UF_ARPMEM 0x0100 /* IT: need arpeggio memory */ -#define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */ -#define UF_PANNING 0x0400 /* module uses panning effects or have - non-tracker default initial panning */ +#define UF_XMPERIODS 0x0001 /* XM periods / finetuning */ +#define UF_LINEAR 0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */ +#define UF_INST 0x0004 /* Instruments are used */ +#define UF_NNA 0x0008 /* IT: NNA used, set numvoices rather + than numchn */ +#define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */ +#define UF_BGSLIDES 0x0020 /* continue volume slides in the background */ +#define UF_HIGHBPM 0x0040 /* MED: can use >255 bpm */ +#define UF_NOWRAP 0x0080 /* XM-type (i.e. illogical) pattern break + semantics */ +#define UF_ARPMEM 0x0100 /* IT: need arpeggio memory */ +#define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */ +#define UF_PANNING 0x0400 /* module uses panning effects or have + non-tracker default initial panning */ typedef struct MODULE { - /* general module information */ - CHAR* songname; /* name of the song */ - CHAR* modtype; /* string type of module loaded */ - CHAR* comment; /* module comments */ - - UWORD flags; /* See module flags above */ - UBYTE numchn; /* number of module channels */ - UBYTE numvoices; /* max # voices used for full NNA playback */ - UWORD numpos; /* number of positions in this song */ - UWORD numpat; /* number of patterns in this song */ - UWORD numins; /* number of instruments */ - UWORD numsmp; /* number of samples */ -struct INSTRUMENT* instruments; /* all instruments */ -struct SAMPLE* samples; /* all samples */ - UBYTE realchn; /* real number of channels used */ - UBYTE totalchn; /* total number of channels used (incl NNAs) */ - - /* playback settings */ - UWORD reppos; /* restart position */ - UBYTE initspeed; /* initial song speed */ - UWORD inittempo; /* initial song tempo */ - UBYTE initvolume; /* initial global volume (0 - 128) */ - UWORD panning[UF_MAXCHAN]; /* panning positions */ - UBYTE chanvol[UF_MAXCHAN]; /* channel positions */ - UWORD bpm; /* current beats-per-minute speed */ - UWORD sngspd; /* current song speed */ - SWORD volume; /* song volume (0-128) (or user volume) */ - - int extspd; /* extended speed flag (default enabled) */ - int panflag; /* panning flag (default enabled) */ - int wrap; /* wrap module ? (default disabled) */ - int loop; /* allow module to loop ? (default enabled) */ - int fadeout; /* volume fade out during last pattern */ - - UWORD patpos; /* current row number */ - SWORD sngpos; /* current song position */ - ULONG sngtime; /* current song time in 2^-10 seconds */ - - SWORD relspd; /* relative speed factor */ - - /* internal module representation */ - UWORD numtrk; /* number of tracks */ - UBYTE** tracks; /* array of numtrk pointers to tracks */ - UWORD* patterns; /* array of Patterns */ - UWORD* pattrows; /* array of number of rows for each pattern */ - UWORD* positions; /* all positions */ - - int forbid; /* if true, no player update! */ - UWORD numrow; /* number of rows on current pattern */ - UWORD vbtick; /* tick counter (counts from 0 to sngspd) */ - UWORD sngremainder;/* used for song time computation */ - -struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */ -struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */ - - UBYTE globalslide; /* global volume slide rate */ - UBYTE pat_repcrazy;/* module has just looped to position -1 */ - UWORD patbrk; /* position where to start a new pattern */ - UBYTE patdly; /* patterndelay counter (command memory) */ - UBYTE patdly2; /* patterndelay counter (real one) */ - SWORD posjmp; /* flag to indicate a jump is needed... */ - UWORD bpmlimit; /* threshold to detect bpm or speed values */ + /* general module information */ + CHAR* songname; /* name of the song */ + CHAR* modtype; /* string type of module loaded */ + CHAR* comment; /* module comments */ + + UWORD flags; /* See module flags above */ + UBYTE numchn; /* number of module channels */ + UBYTE numvoices; /* max # voices used for full NNA playback */ + UWORD numpos; /* number of positions in this song */ + UWORD numpat; /* number of patterns in this song */ + UWORD numins; /* number of instruments */ + UWORD numsmp; /* number of samples */ + + struct INSTRUMENT* instruments; /* all instruments */ + struct SAMPLE* samples; /* all samples */ + + UBYTE realchn; /* real number of channels used */ + UBYTE totalchn; /* total number of channels used (incl NNAs) */ + + /* playback settings */ + UWORD reppos; /* restart position */ + UBYTE initspeed; /* initial song speed */ + UWORD inittempo; /* initial song tempo */ + UBYTE initvolume; /* initial global volume (0 - 128) */ + UWORD panning[UF_MAXCHAN]; /* panning positions */ + UBYTE chanvol[UF_MAXCHAN]; /* channel positions */ + UWORD bpm; /* current beats-per-minute speed */ + UWORD sngspd; /* current song speed */ + SWORD volume; /* song volume (0-128) (or user volume) */ + + int extspd; /* extended speed flag (default enabled) */ + int panflag; /* panning flag (default enabled) */ + int wrap; /* wrap module ? (default disabled) */ + int loop; /* allow module to loop ? (default enabled) */ + int fadeout; /* volume fade out during last pattern */ + + UWORD patpos; /* current row number */ + SWORD sngpos; /* current song position */ + ULONG sngtime; /* current song time in 2^-10 seconds */ + + SWORD relspd; /* relative speed factor */ + + /* internal module representation */ + UWORD numtrk; /* number of tracks */ + UBYTE** tracks; /* array of numtrk pointers to tracks */ + UWORD* patterns; /* array of Patterns */ + UWORD* pattrows; /* array of number of rows for each pattern */ + UWORD* positions; /* all positions */ + + int forbid; /* if true, no player update! */ + UWORD numrow; /* number of rows on current pattern */ + UWORD vbtick; /* tick counter (counts from 0 to sngspd) */ + UWORD sngremainder;/* used for song time computation */ + + struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */ + struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */ + + UBYTE globalslide; /* global volume slide rate */ + UBYTE pat_repcrazy;/* module has just looped to position -1 */ + UWORD patbrk; /* position where to start a new pattern */ + UBYTE patdly; /* patterndelay counter (command memory) */ + UBYTE patdly2; /* patterndelay counter (real one) */ + SWORD posjmp; /* flag to indicate a jump is needed... */ + UWORD bpmlimit; /* threshold to detect bpm or speed values */ } MODULE; /* This structure is used to query current playing voices status */ typedef struct VOICEINFO { - INSTRUMENT* i; /* Current channel instrument */ - SAMPLE* s; /* Current channel sample */ - SWORD panning; /* panning position */ - SBYTE volume; /* channel's "global" volume (0..64) */ - UWORD period; /* period to play the sample at */ - UBYTE kick; /* if true = sample has been restarted */ + INSTRUMENT* i; /* Current channel instrument */ + SAMPLE* s; /* Current channel sample */ + SWORD panning; /* panning position */ + SBYTE volume; /* channel's "global" volume (0..64) */ + UWORD period; /* period to play the sample at */ + UBYTE kick; /* if true = sample has been restarted */ } VOICEINFO; /* - * ========== Module loaders + * ========== Module loaders */ struct MLOADER; @@ -572,18 +658,19 @@ 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_s3m; /* ScreamTracker 3 (by Future Crew) */ 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_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_LoadMem(const char *buffer,int len,int maxchan,int curious); 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_LoadTitleMem(const char *buffer,int len); MIKMODAPI extern CHAR* Player_LoadTitleGeneric(MREADER*); @@ -607,9 +694,9 @@ MIKMODAPI extern void Player_Mute(SLONG,...); MIKMODAPI extern void Player_ToggleMute(SLONG,...); MIKMODAPI extern int Player_GetChannelVoice(UBYTE); MIKMODAPI extern UWORD Player_GetChannelPeriod(UBYTE); -MIKMODAPI extern int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo); +MIKMODAPI extern int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo); MIKMODAPI extern int Player_GetRow(void); -MIKMODAPI extern int Player_GetOrder(void); +MIKMODAPI extern int Player_GetOrder(void); typedef void (*MikMod_player_t)(void); typedef void (*MikMod_callback_t)(unsigned char *data, size_t len); @@ -620,17 +707,17 @@ MIKMODAPI extern MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t); #define MUTE_INCLUSIVE 32001 /* - * ========== Drivers + * ========== Drivers */ enum { - MD_MUSIC = 0, - MD_SNDFX + MD_MUSIC = 0, + MD_SNDFX }; enum { - MD_HARDWARE = 0, - MD_SOFTWARE + MD_HARDWARE = 0, + MD_SOFTWARE }; /* Mixing flags */ @@ -646,46 +733,48 @@ enum { #define DMODE_SURROUND 0x0100 /* enable surround sound */ #define DMODE_INTERP 0x0200 /* enable interpolation */ #define DMODE_REVERSE 0x0400 /* reverse stereo */ -#define DMODE_SIMDMIXER 0x0800 /* enable SIMD mixing */ +#define DMODE_SIMDMIXER 0x0800 /* enable SIMD mixing */ #define DMODE_NOISEREDUCTION 0x1000 /* Low pass filtering */ + struct SAMPLOAD; + typedef struct MDRIVER { -struct MDRIVER* next; - CHAR* Name; - CHAR* Version; - - UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */ - UBYTE SoftVoiceLimit; /* Limit of software mixer voices */ - - CHAR *Alias; - CHAR *CmdLineHelp; - - void (*CommandLine) (CHAR*); - int (*IsPresent) (void); - SWORD (*SampleLoad) (struct SAMPLOAD*,int); - void (*SampleUnload) (SWORD); - ULONG (*FreeSampleSpace) (int); - ULONG (*RealSampleLength) (int,struct SAMPLE*); - int (*Init) (void); - void (*Exit) (void); - int (*Reset) (void); - int (*SetNumVoices) (void); - int (*PlayStart) (void); - void (*PlayStop) (void); - void (*Update) (void); - void (*Pause) (void); - void (*VoiceSetVolume) (UBYTE,UWORD); - UWORD (*VoiceGetVolume) (UBYTE); - void (*VoiceSetFrequency)(UBYTE,ULONG); - ULONG (*VoiceGetFrequency)(UBYTE); - void (*VoiceSetPanning) (UBYTE,ULONG); - ULONG (*VoiceGetPanning) (UBYTE); - void (*VoicePlay) (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); - void (*VoiceStop) (UBYTE); - int (*VoiceStopped) (UBYTE); - SLONG (*VoiceGetPosition) (UBYTE); - ULONG (*VoiceRealVolume) (UBYTE); + struct MDRIVER* next; + const CHAR* Name; + const CHAR* Version; + + UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */ + UBYTE SoftVoiceLimit; /* Limit of software mixer voices */ + + const CHAR* Alias; + const CHAR* CmdLineHelp; + + void (*CommandLine) (const CHAR*); + int (*IsPresent) (void); + SWORD (*SampleLoad) (struct SAMPLOAD*,int); + void (*SampleUnload) (SWORD); + ULONG (*FreeSampleSpace) (int); + ULONG (*RealSampleLength) (int,struct SAMPLE*); + int (*Init) (void); + void (*Exit) (void); + int (*Reset) (void); + int (*SetNumVoices) (void); + int (*PlayStart) (void); + void (*PlayStop) (void); + void (*Update) (void); + void (*Pause) (void); + void (*VoiceSetVolume) (UBYTE,UWORD); + UWORD (*VoiceGetVolume) (UBYTE); + void (*VoiceSetFrequency)(UBYTE,ULONG); + ULONG (*VoiceGetFrequency)(UBYTE); + void (*VoiceSetPanning) (UBYTE,ULONG); + ULONG (*VoiceGetPanning) (UBYTE); + void (*VoicePlay) (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); + void (*VoiceStop) (UBYTE); + int (*VoiceStopped) (UBYTE); + SLONG (*VoiceGetPosition) (UBYTE); + ULONG (*VoiceRealVolume) (UBYTE); } MDRIVER; /* These variables can be changed at ANY time and results will be immediate */ @@ -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 changed). */ 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 */ /* The following variable should not be changed! */ @@ -709,7 +798,6 @@ MIKMODAPI extern MDRIVER* md_driver; /* Current driver in use. */ /* Known drivers list */ MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */ -#if 0 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_stdout; /* output to stdout */ @@ -717,42 +805,53 @@ 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_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_ahi; /* Amiga AHI */ 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_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_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_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_sndio; /* OpenBSD sndio */ 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_os2; /* OS/2 MMPM/2 */ 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_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_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_sb; /* DOS SB driver */ -#endif +MIKMODAPI extern struct MDRIVER drv_sb; /* DOS S/B driver */ + +MIKMODAPI extern struct MDRIVER drv_osles; /* OpenSL ES driver for android */ + /*========== Virtual channel mixer interface (for user-supplied drivers only) */ -MIKMODAPI extern int VC_Init(void); +MIKMODAPI extern int VC_Init(void); MIKMODAPI extern void VC_Exit(void); MIKMODAPI extern void VC_SetCallback(MikMod_callback_t callback); -MIKMODAPI extern int VC_SetNumVoices(void); +MIKMODAPI extern int VC_SetNumVoices(void); MIKMODAPI extern ULONG VC_SampleSpace(int); MIKMODAPI extern ULONG VC_SampleLength(int,SAMPLE*); -MIKMODAPI extern int VC_PlayStart(void); +MIKMODAPI extern int VC_PlayStart(void); MIKMODAPI extern void VC_PlayStop(void); MIKMODAPI extern SWORD VC_SampleLoad(struct SAMPLOAD*,int); diff --git a/apps/plugins/mikmod/mikmod_internals.h b/apps/plugins/mikmod/mikmod_internals.h index 78d7b52045..e6ba1875c0 100644 --- a/apps/plugins/mikmod/mikmod_internals.h +++ b/apps/plugins/mikmod/mikmod_internals.h @@ -20,11 +20,9 @@ /*============================================================================== - $Id: mikmod_internals.h,v 1.7 2010/01/12 03:30:31 realtech Exp $ - MikMod sound library internal definitions -==============================================================================*/ + ==============================================================================*/ #ifndef _MIKMOD_INTERNALS_H #define _MIKMOD_INTERNALS_H @@ -34,32 +32,52 @@ extern "C" { #endif #include -#if 0 -#if defined(__OS2__)||defined(__EMX__)||defined(WIN32) -#define strcasecmp(s,t) stricmp(s,t) -#endif + +#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(HAVE_CONFIG_H) +#define inline __inline #endif #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 */ /* SLONGLONG: 64bit, signed */ -#if defined (__arch64__) || defined(__alpha) || defined (__x64_64) || defined (_LP64) || defined (__powerpc64__) -typedef long SLONGLONG; +#if !defined(_WIN32) && \ + (defined(_LP64) || defined(__LP64__) || defined(__arch64__) || defined(__alpha) || defined(__x64_64) || defined(__powerpc64__)) +typedef long SLONGLONG; +#define NATIVE_64BIT_INT +#elif defined(_WIN64) /* win64 is LLP64, not LP64 */ #define NATIVE_64BIT_INT -#if 0 +typedef long long SLONGLONG; #elif defined(__WATCOMC__) -typedef __int64 SLONGLONG; -#elif defined(WIN32) && !defined(__MWERKS__) -typedef LONGLONG SLONGLONG; -#elif macintosh && !TYPE_LONGLONG +typedef __int64 SLONGLONG; +#elif defined(_WIN32) && !defined(__MWERKS__) +typedef LONGLONG SLONGLONG; +#elif defined(macintosh) && !TYPE_LONGLONG #include -typedef SInt64 SLONGLONG; +typedef SInt64 SLONGLONG; +#else +typedef long long SLONGLONG; #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 -typedef long long SLONGLONG; +/* 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 */ @@ -72,33 +90,36 @@ extern MikMod_handler_t _mm_errorhandler; #ifdef HAVE_PTHREAD #include #define DECLARE_MUTEX(name) \ - extern pthread_mutex_t _mm_mutex_##name -#define MUTEX_LOCK(name) \ - pthread_mutex_lock(&_mm_mutex_##name) -#define MUTEX_UNLOCK(name) \ - pthread_mutex_unlock(&_mm_mutex_##name) + extern pthread_mutex_t _mm_mutex_##name +#define MUTEX_LOCK(name) \ + pthread_mutex_lock(&_mm_mutex_##name) +#define MUTEX_UNLOCK(name) \ + pthread_mutex_unlock(&_mm_mutex_##name) + #elif defined(__OS2__)||defined(__EMX__) -#define DECLARE_MUTEX(name) \ - extern HMTX _mm_mutex_##name -#define MUTEX_LOCK(name) \ - if(_mm_mutex_##name) \ - DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT) -#define MUTEX_UNLOCK(name) \ - if(_mm_mutex_##name) \ - DosReleaseMutexSem(_mm_mutex_##name) -#elif defined(WIN32) +#define DECLARE_MUTEX(name) \ + extern HMTX _mm_mutex_##name +#define MUTEX_LOCK(name) \ + if(_mm_mutex_##name)\ + DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT) +#define MUTEX_UNLOCK(name) \ + if(_mm_mutex_##name)\ + DosReleaseMutexSem(_mm_mutex_##name) + +#elif defined(_WIN32) #include -#define DECLARE_MUTEX(name) \ - extern HANDLE _mm_mutex_##name -#define MUTEX_LOCK(name) \ - if(_mm_mutex_##name) \ - WaitForSingleObject(_mm_mutex_##name,INFINITE) -#define MUTEX_UNLOCK(name) \ - if(_mm_mutex_##name) \ - ReleaseMutex(_mm_mutex_##name) +#define DECLARE_MUTEX(name) \ + extern HANDLE _mm_mutex_##name +#define MUTEX_LOCK(name) \ + if(_mm_mutex_##name)\ + WaitForSingleObject(_mm_mutex_##name,INFINITE) +#define MUTEX_UNLOCK(name) \ + if(_mm_mutex_##name)\ + ReleaseMutex(_mm_mutex_##name) + #else -#define DECLARE_MUTEX(name) \ - extern void *_mm_mutex_##name +#define DECLARE_MUTEX(name) \ + extern void *_mm_mutex_##name #define MUTEX_LOCK(name) #define MUTEX_UNLOCK(name) #endif @@ -106,9 +127,13 @@ extern MikMod_handler_t _mm_errorhandler; DECLARE_MUTEX(lists); DECLARE_MUTEX(vars); +/*========== Replacement funcs */ + +//extern int strcasecmp (const char *__s1, const char *__s2); + /*========== 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 MREADER* _mm_new_file_reader(int fp); @@ -117,33 +142,32 @@ extern void _mm_delete_file_reader(MREADER*); extern MWRITER* _mm_new_file_writer(int fp); 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_UBYTE(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_read_SBYTE(x) (SBYTE)x->Get(x) -#define _mm_read_UBYTE(x) (UBYTE)x->Get(x) +#define _mm_read_SBYTE(x) (SBYTE)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_UBYTES(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,(const 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_fseek(x,y,z) x->Seek(x,y,z) -#define _mm_ftell(x) x->Tell(x) -#define _mm_rewind(x) _mm_fseek(x,0,SEEK_SET) +#define _mm_fseek(x,y,z) x->Seek(x,y,z) +#define _mm_ftell(x) x->Tell(x) +#define _mm_rewind(x) _mm_fseek(x,0,SEEK_SET) -#define _mm_eof(x) x->Eof(x) +#define _mm_eof(x) x->Eof(x) extern void _mm_iobase_setcur(MREADER*); extern void _mm_iobase_revert(MREADER*); -extern int _mm_fopen(CHAR*,CHAR*); -extern int _mm_fclose(int); -#if !defined(ROCKBOX) -extern void _mm_write_string(CHAR*,MWRITER*); -#endif -extern int _mm_read_string (CHAR*,int,MREADER*); +extern int _mm_fopen(const CHAR *, const CHAR *); +extern int _mm_fclose(int); +extern void _mm_write_string(const CHAR*,MWRITER*); +extern int _mm_read_string (CHAR*,int,MREADER*); extern SWORD _mm_read_M_SWORD(MREADER*); extern SWORD _mm_read_I_SWORD(MREADER*); @@ -187,19 +211,21 @@ extern void _mm_write_I_ULONGS(ULONG*,int,MWRITER*); /*========== 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 SL_RegisterSample. Generally, this only need be used or changed by the loaders and drivers of mikmod. */ typedef struct SAMPLOAD { - struct SAMPLOAD *next; - - ULONG length; /* length of sample (in samples!) */ - ULONG loopstart; /* repeat position (relative to start, in samples) */ - ULONG loopend; /* repeat end */ - UWORD infmt,outfmt; - int scalefactor; - SAMPLE* sample; - MREADER* reader; + struct SAMPLOAD *next; + + ULONG length; /* length of sample (in samples!) */ + ULONG loopstart; /* repeat position (relative to start, in samples) */ + ULONG loopend; /* repeat end */ + UWORD infmt,outfmt; + int scalefactor; + SAMPLE* sample; + MREADER* reader; } SAMPLOAD; /*========== Sample and waves loading interface */ @@ -209,9 +235,9 @@ extern void SL_Sample8to16(SAMPLOAD*); extern void SL_Sample16to8(SAMPLOAD*); extern void SL_SampleSigned(SAMPLOAD*); extern void SL_SampleUnsigned(SAMPLOAD*); -extern int SL_LoadSamples(void); +extern int SL_LoadSamples(void); extern SAMPLOAD* SL_RegisterSample(SAMPLE*,int,MREADER*); -extern int SL_Load(void*,SAMPLOAD*,ULONG); +extern int SL_Load(void*,SAMPLOAD*,ULONG); extern int SL_Init(SAMPLOAD*); extern void SL_Exit(SAMPLOAD*); @@ -233,126 +259,126 @@ extern UBYTE* UniDup(void); extern int UniInit(void); extern void UniCleanup(void); extern void UniEffect(UWORD,UWORD); -#define UniInstrument(x) UniEffect(UNI_INSTRUMENT,x) -#define UniNote(x) UniEffect(UNI_NOTE,x) +#define UniInstrument(x) UniEffect(UNI_INSTRUMENT,x) +#define UniNote(x) UniEffect(UNI_NOTE,x) extern void UniPTEffect(UBYTE,UBYTE); extern void UniVolEffect(UWORD,UBYTE); /*========== Module Commands */ enum { - /* Simple note */ - UNI_NOTE = 1, - /* Instrument change */ - UNI_INSTRUMENT, - /* Protracker effects */ - UNI_PTEFFECT0, /* arpeggio */ - UNI_PTEFFECT1, /* porta up */ - UNI_PTEFFECT2, /* porta down */ - UNI_PTEFFECT3, /* porta to note */ - UNI_PTEFFECT4, /* vibrato */ - UNI_PTEFFECT5, /* dual effect 3+A */ - UNI_PTEFFECT6, /* dual effect 4+A */ - UNI_PTEFFECT7, /* tremolo */ - UNI_PTEFFECT8, /* pan */ - UNI_PTEFFECT9, /* sample offset */ - UNI_PTEFFECTA, /* volume slide */ - UNI_PTEFFECTB, /* pattern jump */ - UNI_PTEFFECTC, /* set volume */ - UNI_PTEFFECTD, /* pattern break */ - UNI_PTEFFECTE, /* extended effects */ - UNI_PTEFFECTF, /* set speed */ - /* Scream Tracker effects */ - UNI_S3MEFFECTA, /* set speed */ - UNI_S3MEFFECTD, /* volume slide */ - UNI_S3MEFFECTE, /* porta down */ - UNI_S3MEFFECTF, /* porta up */ - UNI_S3MEFFECTI, /* tremor */ - UNI_S3MEFFECTQ, /* retrig */ - UNI_S3MEFFECTR, /* tremolo */ - UNI_S3MEFFECTT, /* set tempo */ - UNI_S3MEFFECTU, /* fine vibrato */ - UNI_KEYOFF, /* note off */ - /* Fast Tracker effects */ - UNI_KEYFADE, /* note fade */ - UNI_VOLEFFECTS, /* volume column effects */ - UNI_XMEFFECT4, /* vibrato */ - UNI_XMEFFECT6, /* dual effect 4+A */ - UNI_XMEFFECTA, /* volume slide */ - UNI_XMEFFECTE1, /* fine porta up */ - UNI_XMEFFECTE2, /* fine porta down */ - UNI_XMEFFECTEA, /* fine volume slide up */ - UNI_XMEFFECTEB, /* fine volume slide down */ - UNI_XMEFFECTG, /* set global volume */ - UNI_XMEFFECTH, /* global volume slide */ - UNI_XMEFFECTL, /* set envelope position */ - UNI_XMEFFECTP, /* pan slide */ - UNI_XMEFFECTX1, /* extra fine porta up */ - UNI_XMEFFECTX2, /* extra fine porta down */ - /* Impulse Tracker effects */ - UNI_ITEFFECTG, /* porta to note */ - UNI_ITEFFECTH, /* vibrato */ - UNI_ITEFFECTI, /* tremor (xy not incremented) */ - UNI_ITEFFECTM, /* set channel volume */ - UNI_ITEFFECTN, /* slide / fineslide channel volume */ - UNI_ITEFFECTP, /* slide / fineslide channel panning */ - UNI_ITEFFECTT, /* slide tempo */ - UNI_ITEFFECTU, /* fine vibrato */ - UNI_ITEFFECTW, /* slide / fineslide global volume */ - UNI_ITEFFECTY, /* panbrello */ - UNI_ITEFFECTZ, /* resonant filters */ - UNI_ITEFFECTS0, - /* UltraTracker effects */ - UNI_ULTEFFECT9, /* Sample fine offset */ - /* OctaMED effects */ - UNI_MEDSPEED, - UNI_MEDEFFECTF1, /* play note twice */ - UNI_MEDEFFECTF2, /* delay note */ - UNI_MEDEFFECTF3, /* play note three times */ - /* Oktalyzer effects */ - UNI_OKTARP, /* arpeggio */ - - UNI_LAST + /* Simple note */ + UNI_NOTE = 1, + /* Instrument change */ + UNI_INSTRUMENT, + /* Protracker effects */ + UNI_PTEFFECT0, /* arpeggio */ + UNI_PTEFFECT1, /* porta up */ + UNI_PTEFFECT2, /* porta down */ + UNI_PTEFFECT3, /* porta to note */ + UNI_PTEFFECT4, /* vibrato */ + UNI_PTEFFECT5, /* dual effect 3+A */ + UNI_PTEFFECT6, /* dual effect 4+A */ + UNI_PTEFFECT7, /* tremolo */ + UNI_PTEFFECT8, /* pan */ + UNI_PTEFFECT9, /* sample offset */ + UNI_PTEFFECTA, /* volume slide */ + UNI_PTEFFECTB, /* pattern jump */ + UNI_PTEFFECTC, /* set volume */ + UNI_PTEFFECTD, /* pattern break */ + UNI_PTEFFECTE, /* extended effects */ + UNI_PTEFFECTF, /* set speed */ + /* Scream Tracker effects */ + UNI_S3MEFFECTA, /* set speed */ + UNI_S3MEFFECTD, /* volume slide */ + UNI_S3MEFFECTE, /* porta down */ + UNI_S3MEFFECTF, /* porta up */ + UNI_S3MEFFECTI, /* tremor */ + UNI_S3MEFFECTQ, /* retrig */ + UNI_S3MEFFECTR, /* tremolo */ + UNI_S3MEFFECTT, /* set tempo */ + UNI_S3MEFFECTU, /* fine vibrato */ + UNI_KEYOFF, /* note off */ + /* Fast Tracker effects */ + UNI_KEYFADE, /* note fade */ + UNI_VOLEFFECTS, /* volume column effects */ + UNI_XMEFFECT4, /* vibrato */ + UNI_XMEFFECT6, /* dual effect 4+A */ + UNI_XMEFFECTA, /* volume slide */ + UNI_XMEFFECTE1, /* fine porta up */ + UNI_XMEFFECTE2, /* fine porta down */ + UNI_XMEFFECTEA, /* fine volume slide up */ + UNI_XMEFFECTEB, /* fine volume slide down */ + UNI_XMEFFECTG, /* set global volume */ + UNI_XMEFFECTH, /* global volume slide */ + UNI_XMEFFECTL, /* set envelope position */ + UNI_XMEFFECTP, /* pan slide */ + UNI_XMEFFECTX1, /* extra fine porta up */ + UNI_XMEFFECTX2, /* extra fine porta down */ + /* Impulse Tracker effects */ + UNI_ITEFFECTG, /* porta to note */ + UNI_ITEFFECTH, /* vibrato */ + UNI_ITEFFECTI, /* tremor (xy not incremented) */ + UNI_ITEFFECTM, /* set channel volume */ + UNI_ITEFFECTN, /* slide / fineslide channel volume */ + UNI_ITEFFECTP, /* slide / fineslide channel panning */ + UNI_ITEFFECTT, /* slide tempo */ + UNI_ITEFFECTU, /* fine vibrato */ + UNI_ITEFFECTW, /* slide / fineslide global volume */ + UNI_ITEFFECTY, /* panbrello */ + UNI_ITEFFECTZ, /* resonant filters */ + UNI_ITEFFECTS0, + /* UltraTracker effects */ + UNI_ULTEFFECT9, /* Sample fine offset */ + /* OctaMED effects */ + UNI_MEDSPEED, + UNI_MEDEFFECTF1,/* play note twice */ + UNI_MEDEFFECTF2,/* delay note */ + UNI_MEDEFFECTF3,/* play note three times */ + /* Oktalyzer effects */ + UNI_OKTARP, /* arpeggio */ + + UNI_LAST }; -extern UWORD unioperands[UNI_LAST]; +extern const UWORD unioperands[UNI_LAST]; /* IT / S3M Extended SS effects: */ enum { - SS_GLISSANDO = 1, - SS_FINETUNE, - SS_VIBWAVE, - SS_TREMWAVE, - SS_PANWAVE, - SS_FRAMEDELAY, - SS_S7EFFECTS, - SS_PANNING, - SS_SURROUND, - SS_HIOFFSET, - SS_PATLOOP, - SS_NOTECUT, - SS_NOTEDELAY, - SS_PATDELAY + SS_GLISSANDO = 1, + SS_FINETUNE, + SS_VIBWAVE, + SS_TREMWAVE, + SS_PANWAVE, + SS_FRAMEDELAY, + SS_S7EFFECTS, + SS_PANNING, + SS_SURROUND, + SS_HIOFFSET, + SS_PATLOOP, + SS_NOTECUT, + SS_NOTEDELAY, + SS_PATDELAY }; /* IT Volume column effects */ enum { - VOL_VOLUME = 1, - VOL_PANNING, - VOL_VOLSLIDE, - VOL_PITCHSLIDEDN, - VOL_PITCHSLIDEUP, - VOL_PORTAMENTO, - VOL_VIBRATO + VOL_VOLUME = 1, + VOL_PANNING, + VOL_VOLSLIDE, + VOL_PITCHSLIDEDN, + VOL_PITCHSLIDEUP, + VOL_PORTAMENTO, + VOL_VIBRATO }; /* IT resonant filter information */ -#define UF_MAXMACRO 0x10 -#define UF_MAXFILTER 0x100 +#define UF_MAXMACRO 0x10 +#define UF_MAXFILTER 0x100 -#define FILT_CUT 0x80 -#define FILT_RESONANT 0x81 +#define FILT_CUT 0x80 +#define FILT_RESONANT 0x81 typedef struct FILTER { UBYTE filter,inf; @@ -401,163 +427,163 @@ typedef struct FILTER { /*========== Playing */ -#define POS_NONE (-2) /* no loop position defined */ +#define POS_NONE (-2) /* no loop position defined */ -#define LAST_PATTERN (UWORD)(-1) /* special ``end of song'' pattern */ +#define LAST_PATTERN (UWORD)(-1) /* special ``end of song'' pattern */ typedef struct ENVPR { - UBYTE flg; /* envelope flag */ - UBYTE pts; /* number of envelope points */ - UBYTE susbeg; /* envelope sustain index begin */ - UBYTE susend; /* envelope sustain index end */ - UBYTE beg; /* envelope loop begin */ - UBYTE end; /* envelope loop end */ - SWORD p; /* current envelope counter */ - UWORD a; /* envelope index a */ - UWORD b; /* envelope index b */ - ENVPT* env; /* envelope points */ + UBYTE flg; /* envelope flag */ + UBYTE pts; /* number of envelope points */ + UBYTE susbeg; /* envelope sustain index begin */ + UBYTE susend; /* envelope sustain index end */ + UBYTE beg; /* envelope loop begin */ + UBYTE end; /* envelope loop end */ + SWORD p; /* current envelope counter */ + UWORD a; /* envelope index a */ + UWORD b; /* envelope index b */ + ENVPT* env; /* envelope points */ } ENVPR; typedef struct MP_CHANNEL { - INSTRUMENT* i; - SAMPLE* s; - UBYTE sample; /* which sample number */ - UBYTE note; /* the audible note as heard, direct rep of period */ - SWORD outvolume; /* output volume (vol + sampcol + instvol) */ - SBYTE chanvol; /* channel's "global" volume */ - UWORD fadevol; /* fading volume rate */ - SWORD panning; /* panning position */ - UBYTE kick; /* if true = sample has to be restarted */ - UBYTE kick_flag; /* kick has been true */ - UWORD period; /* period to play the sample at */ - UBYTE nna; /* New note action type + master/slave flags */ - - UBYTE volflg; /* volume envelope settings */ - UBYTE panflg; /* panning envelope settings */ - UBYTE pitflg; /* pitch envelope settings */ - - UBYTE keyoff; /* if true = fade out and stuff */ - SWORD handle; /* which sample-handle */ - UBYTE notedelay; /* (used for note delay) */ - SLONG start; /* The starting byte index in the sample */ + INSTRUMENT* i; + SAMPLE *s; + UBYTE sample; /* which sample number */ + UBYTE note; /* the audible note as heard, direct rep of period */ + SWORD outvolume; /* output volume (vol + sampcol + instvol) */ + SBYTE chanvol; /* channel's "global" volume */ + UWORD fadevol; /* fading volume rate */ + SWORD panning; /* panning position */ + UBYTE kick; /* if true = sample has to be restarted */ + UBYTE kick_flag; /* kick has been true */ + UWORD period; /* period to play the sample at */ + UBYTE nna; /* New note action type + master/slave flags */ + + UBYTE volflg; /* volume envelope settings */ + UBYTE panflg; /* panning envelope settings */ + UBYTE pitflg; /* pitch envelope settings */ + + UBYTE keyoff; /* if true = fade out and stuff */ + SWORD handle; /* which sample-handle */ + UBYTE notedelay; /* (used for note delay) */ + SLONG start; /* The starting byte index in the sample */ } MP_CHANNEL; typedef struct MP_CONTROL { - struct MP_CHANNEL main; - - struct MP_VOICE *slave; /* Audio Slave of current effects control channel */ - - UBYTE slavechn; /* Audio Slave of current effects control channel */ - UBYTE muted; /* if set, channel not played */ - UWORD ultoffset; /* fine sample offset memory */ - UBYTE anote; /* the note that indexes the audible */ - UBYTE oldnote; - SWORD ownper; - SWORD ownvol; - UBYTE dca; /* duplicate check action */ - UBYTE dct; /* duplicate check type */ - UBYTE* row; /* row currently playing on this channel */ - SBYTE retrig; /* retrig value (0 means don't retrig) */ - ULONG speed; /* what finetune to use */ - SWORD volume; /* amiga volume (0 t/m 64) to play the sample at */ - - SWORD tmpvolume; /* tmp volume */ - UWORD tmpperiod; /* tmp period */ - UWORD wantedperiod; /* period to slide to (with effect 3 or 5) */ - - UBYTE arpmem; /* arpeggio command memory */ - UBYTE pansspd; /* panslide speed */ - UWORD slidespeed; - UWORD portspeed; /* noteslide speed (toneportamento) */ - - UBYTE s3mtremor; /* s3m tremor (effect I) counter */ - UBYTE s3mtronof; /* s3m tremor ontime/offtime */ - UBYTE s3mvolslide; /* last used volslide */ - SBYTE sliding; - UBYTE s3mrtgspeed; /* last used retrig speed */ - UBYTE s3mrtgslide; /* last used retrig slide */ - - UBYTE glissando; /* glissando (0 means off) */ - UBYTE wavecontrol; - - SBYTE vibpos; /* current vibrato position */ - UBYTE vibspd; /* "" speed */ - UBYTE vibdepth; /* "" depth */ - - SBYTE trmpos; /* current tremolo position */ - UBYTE trmspd; /* "" speed */ - UBYTE trmdepth; /* "" depth */ - - UBYTE fslideupspd; - UBYTE fslidednspd; - UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */ - UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */ - UBYTE ffportupspd; /* fx X1 (extra fine portamento up) data */ - UBYTE ffportdnspd; /* fx X2 (extra fine portamento dn) data */ - - ULONG hioffset; /* last used high order of sample offset */ - UWORD soffset; /* last used low order of sample-offset (effect 9) */ - - UBYTE sseffect; /* last used Sxx effect */ - UBYTE ssdata; /* last used Sxx data info */ - UBYTE chanvolslide; /* last used channel volume slide */ - - UBYTE panbwave; /* current panbrello waveform */ - UBYTE panbpos; /* current panbrello position */ - SBYTE panbspd; /* "" speed */ - UBYTE panbdepth; /* "" depth */ - - UWORD newsamp; /* set to 1 upon a sample / inst change */ - UBYTE voleffect; /* Volume Column Effect Memory as used by IT */ - UBYTE voldata; /* Volume Column Data Memory */ - - SWORD pat_reppos; /* patternloop position */ - UWORD pat_repcnt; /* times to loop */ + struct MP_CHANNEL main; + + struct MP_VOICE* slave; /* Audio Slave of current effects control channel */ + + UBYTE slavechn; /* Audio Slave of current effects control channel */ + UBYTE muted; /* if set, channel not played */ + UWORD ultoffset; /* fine sample offset memory */ + UBYTE anote; /* the note that indexes the audible */ + UBYTE oldnote; + SWORD ownper; + SWORD ownvol; + UBYTE dca; /* duplicate check action */ + UBYTE dct; /* duplicate check type */ + UBYTE* row; /* row currently playing on this channel */ + SBYTE retrig; /* retrig value (0 means don't retrig) */ + ULONG speed; /* what finetune to use */ + SWORD volume; /* amiga volume (0 t/m 64) to play the sample at */ + + SWORD tmpvolume; /* tmp volume */ + UWORD tmpperiod; /* tmp period */ + UWORD wantedperiod;/* period to slide to (with effect 3 or 5) */ + + UBYTE arpmem; /* arpeggio command memory */ + UBYTE pansspd; /* panslide speed */ + UWORD slidespeed; + UWORD portspeed; /* noteslide speed (toneportamento) */ + + UBYTE s3mtremor; /* s3m tremor (effect I) counter */ + UBYTE s3mtronof; /* s3m tremor ontime/offtime */ + UBYTE s3mvolslide;/* last used volslide */ + SBYTE sliding; + UBYTE s3mrtgspeed;/* last used retrig speed */ + UBYTE s3mrtgslide;/* last used retrig slide */ + + UBYTE glissando; /* glissando (0 means off) */ + UBYTE wavecontrol; + + SBYTE vibpos; /* current vibrato position */ + UBYTE vibspd; /* "" speed */ + UBYTE vibdepth; /* "" depth */ + + SBYTE trmpos; /* current tremolo position */ + UBYTE trmspd; /* "" speed */ + UBYTE trmdepth; /* "" depth */ + + UBYTE fslideupspd; + UBYTE fslidednspd; + UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */ + UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */ + UBYTE ffportupspd;/* fx X1 (extra fine portamento up) data */ + UBYTE ffportdnspd;/* fx X2 (extra fine portamento dn) data */ + + ULONG hioffset; /* last used high order of sample offset */ + UWORD soffset; /* last used low order of sample-offset (effect 9) */ + + UBYTE sseffect; /* last used Sxx effect */ + UBYTE ssdata; /* last used Sxx data info */ + UBYTE chanvolslide;/* last used channel volume slide */ + + UBYTE panbwave; /* current panbrello waveform */ + UBYTE panbpos; /* current panbrello position */ + SBYTE panbspd; /* "" speed */ + UBYTE panbdepth; /* "" depth */ + + UWORD newsamp; /* set to 1 upon a sample / inst change */ + UBYTE voleffect; /* Volume Column Effect Memory as used by IT */ + UBYTE voldata; /* Volume Column Data Memory */ + + SWORD pat_reppos; /* patternloop position */ + UWORD pat_repcnt; /* times to loop */ } MP_CONTROL; /* Used by NNA only player (audio control. AUDTMP is used for full effects control). */ typedef struct MP_VOICE { - struct MP_CHANNEL main; + struct MP_CHANNEL main; - ENVPR venv; - ENVPR penv; - ENVPR cenv; + ENVPR venv; + ENVPR penv; + ENVPR cenv; - UWORD avibpos; /* autovibrato pos */ - UWORD aswppos; /* autovibrato sweep pos */ + UWORD avibpos; /* autovibrato pos */ + UWORD aswppos; /* autovibrato sweep pos */ - ULONG totalvol; /* total volume of channel (before global mixings) */ + ULONG totalvol; /* total volume of channel (before global mixings) */ - int mflag; - SWORD masterchn; - UWORD masterperiod; + int mflag; + SWORD masterchn; + UWORD masterperiod; - MP_CONTROL* master; /* index of "master" effects channel */ + MP_CONTROL* master; /* index of "master" effects channel */ } MP_VOICE; /*========== Loaders */ typedef struct MLOADER { -struct MLOADER* next; - CHAR* type; - CHAR* version; - int (*Init)(void); - int (*Test)(void); - int (*Load)(int); - void (*Cleanup)(void); - CHAR* (*LoadTitle)(void); + struct MLOADER* next; + const CHAR* type; + const CHAR* version; + int (*Init)(void); + int (*Test)(void); + int (*Load)(int); + void (*Cleanup)(void); + CHAR* (*LoadTitle)(void); } MLOADER; /* internal loader variables */ extern MREADER* modreader; -extern UWORD finetune[16]; 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 UBYTE* poslookup; /* lookup table for pattern jumps after - blank pattern removal */ + blank pattern removal */ extern UWORD poslookupcnt; extern UWORD* origpositions; @@ -577,8 +603,7 @@ extern int AllocPatterns(void); extern int AllocTracks(void); extern int AllocInstruments(void); extern int AllocSamples(void); -extern CHAR* DupStr(CHAR*,UWORD,int); -extern CHAR* StrDup(CHAR *s); +extern CHAR* DupStr(const CHAR*, UWORD, int); /* loader utility functions */ extern int* AllocLinear(void); @@ -588,28 +613,38 @@ extern void S3MIT_ProcessCmd(UBYTE,UBYTE,unsigned int); extern void S3MIT_CreateOrders(int); /* flags for S3MIT_ProcessCmd */ -#define S3MIT_OLDSTYLE 1 /* behave as old scream tracker */ -#define S3MIT_IT 2 /* behave as impulse tracker */ -#define S3MIT_SCREAM 4 /* enforce scream tracker specific limits */ +#define S3MIT_OLDSTYLE 1 /* behave as old scream tracker */ +#define S3MIT_IT 2 /* behave as impulse tracker */ +#define S3MIT_SCREAM 4 /* enforce scream tracker specific limits */ /* used to convert c4spd to linear XM periods (IT and IMF loaders). */ extern UWORD getlinearperiod(UWORD,ULONG); extern ULONG getfrequency(UWORD,ULONG); /* loader shared data */ -#define STM_NTRACKERS 3 -extern CHAR *STM_Signatures[STM_NTRACKERS]; +#define STM_NTRACKERS 3 +extern const CHAR *STM_Signatures[STM_NTRACKERS]; /*========== Player interface */ -extern int Player_Init(MODULE*); +extern int Player_Init(MODULE*); extern void Player_Exit(MODULE*); 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 */ /* max. number of handles a driver has to provide. (not strict) */ -#define MAXSAMPLEHANDLES 384 +#define MAXSAMPLEHANDLES 384 /* These variables can be changed at ANY time and results will be immediate */ extern UWORD md_bpm; /* current song / hardware BPM rate */ @@ -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 tickhandler function. */ -extern void (*md_player)(void); +extern MikMod_player_t md_player; extern SWORD MD_SampleLoad(SAMPLOAD*,int); extern void MD_SampleUnload(SWORD); @@ -636,17 +671,17 @@ extern ULONG MD_SampleLength(int,SAMPLE*); extern void unsignedtoulaw(char *,int); /* Parameter extraction helper */ -extern CHAR *MD_GetAtom(CHAR*,CHAR*,int); +extern CHAR *MD_GetAtom(const CHAR*, const CHAR*, int); /* Internal software mixer stuff */ extern void VC_SetupPointers(void); -extern int VC1_Init(void); -extern int VC2_Init(void); +extern int VC1_Init(void); +extern int VC2_Init(void); -#if defined(unix) || defined(__APPLE__) && defined(__MACH__) +#if (MIKMOD_UNIX) /* POSIX helper functions */ -extern int MD_Access(CHAR *); -extern int MD_DropPrivileges(void); +extern int MD_Access(const CHAR *); +extern int MD_DropPrivileges(void); #endif /* Macro to define a missing driver, yet allowing binaries to dynamically link @@ -659,9 +694,9 @@ extern void _mm_registerdriver(struct MDRIVER*); extern void _mm_registerloader(struct MLOADER*); extern int MikMod_Active_internal(void); extern void MikMod_DisableOutput_internal(void); -extern int MikMod_EnableOutput_internal(void); +extern int MikMod_EnableOutput_internal(void); extern void MikMod_Exit_internal(void); -extern int MikMod_SetNumVoices_internal(int,int); +extern int MikMod_SetNumVoices_internal(int,int); extern void Player_Exit_internal(MODULE*); extern void Player_Stop_internal(void); extern int Player_Paused_internal(void); @@ -673,6 +708,15 @@ extern void Voice_SetVolume_internal(SBYTE,UWORD); extern void Voice_Stop_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 } #endif @@ -680,30 +724,36 @@ extern int Voice_Stopped_internal(SBYTE); /*========== SIMD mixing routines */ #undef HAVE_ALTIVEC #undef HAVE_SSE2 +#if defined(MIKMOD_SIMD) -#if defined(__APPLE__) && !defined (__i386__) - -#if defined __VEC__ && !(defined(__GNUC__) && (__GNUC__ < 3)) +#if (defined(__ppc__) || defined(__ppc64__)) && defined(__VEC__) && !(defined(__GNUC__) && (__GNUC__ < 3)) #define HAVE_ALTIVEC -#endif // __VEC__ -#elif defined WIN32 || defined __WIN64 || (defined __APPLE__ && defined (__i386__) && defined __VEC__) - -// FIXME: emmintrin.h requires VC6 processor pack or VC2003+ +#elif defined(__GNUC__) && defined(__SSE2__) /* x86 / x86_64 */ #define HAVE_SSE2 -/* Fixes couples warnings */ -#ifdef _MSC_VER +#elif defined(_MSC_VER) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64)) +/* FIXME: emmintrin.h requires VC6 processor pack or VC2003+ */ +#define HAVE_SSE2 +/* avoid some warnings */ #pragma warning(disable:4761) #pragma warning(disable:4391) #pragma warning(disable:4244) -#endif -#endif -// TODO: Test for GCC Linux + +#endif /* AltiVec/SSE2 */ +#endif /* MIKMOD_SIMD */ /*========== 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 */ #if defined HAVE_ALTIVEC @@ -715,33 +765,29 @@ extern int Voice_Stopped_internal(SBYTE); #include #endif -// Helper functions +/* Helper functions */ -// Set single float across the four values -static inline vector float vec_mul( const vector float a, const vector float b) -{ +/* Set single float across the four values */ +static inline vector float vec_mul(const vector float a, const vector float b) { return vec_madd(a, b, (const vector float)(0.f)); } -// Set single float across the four values -static inline vector float vec_load_ps1(const float *pF ) -{ +/* Set single float across the four values */ +static inline vector float vec_load_ps1(const float *pF) { vector float data = vec_lde(0, pF); return vec_splat(vec_perm(data, data, vec_lvsl(0, pF)), 0); } -// Set vector to 0 -static inline const vector float vec_setzero() -{ - return (const vector float) (0.); +/* Set vector to 0 */ +static inline vector float vec_setzero() { + return (vector float) (0.); } -static inline vector signed char vec_set1_8(unsigned char splatchar) -{ - vector unsigned char splatmap = vec_lvsl(0, &splatchar); - vector unsigned char result = vec_lde(0, &splatchar); - splatmap = vec_splat(splatmap, 0); - return (vector signed char)vec_perm(result, result, splatmap); +static inline vector signed char vec_set1_8(unsigned char splatchar) { + vector unsigned char splatmap = vec_lvsl(0, &splatchar); + vector unsigned char result = vec_lde(0, &splatchar); + splatmap = vec_splat(splatmap, 0); + return (vector signed char)vec_perm(result, result, splatmap); } #define PERM_A0 0x00,0x01,0x02,0x03 @@ -753,48 +799,45 @@ static inline vector signed char vec_set1_8(unsigned char splatchar) #define PERM_B2 0x18,0x19,0x1A,0x1B #define PERM_B3 0x1C,0x1D,0x1E,0x1F -// Equivalent to _mm_unpacklo_epi32 -static inline vector signed int vec_unpacklo(vector signed int a, vector signed int b) -{ +/* Equivalent to _mm_unpacklo_epi32 */ +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)); } -// Equivalent to _mm_srli_si128(a, 8) (without the zeroing in high part). -static inline vector signed int vec_hiqq(vector signed int a) -{ +/* Equivalent to _mm_srli_si128(a, 8) (without the zeroing in high part). */ +static inline vector signed int vec_hiqq(vector signed int a) { vector signed int b = vec_splat_s32(0); 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 ... -#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_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_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_16(srce, var) var = vec_sra(vec_ld(0, (vector signed int*)(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_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); +/* 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 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 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 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 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_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 LOAD_PS1_SIMD(ptr) vec_load_ps1(ptr) #elif defined HAVE_SSE2 -/* SSE2 helper function */ - #include -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). +/* SSE2 helper function */ + +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 */ -#define EXTRACT_SAMPLE_SIMD(srce, var, size) var = _mm_srai_epi32(_mm_load_si128((__m128i*)(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(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 const *)(srce)), BITSHIFT-size)), mul); #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_16(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 16) -#define PUT_SAMPLE_SIMD_W(dste, v1, v2) _mm_store_si128((__m128i*)(dste), _mm_packs_epi32(v1, v2)); -#define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) _mm_store_si128((__m128i*)(dste), _mm_add_epi8(_mm_packs_epi16(_mm_packs_epi32(v1, v2), _mm_packs_epi32(v3, v4)), _mm_set1_epi8(128))); +#define PUT_SAMPLE_SIMD_W(dste, v1, v2) _mm_store_si128((__m128i*)(dste), _mm_packs_epi32(v1, v2)); +#define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) _mm_store_si128((__m128i*)(dste), _mm_add_epi8(_mm_packs_epi16(_mm_packs_epi32(v1, v2), _mm_packs_epi32(v3, v4)), _mm_set1_epi8(128))); #define PUT_SAMPLE_SIMD_F(dste, v1) _mm_store_ps((float*)(dste), v1); #define LOAD_PS1_SIMD(ptr) _mm_load_ps1(ptr) #define simd_m128i __m128i @@ -802,7 +845,25 @@ static __inline __m128i mm_hiqq(const __m128i a) #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 +#else /* NO SIMD */ +#define MikMod_amalloc MikMod_malloc +#define MikMod_afree MikMod_free #endif +#endif /* _MIKMOD_INTERNALS_H */ + /* ex:set ts=4: */ diff --git a/apps/plugins/mikmod/mikmod_supp.h b/apps/plugins/mikmod/mikmod_supp.h index c1a8681720..fdd9d8f24f 100644 --- a/apps/plugins/mikmod/mikmod_supp.h +++ b/apps/plugins/mikmod/mikmod_supp.h @@ -8,6 +8,9 @@ #undef WIN32 +#define NO_DEPACKERS // We don't support these +//#define NO_HQMIXER // We don't have the oomph + #ifndef NO_MMSUPP_DEFINES #define snprintf(...) rb->snprintf(__VA_ARGS__) #define fdprintf(...) rb->fdprintf(__VA_ARGS__) diff --git a/apps/plugins/mikmod/mloader.c b/apps/plugins/mikmod/mloader.c index 5f58d8102f..9ea9489272 100644 --- a/apps/plugins/mikmod/mloader.c +++ b/apps/plugins/mikmod/mloader.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -50,7 +50,17 @@ MODULE of; 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, 7895,7941,7985,8046,8107,8169,8232,8280 }; @@ -63,15 +73,18 @@ MIKMODAPI CHAR* MikMod_InfoLoader(void) MUTEX_LOCK(lists); /* 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((list=MikMod_malloc(len*sizeof(CHAR)))) { - list[0]=0; - /* list all registered module loders */ - for(l=firstloader;l;l=l->next) - sprintf(list,(l->next)?"%s%s\n":"%s%s",list,l->version); + if((list=(CHAR*)MikMod_malloc(len*sizeof(CHAR))) != NULL) { + CHAR *list_end = list; + list[0] = 0; + /* list all registered module loders */ + for(l = firstloader; l; l = l->next) { + list_end += sprintf(list_end, "%s%s", l->version, (l->next) ? "\n" : ""); } + } MUTEX_UNLOCK(lists); return list; } @@ -84,7 +97,7 @@ void _mm_registerloader(MLOADER* ldr) while(cruise->next) cruise = cruise->next; cruise->next=ldr; } else - firstloader=ldr; + firstloader=ldr; } MIKMODAPI void MikMod_RegisterLoader(struct MLOADER* ldr) @@ -106,7 +119,7 @@ int ReadComment(UWORD len) if(!(of.comment=(CHAR*)MikMod_malloc(len+1))) return 0; _mm_read_UBYTES(of.comment,len,modreader); - + /* translate IT linefeeds */ for(i=0;i=0)&&(line[i]==' ');i--) line[i]=0; - for(i=0;ilines) { - if(!(of.comment=(CHAR*)MikMod_malloc(total+1))) { - MikMod_free(storage); - MikMod_free(tempcomment); - return 0; - } + /* Adapted from the OpenMPT project, C'ified. */ + CHAR *buf, *storage, *p; + size_t numlines, line, fpos, cpos, lpos, cnt; + + if (!linelen) return 0; + if (!len) return 1; + + if (!(buf = (CHAR *) MikMod_malloc(len))) return 0; + numlines = (len + linelen - 1) / linelen; + cnt = (linelen + 1) * numlines; + if (!(storage = (CHAR *) MikMod_malloc(cnt + 1))) { + MikMod_free(buf); + return 0; + } - /* convert message */ - for(line=tempcomment,t=0;t linelen) cnt = linelen; + p = storage + cpos; + 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; } - MikMod_free(storage); - MikMod_free(tempcomment); } } + + of.comment = storage; + MikMod_free(buf); return 1; } @@ -169,7 +182,7 @@ int AllocPositions(int total) _mm_errno=MMERR_NOT_A_MODULE; 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; } @@ -207,7 +220,7 @@ int AllocTracks(void) int AllocInstruments(void) { int t,n; - + if(!of.numins) { _mm_errno=MMERR_NOT_A_MODULE; return 0; @@ -216,11 +229,11 @@ int AllocInstruments(void) return 0; for(t=0;thandle>=0) 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) { - if(i->insname) MikMod_free(i->insname); + MikMod_free(i->insname); } static void ML_FreeEx(MODULE *mf) { UWORD t; - if(mf->songname) MikMod_free(mf->songname); - if(mf->comment) MikMod_free(mf->comment); + MikMod_free(mf->songname); + MikMod_free(mf->comment); - if(mf->modtype) MikMod_free(mf->modtype); - if(mf->positions) MikMod_free(mf->positions); - if(mf->patterns) MikMod_free(mf->patterns); - if(mf->pattrows) MikMod_free(mf->pattrows); + MikMod_free(mf->modtype); + MikMod_free(mf->positions); + MikMod_free(mf->patterns); + MikMod_free(mf->pattrows); if(mf->tracks) { for(t=0;tnumtrk;t++) - if(mf->tracks[t]) MikMod_free(mf->tracks[t]); + MikMod_free(mf->tracks[t]); MikMod_free(mf->tracks); } if(mf->instruments) { @@ -327,8 +334,10 @@ static void ML_FreeEx(MODULE *mf) MikMod_free(mf->instruments); } if(mf->samples) { - for(t=0;tnumsmp;t++) + for(t=0;tnumsmp;t++) { + MikMod_free(mf->samples[t].samplename); if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]); + } MikMod_free(mf->samples); } memset(mf,0,sizeof(MODULE)); @@ -337,10 +346,24 @@ static void ML_FreeEx(MODULE *mf) static MODULE *ML_AllocUniMod(void) { - MODULE *mf; + return (MODULE *) MikMod_malloc(sizeof(MODULE)); +} + +#ifndef NO_DEPACKERS +static int ML_TryUnpack(MREADER *reader,void **out,long *outlen) +{ + int i; - return (mf=MikMod_malloc(sizeof(MODULE))); + *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) { @@ -360,25 +383,50 @@ MIKMODAPI void Player_Free(MODULE *mf) static CHAR* Player_LoadTitle_internal(MREADER *reader) { MLOADER *l; + CHAR *title; + #ifndef NO_DEPACKERS + void *unpk; + long newlen; + #endif modreader=reader; _mm_errno = 0; _mm_critical = 0; _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 */ for(l=firstloader;l;l=l->next) { _mm_rewind(modreader); if(l->Test()) break; } - if(!l) { + if(l) { + title = l->LoadTitle(); + } + else { _mm_errno = MMERR_NOT_A_MODULE; 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) @@ -386,7 +434,7 @@ MIKMODAPI CHAR* Player_LoadTitleFP(int fp) CHAR* result=NULL; MREADER* reader; - if(fp && (reader=_mm_new_file_reader(fp))) { + if(fp && (reader=_mm_new_file_reader(fp)) != NULL) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); @@ -400,22 +448,22 @@ MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len) CHAR *result=NULL; 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); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); _mm_delete_mem_reader(reader); } - - + return result; } MIKMODAPI CHAR* Player_LoadTitleGeneric(MREADER *reader) -{ +{ CHAR *result=NULL; - + if (reader) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); @@ -424,14 +472,14 @@ MIKMODAPI CHAR* Player_LoadTitleGeneric(MREADER *reader) return result; } -MIKMODAPI CHAR* Player_LoadTitle(CHAR* filename) +MIKMODAPI CHAR* Player_LoadTitle(const CHAR* filename) { CHAR* result=NULL; int fp; MREADER* reader; - if((fp=_mm_fopen(filename,"rb"))) { - if((reader=_mm_new_file_reader(fp))) { + if((fp=_mm_fopen(filename,"rb")) >= 0) { + if((reader=_mm_new_file_reader(fp)) != NULL) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); @@ -449,12 +497,26 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio MLOADER *l; int ok; MODULE *mf; + #ifndef NO_DEPACKERS + void *unpk; + long newlen; + #endif modreader = reader; _mm_errno = 0; _mm_critical = 0; _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 */ for(l=firstloader;l;l=l->next) { _mm_rewind(modreader); @@ -463,15 +525,31 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio if(!l) { _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(); - _mm_rewind(modreader);_mm_iobase_revert(modreader); + _mm_rewind(modreader); + _mm_iobase_revert(modreader); return NULL; } /* init unitrk routines */ if(!UniInit()) { + #ifndef NO_DEPACKERS + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + #endif if(_mm_errorhandler) _mm_errorhandler(); - _mm_rewind(modreader);_mm_iobase_revert(modreader); + _mm_rewind(modreader); + _mm_iobase_revert(modreader); return NULL; } @@ -487,7 +565,7 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio if (!l->Init || l->Init()) { _mm_rewind(modreader); ok = l->Load(curious); - if (ok) { + if (ok) { /* propagate inflags=flags for in-module samples */ for (t = 0; t < of.numsmp; t++) if (of.samples[t].inflags == 0) @@ -500,27 +578,23 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio if (l->Cleanup) l->Cleanup(); UniCleanup(); + if(ok) ok = ML_LoadSamples(); + if(ok) ok = ((mf=ML_AllocUniMod()) != NULL); if(!ok) { ML_FreeEx(&of); + #ifndef NO_DEPACKERS + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + #endif if(_mm_errorhandler) _mm_errorhandler(); - _mm_rewind(modreader);_mm_iobase_revert(modreader); - return NULL; - } - - if(!ML_LoadSamples()) { - ML_FreeEx(&of); - if(_mm_errorhandler) _mm_errorhandler(); - _mm_rewind(modreader);_mm_iobase_revert(modreader); + _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(); - return NULL; - } - /* If the module doesn't have any specific panning, create a MOD-like panning, with the channels half-separated. */ if (!(of.flags & UF_PANNING)) @@ -539,23 +613,25 @@ static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,int curio if(maxchannumchn) mf->flags |= UF_NNA; - if(MikMod_SetNumVoices_internal(maxchan,-1)) { - _mm_iobase_revert(modreader); - Player_Free(mf); - return NULL; - } + ok = !MikMod_SetNumVoices_internal(maxchan,-1); } - if(SL_LoadSamples()) { - _mm_iobase_revert(modreader); - Player_Free_internal(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(Player_Init(mf)) { - _mm_iobase_revert(modreader); + #endif + _mm_iobase_revert(modreader); + + if(!ok) { Player_Free_internal(mf); - mf=NULL; + return NULL; } - _mm_iobase_revert(modreader); return mf; } @@ -577,7 +653,8 @@ MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,int curi MODULE* result=NULL; 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); _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) { 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); _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 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; MODULE *mf=NULL; - if((fp=_mm_fopen(filename,"rb"))) { + if((fp=_mm_fopen(filename,"rb")) >= 0) { mf=Player_LoadFP(fp,maxchan,curious); _mm_fclose(fp); } diff --git a/apps/plugins/mikmod/mlreg.c b/apps/plugins/mikmod/mlreg.c index c8850fb62f..10095d8157 100644 --- a/apps/plugins/mikmod/mlreg.c +++ b/apps/plugins/mikmod/mlreg.c @@ -40,7 +40,7 @@ static void MikMod_RegisterAllLoaders_internal(void) _mm_registerloader(&load_dsm); _mm_registerloader(&load_far); _mm_registerloader(&load_gdm); - _mm_registerloader(&load_gt2); +/* _mm_registerloader(&load_gt2);*/ /* load_gt2 isn't complete */ _mm_registerloader(&load_it); _mm_registerloader(&load_imf); _mm_registerloader(&load_mod); @@ -51,13 +51,14 @@ static void MikMod_RegisterAllLoaders_internal(void) _mm_registerloader(&load_stm); _mm_registerloader(&load_stx); _mm_registerloader(&load_ult); + _mm_registerloader(&load_umx); _mm_registerloader(&load_uni); _mm_registerloader(&load_xm); _mm_registerloader(&load_m15); } -void MikMod_RegisterAllLoaders(void) +MIKMODAPI void MikMod_RegisterAllLoaders(void) { MUTEX_LOCK(lists); MikMod_RegisterAllLoaders_internal(); diff --git a/apps/plugins/mikmod/mlutil.c b/apps/plugins/mikmod/mlutil.c index ddaddc7871..328b1d4089 100644 --- a/apps/plugins/mikmod/mlutil.c +++ b/apps/plugins/mikmod/mlutil.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -43,13 +43,13 @@ extern int fprintf(FILE *, const char *, ...); /*========== Shared tracker identifiers */ -CHAR *STM_Signatures[STM_NTRACKERS] = { +const CHAR *STM_Signatures[STM_NTRACKERS] = { "!Scream!", "BMOD2STM", "WUZAMOD!" }; -CHAR *STM_Version[STM_NTRACKERS] = { +const CHAR *STM_Version[STM_NTRACKERS] = { "Screamtracker 2", "Converted by MOD2STM (STM format)", "Wuzamod (STM format)" @@ -71,29 +71,27 @@ FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */ /*========== Linear periods stuff */ int* noteindex=NULL; /* remap value for linear period modules */ -static int noteindexcount=0; +static unsigned noteindexcount=0; int *AllocLinear(void) { if(of.numsmp>noteindexcount) { noteindexcount=of.numsmp; - noteindex=MikMod_realloc(noteindex,noteindexcount*sizeof(int)); + noteindex=(int*)MikMod_realloc(noteindex,noteindexcount*sizeof(int)); } return noteindex; } void FreeLinear(void) { - if(noteindex) { - MikMod_free(noteindex); - noteindex=NULL; - } + MikMod_free(noteindex); + noteindex=NULL; noteindexcount=0; } 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; while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))speed) - tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune)); + tmp=getfrequency(of.flags,getlinearperiod(note<<1,--ft)); else { note--; while(ctmp>4; */ - + UBYTE lo = inf&0xF; /* process S3M / IT specific command structure */ if(cmd!=255) { @@ -196,7 +190,7 @@ void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags) case 9: /* Ixy tremor, ontime x, offtime y */ if (flags & S3MIT_OLDSTYLE) UniEffect(UNI_S3MEFFECTI,inf); - else + else UniEffect(UNI_ITEFFECTI,inf); break; case 0xa: /* Jxy arpeggio */ @@ -204,7 +198,7 @@ void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags) break; case 0xb: /* Kxy Dual command H00 & Dxy */ if (flags & S3MIT_OLDSTYLE) - UniPTEffect(0x4,0); + UniPTEffect(0x4,0); else UniEffect(UNI_ITEFFECTH,0); UniEffect(UNI_S3MEFFECTD,inf); @@ -218,7 +212,7 @@ void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags) break; case 0xd: /* Mxx Set Channel Volume */ UniEffect(UNI_ITEFFECTM,inf); - break; + break; case 0xe: /* Nxy Slide Channel Volume */ UniEffect(UNI_ITEFFECTN,inf); break; @@ -233,7 +227,7 @@ void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags) if(inf && !lo && !(flags & S3MIT_OLDSTYLE)) UniWriteByte(1); else - UniWriteByte(inf); + UniWriteByte(inf); break; case 0x12: /* Rxy tremolo speed x, depth y */ UniEffect(UNI_S3MEFFECTR,inf); diff --git a/apps/plugins/mikmod/mmalloc.c b/apps/plugins/mikmod/mmalloc.c index 2797def57d..ed5fd4684c 100644 --- a/apps/plugins/mikmod/mmalloc.c +++ b/apps/plugins/mikmod/mmalloc.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: mmalloc.c,v 1.3 2007/12/03 20:42:58 denis111 Exp $ + $Id$ Dynamic memory routines @@ -30,150 +30,113 @@ #include "config.h" #endif -#include "mikmod_internals.h" - -#define ALIGN_STRIDE 16 -/* not used -static void * align_pointer(char *ptr, size_t stride) -{ - char *pptr = ptr + sizeof(void*); - char *fptr; - size_t err = ((size_t)pptr)&(stride-1); - if (err) - fptr = pptr + (stride - err); - else - fptr = pptr; - *(size_t*)(fptr - sizeof(void*)) = (size_t)ptr; - return fptr; -} +#ifdef HAVE_POSIX_MEMALIGN +#define _XOPEN_SOURCE 600 /* for posix_memalign */ +#endif -static void *get_pointer(void *data) -{ - unsigned char *_pptr = (unsigned char*)data - sizeof(void*); - size_t _ptr = *(size_t*)_pptr; - return (void*)_ptr; -} -*/ +#include "string.h" +#include "mikmod_internals.h" -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); +#if defined(HAVE_SSE2) || defined(HAVE_ALTIVEC) +#undef WIN32_ALIGNED_MALLOC +#if defined(_WIN32) && !defined(_WIN32_WCE) +# if defined(_WIN64) /* OK with MSVC and MinGW */ +# define WIN32_ALIGNED_MALLOC +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# define WIN32_ALIGNED_MALLOC +# elif defined(__MINGW32__) + /* no guarantees that msvcrt.dll will have it */ +# 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 */ -void* MikMod_malloc(size_t size) +/* return a 16 byte aligned address */ +void* MikMod_amalloc(size_t size) { void *d; - if(!(d=calloc(1,size))) { - _mm_errno = MMERR_OUT_OF_MEMORY; - if(_mm_errorhandler) _mm_errorhandler(); - } - return d; - -#if 0 -#if defined __MACH__ - void *d = calloc(1, size); - if (d) - { +#if defined(HAVE_POSIX_MEMALIGN) + if (!posix_memalign(&d, 16, size)) { + memset(d, 0, size); return d; } - return 0; -#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE) - void * d = _aligned_malloc(size, ALIGN_STRIDE); - if (d) - { +#elif defined(WIN32_ALIGNED_MALLOC) + d = _aligned_malloc(size, 16); + if (d) { ZeroMemory(d, size); return d; } - return 0; #else - void *d = calloc(1, size + ALIGN_STRIDE + sizeof(void*)); - - if(!d) { - _mm_errno = MMERR_OUT_OF_MEMORY; - if(_mm_errorhandler) _mm_errorhandler(); + 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; } - return align_pointer(d, ALIGN_STRIDE); #endif + + _mm_errno = MMERR_OUT_OF_MEMORY; + if(_mm_errorhandler) _mm_errorhandler(); + return NULL; +} + +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 /* (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 */ -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); - if (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; - if(_mm_errorhandler) _mm_errorhandler(); - } - return align_pointer(d, ALIGN_STRIDE); -#endif -#endif + if (d) return d; + + _mm_errno = MMERR_OUT_OF_MEMORY; + if(_mm_errorhandler) _mm_errorhandler(); + return NULL; } void MikMod_free(void *data) { - free(data); - -#if 0 - if (data) - { -#if defined __MACH__ - free(data); -#elif (defined _WIN32 || defined _WIN64) && !defined(_WIN32_WCE) - _aligned_free(data); -#else - free(get_pointer(data)); -#endif - } -#endif + if (data) free(data); +} + +/* like strdup(), but the result must be freed using MikMod_free() */ +CHAR *MikMod_strdup(const CHAR *s) +{ + size_t l; + CHAR *d; + + if (!s) return NULL; + + l = strlen(s) + 1; + d = (CHAR *) MikMod_calloc(1, l * sizeof(CHAR)); + if (d) strcpy(d, s); + return d; } /* ex:set ts=4: */ diff --git a/apps/plugins/mikmod/mmerror.c b/apps/plugins/mikmod/mmerror.c index ed7c66a10f..4d7949890e 100644 --- a/apps/plugins/mikmod/mmerror.c +++ b/apps/plugins/mikmod/mmerror.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: mmerror.c,v 1.2 2005/03/30 19:10:41 realtech Exp $ + $Id$ Error handling functions. Register an error handler with _mm_RegisterErrorHandler() and you're all set. @@ -40,7 +40,9 @@ #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 */ @@ -82,62 +84,89 @@ CHAR *_mm_errmsg[MMERR_MAX+1] = "Unable to set non-blocking mode for audio device", /* AudioFile driver errors */ - +#ifdef DRV_AF "Cannot find suitable AudioFile audio port", +#else + _mmerr_invalid, +#endif /* AIX driver errors */ - +#ifdef DRV_AIX "Configuration (init step) of audio device failed", "Configuration (control step) of audio device failed", "Configuration (start step) of audio device failed", - -/* ALSA driver errors */ - -/* EsounD driver errors */ +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, +#endif /* Ultrasound driver errors */ - +#ifdef DRV_ULTRA "Ultrasound driver only works in 16 bit stereo 44 KHz", "Ultrasound card could not be reset", "Could not start Ultrasound timer", +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, +#endif /* HP driver errors */ - +#ifdef DRV_HP "Unable to select 16bit-linear sample format", "Could not select requested sample-rate", "Could not select requested number of channels", "Unable to select audio output", "Unable to get audio description", "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 */ - +#ifdef DRV_OSS "Could not set fragment size", "Could not set sample size", "Could not set mono/stereo setting", "Could not set sample rate", +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, + _mmerr_invalid, +#endif /* SGI driver errors */ - +#ifdef DRV_SGI "Unsupported sample rate", "Hardware does not support 16 bit sound", "Hardware does not support 8 bit sound", "Hardware does not support stereo sound", "Hardware does not support mono sound", +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, + _mmerr_invalid, _mmerr_invalid, +#endif /* Sun driver errors */ - +#ifdef DRV_SUN "Sound device initialization failed", +#else + _mmerr_invalid, +#endif /* OS/2 drivers errors */ - +#if defined(DRV_OS2) || defined(DRV_DART) "Could not set mixing parameters", +#else + _mmerr_invalid, +#endif +#ifdef DRV_OS2 "Could not create playback semaphores", "Could not create playback timer", "Could not create playback thread", +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, +#endif /* DirectSound driver errors */ - +#ifdef DRV_DS "Could not set playback priority", "Could not create playback buffers", "Could not set playback format", @@ -145,22 +174,34 @@ CHAR *_mm_errmsg[MMERR_MAX+1] = "Could not register event", "Could not create 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 */ - +#ifdef DRV_WIN "Invalid device handle", "The resource is already allocated", "Invalid device identifier", "Unsupported output format", "Unknown error", +#else + _mmerr_invalid, _mmerr_invalid, _mmerr_invalid, + _mmerr_invalid, _mmerr_invalid, +#endif /* Macintosh driver errors */ - +#ifdef DRV_MAC "Unsupported sample rate", "Could not start playback", +#else + _mmerr_invalid, _mmerr_invalid, +#endif /* MacOS X/Darwin driver errors */ - +#ifdef DRV_OSX "Unknown device", "Bad property", "Could not set playback format", @@ -169,20 +210,81 @@ CHAR *_mm_errmsg[MMERR_MAX+1] = "Could not create playback thread", "Could not start audio device", "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 */ - +#ifdef DRV_WSS "WSS_STARTDMA", +#else + _mmerr_invalid, +#endif +#ifdef DRV_SB "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 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]; } diff --git a/apps/plugins/mikmod/mmio.c b/apps/plugins/mikmod/mmio.c index 0ffecffd2f..023c56baef 100644 --- a/apps/plugins/mikmod/mmio.c +++ b/apps/plugins/mikmod/mmio.c @@ -6,12 +6,12 @@ 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 @@ -20,8 +20,6 @@ /*============================================================================== - $Id: mmio.c,v 1.3 2005/03/30 19:10:58 realtech Exp $ - Portable file I/O routines ==============================================================================*/ @@ -51,10 +49,14 @@ #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif + #include #include +#include -#include "mikmod.h" #include "mikmod_internals.h" #ifdef SUNOS @@ -66,8 +68,6 @@ extern int fseek(FILE *, long, int); extern size_t fwrite(const void *, size_t, size_t, FILE *); #endif -#define COPY_BUFSIZE 1024 - /* some prototypes */ static int _mm_MemReader_Eof(MREADER* reader); static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size); @@ -75,16 +75,13 @@ static int _mm_MemReader_Get(MREADER* reader); static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence); static long _mm_MemReader_Tell(MREADER* reader); -//static long _mm_iobase=0,temp_iobase=0; - -int _mm_fopen(CHAR* fname,CHAR* attrib) +int _mm_fopen(const CHAR* fname, const CHAR* attrib) { int fp; - (void)attrib; - + (void)attrib; //if(!(fp=fopen(fname,attrib))) { - // _mm_errno = MMERR_OPENING_FILE; - // if(_mm_errorhandler) _mm_errorhandler(); + // _mm_errno = MMERR_OPENING_FILE; + // if(_mm_errorhandler) _mm_errorhandler(); //} fp = open(fname, O_RDONLY); if( fp < 0 ) { @@ -94,7 +91,7 @@ int _mm_fopen(CHAR* fname,CHAR* attrib) return fp; } -int _mm_FileExists(CHAR* fname) +int _mm_FileExists(const CHAR* fname) { int fp; @@ -103,7 +100,7 @@ int _mm_FileExists(CHAR* fname) fp = open(fname, O_RDONLY); if ( fp < 0 ) return 0; close(fp); - + return 1; } @@ -130,12 +127,12 @@ void _mm_iobase_revert(MREADER* reader) typedef struct MFILEREADER { MREADER core; - int file; + int file; } MFILEREADER; static int _mm_FileReader_Eof(MREADER* reader) { - //return feof(((MFILEREADER*)reader)->file); + //return feof(((MFILEREADER*)reader)->file); int size = filesize(((MFILEREADER*)reader)->file); int offset = lseek(((MFILEREADER*)reader)->file, 0, SEEK_CUR); return (size <= 0 || offset < 0 || offset >= size) ? 1 : 0; @@ -143,8 +140,8 @@ static int _mm_FileReader_Eof(MREADER* reader) 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 !!fread(ptr,size,1,((MFILEREADER*)reader)->file); } static int _mm_FileReader_Get(MREADER* reader) @@ -160,7 +157,7 @@ static int _mm_FileReader_Get(MREADER* reader) static int _mm_FileReader_Seek(MREADER* reader,long offset,int whence) { //return fseek(((MFILEREADER*)reader)->file, - // (whence==SEEK_SET)?offset+reader->iobase:offset,whence); + // (whence==SEEK_SET)?offset+reader->iobase:offset,whence); return lseek(((MFILEREADER*)reader)->file, (whence==SEEK_SET)?offset+reader->iobase:offset,whence); } @@ -173,7 +170,7 @@ static long _mm_FileReader_Tell(MREADER* reader) MREADER *_mm_new_file_reader(int fp) { - MFILEREADER* reader=(MFILEREADER*)MikMod_malloc(sizeof(MFILEREADER)); + MFILEREADER* reader=(MFILEREADER*)MikMod_calloc(1,sizeof(MFILEREADER)); if (reader) { reader->core.Eof =&_mm_FileReader_Eof; reader->core.Read=&_mm_FileReader_Read; @@ -187,14 +184,14 @@ MREADER *_mm_new_file_reader(int fp) void _mm_delete_file_reader (MREADER* reader) { - if(reader) MikMod_free(reader); + MikMod_free(reader); } /*========== File Writer */ typedef struct MFILEWRITER { MWRITER core; - int file; + int file; } MFILEWRITER; static int _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence) @@ -209,27 +206,26 @@ static long _mm_FileWriter_Tell(MWRITER* writer) 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 (write(ptr,size,((MFILEWRITER*)writer)->file)==(int)size); - (void)writer; - (void)ptr; - (void)size; - return 0; + (void)writer; + (void)ptr; + (void)size; + return 0; } static int _mm_FileWriter_Put(MWRITER* writer,int value) { - (void)writer; - (void)value; + (void)writer; + (void)value; //return fputc(value,((MFILEWRITER*)writer)->file); - return 1; // TODO + return 1; // TODO } MWRITER *_mm_new_file_writer(int fp) { - MFILEWRITER* writer=(MFILEWRITER*)MikMod_malloc(sizeof(MFILEWRITER)); + MFILEWRITER* writer=(MFILEWRITER*)MikMod_calloc(1,sizeof(MFILEWRITER)); if (writer) { writer->core.Seek =&_mm_FileWriter_Seek; writer->core.Tell =&_mm_FileWriter_Tell; @@ -242,12 +238,11 @@ MWRITER *_mm_new_file_writer(int fp) void _mm_delete_file_writer (MWRITER* writer) { - if(writer) MikMod_free (writer); + MikMod_free (writer); } /*========== Memory Reader */ - typedef struct MMEMREADER { MREADER core; const void *buffer; @@ -257,12 +252,12 @@ typedef struct MMEMREADER { 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) { 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) { - if (!reader) { return 1; } - if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { - return 1; - } + MMEMREADER* mr = (MMEMREADER*) reader; + if (!mr) return 1; + if (mr->pos >= mr->len) return 1; return 0; } static int _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size) { - unsigned char *d=ptr; + unsigned char *d; const unsigned char *s; - - if (!reader) { return 0; } - - if (reader->Eof(reader)) { return 0; } - - s = ((MMEMREADER*)reader)->buffer; - s += ((MMEMREADER*)reader)->pos; - - if ( ((MMEMREADER*)reader)->pos + (long)size > ((MMEMREADER*)reader)->len) - { - ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; - return 0; /* not enough remaining bytes */ + MMEMREADER* mr; + long siz; + int ret; + + if (!reader || !size || (size > (size_t) LONG_MAX)) + return 0; + + mr = (MMEMREADER*) reader; + siz = (long) size; + if (mr->pos >= mr->len) return 0; /* @ eof */ + if (mr->pos + siz > mr->len) { + siz = mr->len - mr->pos; + ret = 0; /* not enough remaining bytes */ + } + else { + 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--) - { - *d = *s; - s++; - d++; + while (siz) { + *d++ = *s++; + siz--; } - - return 1; + + return ret; } static int _mm_MemReader_Get(MREADER* reader) { - int pos; + MMEMREADER* mr; + int c; - if (reader->Eof(reader)) { return 0; } - - pos = ((MMEMREADER*)reader)->pos; - ((MMEMREADER*)reader)->pos++; + mr = (MMEMREADER*) reader; + if (mr->pos >= mr->len) return EOF; + c = ((const unsigned char*) mr->buffer)[mr->pos]; + mr->pos++; - return ((unsigned char*)(((MMEMREADER*)reader)->buffer))[pos]; + return c; } 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) { - case SEEK_CUR: - ((MMEMREADER*)reader)->pos += offset; - break; - case SEEK_SET: - ((MMEMREADER*)reader)->pos = offset; - break; - case SEEK_END: - ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len - offset - 1; - break; + case SEEK_CUR: + mr->pos += offset; + break; + case SEEK_SET: + mr->pos = reader->iobase + offset; + break; + case SEEK_END: + mr->pos = mr->len + offset; + break; + default: /* invalid */ + return -1; } - if ( ((MMEMREADER*)reader)->pos < 0) { ((MMEMREADER*)reader)->pos = 0; } - if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { - ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; + if (mr->pos < reader->iobase) { + mr->pos = mr->core.iobase; + return -1; + } + if (mr->pos > mr->len) { + mr->pos = mr->len; } return 0; } @@ -354,13 +361,14 @@ static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence) static long _mm_MemReader_Tell(MREADER* reader) { if (reader) { - return ((MMEMREADER*)reader)->pos; + return ((MMEMREADER*)reader)->pos - reader->iobase; } return 0; } /*========== Write functions */ -void _mm_write_string(CHAR* data,MWRITER* writer) + +void _mm_write_string(const CHAR* data,MWRITER* writer) { if(data) _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); } -#if defined __STDC__ || defined _MSC_VER || defined MPW_C -#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ -void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \ -{ \ - while(number-->0) \ - _mm_write_##type_name(*(buffer++),writer); \ +void _mm_write_M_SWORDS(SWORD *buffer,int cnt,MWRITER* writer) +{ + while(cnt-- > 0) _mm_write_M_SWORD(*(buffer++),writer); } -#else -#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ -void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \ -{ \ - while(number-->0) \ - _mm_write_/**/type_name(*(buffer++),writer); \ + +void _mm_write_M_UWORDS(UWORD *buffer,int cnt,MWRITER* writer) +{ + while(cnt-- > 0) _mm_write_M_UWORD(*(buffer++),writer); } -#endif -DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD) -DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD) -DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD) -DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD) +void _mm_write_I_SWORDS(SWORD *buffer,int cnt,MWRITER* writer) +{ + while(cnt-- > 0) _mm_write_I_SWORD(*(buffer++),writer); +} -DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG) -DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG) -DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG) -DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG) +void _mm_write_I_UWORDS(UWORD *buffer,int cnt,MWRITER* writer) +{ + while(cnt-- > 0) _mm_write_I_UWORD(*(buffer++),writer); +} + +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 */ -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) @@ -491,32 +513,52 @@ SLONG _mm_read_I_SLONG(MREADER* reader) return((SLONG)_mm_read_I_ULONG(reader)); } -#if defined __STDC__ || defined _MSC_VER || defined MPW_C -#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ -int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \ -{ \ - while(number-->0) \ - *(buffer++)=_mm_read_##type_name(reader); \ - return !reader->Eof(reader); \ +int _mm_read_M_SWORDS(SWORD *buffer,int cnt,MREADER* reader) +{ + while(cnt-- > 0) *(buffer++)=_mm_read_M_SWORD(reader); + return !reader->Eof(reader); } -#else -#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ -int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \ -{ \ - while(number-->0) \ - *(buffer++)=_mm_read_/**/type_name(reader); \ - return !reader->Eof(reader); \ + +int _mm_read_M_UWORDS(UWORD *buffer,int cnt,MREADER* reader) +{ + while(cnt-- > 0) *(buffer++)=_mm_read_M_UWORD(reader); + return !reader->Eof(reader); } -#endif -DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD) -DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD) -DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD) -DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD) +int _mm_read_I_SWORDS(SWORD *buffer,int cnt,MREADER* reader) +{ + while(cnt-- > 0) *(buffer++)=_mm_read_I_SWORD(reader); + return !reader->Eof(reader); +} + +int _mm_read_I_UWORDS(UWORD *buffer,int cnt,MREADER* reader) +{ + while(cnt-- > 0) *(buffer++)=_mm_read_I_UWORD(reader); + 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); +} -DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG) -DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG) -DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG) -DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG) +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: */ diff --git a/apps/plugins/mikmod/mplayer.c b/apps/plugins/mikmod/mplayer.c index 88d6a81af4..ee5c2d187e 100644 --- a/apps/plugins/mikmod/mplayer.c +++ b/apps/plugins/mikmod/mplayer.c @@ -6,12 +6,12 @@ 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 @@ -20,7 +20,7 @@ /*============================================================================== - $Id: mplayer.c,v 1.4 2006/08/08 00:06:31 realtech Exp $ + $Id$ The Protracker Player Driver @@ -40,31 +40,35 @@ #include #endif +#include + #include "mikmod_internals.h" #ifdef SUNOS -extern int fprintf(FILE *, const char *, ...); +extern int fprintf(int, const char *, ...); extern long int random(void); #endif /* The currently playing module */ MODULE *pf = NULL; +#define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices) + #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, 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0, 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160, 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, 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, 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, @@ -76,7 +80,7 @@ static UBYTE avibtab[128]={ }; /* 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, 531381,530902,530423,529944,529466,528988,528511,528034, 527558,527082,526607,526131,525657,525183,524709,524236, @@ -176,7 +180,7 @@ static ULONG lintab[768]={ }; #define LOGFAC 2*16 -static UWORD logtab[104]={ +static const UWORD logtab[104]={ LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887, LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838, @@ -205,7 +209,7 @@ static UWORD logtab[104]={ 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, 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, @@ -225,12 +229,12 @@ static SBYTE PanbrelloTable[256]={ }; /* 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 - return random()&(ceil-1); +#if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA) + return random()&(ceilval-1); #else - return (rand()*ceil)/(RAND_MAX+1.0); + return (rand()*ceilval)/(RAND_MAX+1.0); #endif } @@ -246,14 +250,14 @@ static int MP_FindEmptyChannel(MODULE *mod) MP_VOICE *a; ULONG t,k,tvol,pp; - for (t=0;tvoice[t].main.kick==KICK_ABSENT)|| (mod->voice[t].main.kick==KICK_ENV))&& Voice_Stopped_internal(t)) return t; tvol=0xffffffUL;t=-1;a=mod->voice; - for (k=0;kmain.s) return k; @@ -325,9 +329,9 @@ static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed) { if (flags & UF_XMPERIODS) { if (flags & UF_LINEAR) - return getlinearperiod(note, speed); + return getlinearperiod(note, speed); else - return getlogperiod(note, speed); + return getlogperiod(note, speed); } else return getoldperiod(note, speed); } @@ -359,9 +363,15 @@ static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susen t->a=0; 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 */ 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 */ @@ -615,10 +625,10 @@ static void DoToneSlide(UWORD tick, MP_CONTROL *a) /* ...make tmpperiod equal tperiod */ a->tmpperiod=a->main.period=a->wantedperiod; else if (dist>0) { - a->tmpperiod-=a->portspeed; + a->tmpperiod-=a->portspeed; a->main.period-=a->portspeed; /* dist>0, slide up */ } else { - a->tmpperiod+=a->portspeed; + a->tmpperiod+=a->portspeed; a->main.period+=a->portspeed; /* dist<0, slide down */ } } else @@ -786,8 +796,8 @@ static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)tick; - (void)flags; + (void)tick; + (void)flags; dat = UniGetByte(); if (mod->panflag) @@ -799,16 +809,16 @@ static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)flags; - (void)mod; - (void)channel; + (void)flags; + (void)mod; + (void)channel; dat=UniGetByte(); if (!tick) { if (dat) a->soffset=(UWORD)dat<<8; 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.s->loopstart:a->main.s->length; } @@ -819,9 +829,9 @@ static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)flags; - (void)mod; - (void)channel; + (void)flags; + (void)mod; + (void)channel; dat=UniGetByte(); if (tick) @@ -842,14 +852,19 @@ static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)a; - (void)channel; + (void)a; + (void)channel; dat=UniGetByte(); if (tick || mod->patdly2) 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" */ if (dat == mod->sngpos && mod->patbrk == mod->patpos) return 0; @@ -857,8 +872,8 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR if (!mod->loop && !mod->patbrk && (dat < mod->sngpos || (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 pattern, after all... so: mod->patbrk=0; */ @@ -870,6 +885,9 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR mod->sngpos=dat; mod->posjmp=2; 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; @@ -878,15 +896,15 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)flags; - (void)mod; - (void)channel; + (void)flags; + (void)mod; + (void)channel; - dat=UniGetByte(); - if (tick) return 0; - if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */ - else if (dat>64) dat=64; - a->tmpvolume=dat; + dat=UniGetByte(); + if (tick) return 0; + if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */ + else if (dat>64) dat=64; + a->tmpvolume=dat; return 0; } @@ -894,29 +912,33 @@ static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; - (void)a; - (void)channel; + (void)a; + (void)channel; - dat=UniGetByte(); - if ((tick)||(mod->patdly2)) return 0; - if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&& - (dat>mod->pattrows[mod->positions[mod->sngpos]])) - dat=mod->pattrows[mod->positions[mod->sngpos]]; - mod->patbrk=dat; - if (!mod->posjmp) { - /* don't ask me to explain this code - it makes - backwards.s3m and children.xm (heretic's version) play - correctly, among others. Take that for granted, or write - the page of comments yourself... you might need some - aspirin - Miod */ - if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)|| - (mod->positions[mod->sngpos]==(mod->numpat-1) - && !(flags&UF_NOWRAP)))) { - mod->sngpos=0; - mod->posjmp=2; - } else - mod->posjmp=3; - } + dat=UniGetByte(); + 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)&& + (dat>mod->pattrows[mod->positions[mod->sngpos]])) { + dat=mod->pattrows[mod->positions[mod->sngpos]]; + } + mod->patbrk=dat; + if (!mod->posjmp) { + /* don't ask me to explain this code - it makes + backwards.s3m and children.xm (heretic's version) play + correctly, among others. Take that for granted, or write + the page of comments yourself... you might need some + aspirin - Miod */ + if ((mod->sngpos==mod->numpos-1)&&(dat)&& + ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) { + mod->sngpos=0; + mod->posjmp=2; + } else + mod->posjmp=3; + } return 0; } @@ -982,8 +1004,13 @@ static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, } else mod->patpos=a->pat_reppos; } else a->pat_reppos=POS_NONE; - } else + } else { 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; case 0x7: /* set tremolo waveform */ a->wavecontrol&=0x0f; @@ -1065,7 +1092,7 @@ static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR if (tick||mod->patdly2) return 0; if (mod->extspd&&(dat>=mod->bpmlimit)) mod->bpm=dat; - else + else if (dat) { mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat; mod->vbtick=0; @@ -1465,7 +1492,7 @@ static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR a->s3mvolslide = inf; else inf = a->s3mvolslide; - + if (tick) { lo=inf&0xf; hi=inf>>4; @@ -1608,7 +1635,7 @@ static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR INSTRUMENT *i=a->main.i; MP_VOICE *aout; - if ((aout=a->slave)) { + if ((aout=a->slave) != NULL) { if (aout->venv.env) { points=i->volenv[i->volpts-1].pos; aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos; @@ -1710,7 +1737,7 @@ static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat) /* if we don't come from another note, ignore the slide and play the note as is */ if (!a->oldnote || !a->main.period) - return; + return; if ((!tick)&&(a->newsamp)){ a->main.kick=KICK_NOTE; @@ -1725,15 +1752,15 @@ static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat) difference between those two values */ dist=a->main.period-a->wantedperiod; - /* if they are equal or if portamentospeed is too big... */ + /* if they are equal or if portamentospeed is too big... */ if ((!dist)||((a->portspeed<<2)>abs(dist))) /* ... make tmpperiod equal tperiod */ a->tmpperiod=a->main.period=a->wantedperiod; else - if (dist>0) { + if (dist>0) { a->tmpperiod-=a->portspeed<<2; a->main.period-=a->portspeed<<2; /* dist>0 slide up */ - } else { + } else { a->tmpperiod+=a->portspeed<<2; a->main.period+=a->portspeed<<2; /* dist<0 slide down */ } @@ -1762,7 +1789,7 @@ static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat) if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } if (!a->main.period) - return; + return; q=(a->vibpos>>2)&0x1f; @@ -1867,7 +1894,7 @@ static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR lo=inf&0xf; hi=inf>>4; - if (!hi) + if (!hi) a->main.chanvol-=lo; else if (!lo) { @@ -2105,13 +2132,13 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO switch (c) { case SS_GLISSANDO: /* S1x set glissando voice */ DoEEffects(tick, flags, a, mod, channel, 0x30|inf); - break; + break; case SS_FINETUNE: /* S2x set finetune */ DoEEffects(tick, flags, a, mod, channel, 0x50|inf); break; case SS_VIBWAVE: /* S3x set vibrato waveform */ DoEEffects(tick, flags, a, mod, channel, 0x40|inf); - break; + break; case SS_TREMWAVE: /* S4x set tremolo waveform */ DoEEffects(tick, flags, a, mod, channel, 0x70|inf); break; @@ -2130,13 +2157,13 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO case SS_SURROUND: /* S9x set surround sound */ if (mod->panflag) a->main.panning = mod->panning[channel] = PAN_SURROUND; - break; + break; case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */ if (!tick) { a->hioffset=inf<<16; 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.s->loopstart:a->main.s->length; } @@ -2168,10 +2195,10 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE c, inf; - (void)channel; - - c = UniGetByte(); - inf = UniGetByte(); + (void)channel; + + c = UniGetByte(); + inf = UniGetByte(); if ((!c)&&(!inf)) { c=a->voleffect; @@ -2219,16 +2246,16 @@ static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UWORD offset=UniGetWord(); - (void)tick; - (void)flags; - (void)mod; - (void)channel; + (void)tick; + (void)flags; + (void)mod; + (void)channel; if (offset) a->ultoffset=offset; 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.s->loopstart:a->main.s->length; @@ -2310,68 +2337,68 @@ static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD); static effect_func effects[UNI_LAST] = { - DoNothing, /* 0 */ - DoNothing, /* UNI_NOTE */ - DoNothing, /* UNI_INSTRUMENT */ - DoPTEffect0, /* UNI_PTEFFECT0 */ - DoPTEffect1, /* UNI_PTEFFECT1 */ - DoPTEffect2, /* UNI_PTEFFECT2 */ - DoPTEffect3, /* UNI_PTEFFECT3 */ - DoPTEffect4, /* UNI_PTEFFECT4 */ - DoPTEffect5, /* UNI_PTEFFECT5 */ - DoPTEffect6, /* UNI_PTEFFECT6 */ - DoPTEffect7, /* UNI_PTEFFECT7 */ - DoPTEffect8, /* UNI_PTEFFECT8 */ - DoPTEffect9, /* UNI_PTEFFECT9 */ - DoPTEffectA, /* UNI_PTEFFECTA */ - DoPTEffectB, /* UNI_PTEFFECTB */ - DoPTEffectC, /* UNI_PTEFFECTC */ - DoPTEffectD, /* UNI_PTEFFECTD */ - DoPTEffectE, /* UNI_PTEFFECTE */ - DoPTEffectF, /* UNI_PTEFFECTF */ - DoS3MEffectA, /* UNI_S3MEFFECTA */ - DoS3MEffectD, /* UNI_S3MEFFECTD */ - DoS3MEffectE, /* UNI_S3MEFFECTE */ - DoS3MEffectF, /* UNI_S3MEFFECTF */ - DoS3MEffectI, /* UNI_S3MEFFECTI */ - DoS3MEffectQ, /* UNI_S3MEFFECTQ */ - DoS3MEffectR, /* UNI_S3MEFFECTR */ - DoS3MEffectT, /* UNI_S3MEFFECTT */ - DoS3MEffectU, /* UNI_S3MEFFECTU */ - DoKeyOff, /* UNI_KEYOFF */ - DoKeyFade, /* UNI_KEYFADE */ - DoVolEffects, /* UNI_VOLEFFECTS */ - DoPTEffect4, /* UNI_XMEFFECT4 */ - DoXMEffect6, /* UNI_XMEFFECT6 */ - DoXMEffectA, /* UNI_XMEFFECTA */ - DoXMEffectE1, /* UNI_XMEFFECTE1 */ - DoXMEffectE2, /* UNI_XMEFFECTE2 */ - DoXMEffectEA, /* UNI_XMEFFECTEA */ - DoXMEffectEB, /* UNI_XMEFFECTEB */ - DoXMEffectG, /* UNI_XMEFFECTG */ - DoXMEffectH, /* UNI_XMEFFECTH */ - DoXMEffectL, /* UNI_XMEFFECTL */ - DoXMEffectP, /* UNI_XMEFFECTP */ - DoXMEffectX1, /* UNI_XMEFFECTX1 */ - DoXMEffectX2, /* UNI_XMEFFECTX2 */ - DoITEffectG, /* UNI_ITEFFECTG */ - DoITEffectH, /* UNI_ITEFFECTH */ - DoITEffectI, /* UNI_ITEFFECTI */ - DoITEffectM, /* UNI_ITEFFECTM */ - DoITEffectN, /* UNI_ITEFFECTN */ - DoITEffectP, /* UNI_ITEFFECTP */ - DoITEffectT, /* UNI_ITEFFECTT */ - DoITEffectU, /* UNI_ITEFFECTU */ - DoITEffectW, /* UNI_ITEFFECTW */ - DoITEffectY, /* UNI_ITEFFECTY */ - DoNothing, /* UNI_ITEFFECTZ */ - DoITEffectS0, /* UNI_ITEFFECTS0 */ - DoULTEffect9, /* UNI_ULTEFFECT9 */ - DoMEDSpeed, /* UNI_MEDSPEED */ - DoMEDEffectF1, /* UNI_MEDEFFECTF1 */ - DoMEDEffectF2, /* UNI_MEDEFFECTF2 */ - DoMEDEffectF3, /* UNI_MEDEFFECTF3 */ - DoOktArp, /* UNI_OKTARP */ + DoNothing, /* 0 */ + DoNothing, /* UNI_NOTE */ + DoNothing, /* UNI_INSTRUMENT */ + DoPTEffect0, /* UNI_PTEFFECT0 */ + DoPTEffect1, /* UNI_PTEFFECT1 */ + DoPTEffect2, /* UNI_PTEFFECT2 */ + DoPTEffect3, /* UNI_PTEFFECT3 */ + DoPTEffect4, /* UNI_PTEFFECT4 */ + DoPTEffect5, /* UNI_PTEFFECT5 */ + DoPTEffect6, /* UNI_PTEFFECT6 */ + DoPTEffect7, /* UNI_PTEFFECT7 */ + DoPTEffect8, /* UNI_PTEFFECT8 */ + DoPTEffect9, /* UNI_PTEFFECT9 */ + DoPTEffectA, /* UNI_PTEFFECTA */ + DoPTEffectB, /* UNI_PTEFFECTB */ + DoPTEffectC, /* UNI_PTEFFECTC */ + DoPTEffectD, /* UNI_PTEFFECTD */ + DoPTEffectE, /* UNI_PTEFFECTE */ + DoPTEffectF, /* UNI_PTEFFECTF */ + DoS3MEffectA, /* UNI_S3MEFFECTA */ + DoS3MEffectD, /* UNI_S3MEFFECTD */ + DoS3MEffectE, /* UNI_S3MEFFECTE */ + DoS3MEffectF, /* UNI_S3MEFFECTF */ + DoS3MEffectI, /* UNI_S3MEFFECTI */ + DoS3MEffectQ, /* UNI_S3MEFFECTQ */ + DoS3MEffectR, /* UNI_S3MEFFECTR */ + DoS3MEffectT, /* UNI_S3MEFFECTT */ + DoS3MEffectU, /* UNI_S3MEFFECTU */ + DoKeyOff, /* UNI_KEYOFF */ + DoKeyFade, /* UNI_KEYFADE */ + DoVolEffects, /* UNI_VOLEFFECTS */ + DoPTEffect4, /* UNI_XMEFFECT4 */ + DoXMEffect6, /* UNI_XMEFFECT6 */ + DoXMEffectA, /* UNI_XMEFFECTA */ + DoXMEffectE1, /* UNI_XMEFFECTE1 */ + DoXMEffectE2, /* UNI_XMEFFECTE2 */ + DoXMEffectEA, /* UNI_XMEFFECTEA */ + DoXMEffectEB, /* UNI_XMEFFECTEB */ + DoXMEffectG, /* UNI_XMEFFECTG */ + DoXMEffectH, /* UNI_XMEFFECTH */ + DoXMEffectL, /* UNI_XMEFFECTL */ + DoXMEffectP, /* UNI_XMEFFECTP */ + DoXMEffectX1, /* UNI_XMEFFECTX1 */ + DoXMEffectX2, /* UNI_XMEFFECTX2 */ + DoITEffectG, /* UNI_ITEFFECTG */ + DoITEffectH, /* UNI_ITEFFECTH */ + DoITEffectI, /* UNI_ITEFFECTI */ + DoITEffectM, /* UNI_ITEFFECTM */ + DoITEffectN, /* UNI_ITEFFECTN */ + DoITEffectP, /* UNI_ITEFFECTP */ + DoITEffectT, /* UNI_ITEFFECTT */ + DoITEffectU, /* UNI_ITEFFECTU */ + DoITEffectW, /* UNI_ITEFFECTW */ + DoITEffectY, /* UNI_ITEFFECTY */ + DoNothing, /* UNI_ITEFFECTZ */ + DoITEffectS0, /* UNI_ITEFFECTS0 */ + DoULTEffect9, /* UNI_ULTEFFECT9 */ + DoMEDSpeed, /* UNI_MEDSPEED */ + DoMEDEffectF1, /* UNI_MEDEFFECTF1 */ + DoMEDEffectF2, /* UNI_MEDEFFECTF2 */ + DoMEDEffectF3, /* UNI_MEDEFFECTF3 */ + DoOktArp, /* UNI_OKTARP */ }; static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a) @@ -2382,10 +2409,14 @@ static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a) int explicitslides = 0; 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]; if (f != DoNothing) - a->sliding = 0; + a->sliding = 0; explicitslides |= f(tick, flags, a, mod, channel); } return explicitslides; @@ -2396,17 +2427,17 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat) int t; MP_VOICE *aout; - dat&=0xf; + dat&=0xf; aout=(a->slave)?a->slave:NULL; switch (dat) { case 0x0: /* past note cut */ - for (t=0;tvoice[t].master==a) mod->voice[t].main.fadevol=0; break; case 0x1: /* past note off */ - for (t=0;tvoice[t].master==a) { mod->voice[t].main.keyoff|=KEY_OFF; if ((!(mod->voice[t].venv.flg & EF_ON))|| @@ -2415,7 +2446,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat) } break; case 0x2: /* past note fade */ - for (t=0;tvoice[t].master==a) mod->voice[t].main.keyoff|=KEY_FADE; break; @@ -2427,7 +2458,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat) break; case 0x5: /* set NNA note off */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF; - break; + break; case 0x6: /* set NNA note fade */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE; break; @@ -2442,7 +2473,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat) case 0x9: /* disable panning envelope */ if (aout) aout->main.panflg&=~EF_ON; - break; + break; case 0xa: /* enable panning envelope */ if (aout) aout->main.panflg|=EF_ON; @@ -2470,7 +2501,7 @@ static void pt_UpdateVoices(MODULE *mod, int max_volume) SAMPLE *s; mod->totalchn=mod->realchn=0; - for (channel=0;channelvoice[channel]; i=aout->main.i; 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)) { 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->aswppos=0; } @@ -2687,7 +2718,7 @@ static void pt_Notes(MODULE *mod) UniSetRow(a->row); funky=0; - while((c=UniGetByte())) + while((c=UniGetByte()) != 0) switch (c) { case UNI_NOTE: funky|=1; @@ -2720,7 +2751,7 @@ static void pt_Notes(MODULE *mod) INSTRUMENT *i; SAMPLE *s; - if ((i=a->main.i)) { + if ((i=a->main.i) != NULL) { if (i->samplenumber[a->anote] >= mod->numsmp) continue; s=&mod->samples[i->samplenumber[a->anote]]; a->main.note=i->samplenote[a->anote]; @@ -2809,7 +2840,7 @@ static void pt_EffectsPass1(MODULE *mod) for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; - if ((aout=a->slave)) { + if ((aout=a->slave) != NULL) { a->main.fadevol=aout->main.fadevol; a->main.period=aout->main.period; if (a->main.kick==KICK_KEYOFF) @@ -2891,7 +2922,7 @@ static void pt_NNA(MODULE *mod) if (a->dct!=DCT_OFF) { int t; - for (t=0;tvoice[t].masterchn==channel)&& (a->main.sample==mod->voice[t].main.sample)) { @@ -2951,11 +2982,11 @@ static void pt_SetupVoices(MODULE *mod) if ((newchn=MP_FindEmptyChannel(mod))!=-1) a->slave=&mod->voice[a->slavechn=newchn]; } - } else + } else a->slave=&mod->voice[a->slavechn=channel]; /* 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; aout->master=a; a->slave=aout; @@ -2984,7 +3015,7 @@ static void pt_EffectsPass2(MODULE *mod) if (!a->row) continue; UniSetRow(a->row); - while((c=UniGetByte())) + while((c=UniGetByte()) != 0) if (c==UNI_ITEFFECTS0) { c=UniGetByte(); if ((c>>4)==SS_S7EFFECTS) @@ -3016,7 +3047,7 @@ void Player_HandleTick(void) pf->sngremainder%=pf->bpm; if (++pf->vbtick>=pf->sngspd) { - if (pf->pat_repcrazy) + if (pf->pat_repcrazy) pf->pat_repcrazy=0; /* play 2 times row 0 */ else pf->patpos++; @@ -3046,6 +3077,9 @@ void Player_HandleTick(void) pf->control[channel].pat_reppos=-1; 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 *inside* the module in some formats */ if ((pf->sngpos>=pf->numpos)|| @@ -3060,7 +3094,6 @@ void Player_HandleTick(void) pf->bpm=pf->inittempo<32?32:pf->inittempo; } } - if (pf->sngpos<0) pf->sngpos=pf->numpos-1; } if (!pf->patdly2) @@ -3093,7 +3126,7 @@ static void Player_Init_internal(MODULE* mod) mod->control[t].main.chanvol=mod->chanvol[t]; mod->control[t].main.panning=mod->panning[t]; } - + mod->sngtime=0; mod->sngremainder=0; @@ -3133,6 +3166,11 @@ int Player_Init(MODULE* mod) if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE)))) 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); return 0; } @@ -3148,10 +3186,8 @@ void Player_Exit_internal(MODULE* mod) pf=NULL; } - if (mod->control) - MikMod_free(mod->control); - if (mod->voice) - MikMod_free(mod->voice); + MikMod_free(mod->control); + MikMod_free(mod->voice); mod->control=NULL; mod->voice=NULL; } @@ -3166,8 +3202,10 @@ void Player_Exit(MODULE* mod) MIKMODAPI void Player_SetVolume(SWORD volume) { MUTEX_LOCK(vars); - if (pf) + if (pf) { pf->volume=(volume<0)?0:(volume>128)?128:volume; + pf->initvolume=pf->volume; + } MUTEX_UNLOCK(vars); } @@ -3241,7 +3279,7 @@ MIKMODAPI void Player_NextPosition(void) pf->patbrk=0; pf->vbtick=pf->sngspd; - for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; @@ -3266,7 +3304,7 @@ MIKMODAPI void Player_PrevPosition(void) pf->patbrk=0; pf->vbtick=pf->sngspd; - for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; @@ -3293,7 +3331,7 @@ MIKMODAPI void Player_SetPosition(UWORD pos) pf->sngpos=pos; pf->vbtick=pf->sngspd; - for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; @@ -3303,12 +3341,12 @@ MIKMODAPI void Player_SetPosition(UWORD pos) pf->control[t].main.s=NULL; } pf->forbid=0; - + if (!pos) Player_Init_internal(pf); } MUTEX_UNLOCK(vars); -} +} static void Player_Unmute_internal(SLONG arg1,va_list ap) { @@ -3418,7 +3456,7 @@ static void Player_ToggleMute_internal(SLONG arg1,va_list ap) } break; default: - if (arg1numchn) + if (arg1numchn) pf->control[arg1].muted=1-pf->control[arg1].muted; break; } @@ -3465,7 +3503,7 @@ MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan) UWORD result=0; MUTEX_LOCK(vars); - if (pf) + if (pf) result=(channumchn)?pf->control[chan].main.period:0; MUTEX_UNLOCK(vars); @@ -3499,7 +3537,7 @@ MIKMODAPI void Player_TogglePause(void) MIKMODAPI void Player_SetSpeed(UWORD speed) { MUTEX_LOCK(vars); - if (pf) + if (pf) pf->sngspd=speed?(speed<32?speed:32):1; MUTEX_UNLOCK(vars); } @@ -3538,18 +3576,17 @@ MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo) return numvoices; } - -// Get current module order +/* Get current module order */ MIKMODAPI int Player_GetOrder(void) { int ret; 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); return ret; } -// Get current module row +/* Get current module row */ MIKMODAPI int Player_GetRow(void) { int ret; @@ -3559,5 +3596,4 @@ MIKMODAPI int Player_GetRow(void) return ret; } - /* ex:set ts=4: */ diff --git a/apps/plugins/mikmod/munitrk.c b/apps/plugins/mikmod/munitrk.c index f0a8f58af7..72e7de4e7e 100644 --- a/apps/plugins/mikmod/munitrk.c +++ b/apps/plugins/mikmod/munitrk.c @@ -6,12 +6,12 @@ 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 @@ -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 @@ -37,7 +37,7 @@ /* Unibuffer chunk size */ #define BUFPAGE 128 -UWORD unioperands[UNI_LAST]={ +const UWORD unioperands[UNI_LAST] = { 0, /* not used */ 1, /* UNI_NOTE */ 1, /* UNI_INSTRUMENT */ @@ -214,7 +214,7 @@ static int UniExpand(int wanted) unibuf = newbuf; unimax+=BUFPAGE; return 1; - } else + } else return 0; } return 1; @@ -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; @@ -275,15 +275,15 @@ void UniNewline(void) stream. */ UBYTE* UniDup(void) { - UBYTE *d; + void *d; - if (!UniExpand(unitt-unipc)) return NULL; + if (!UniExpand(unipc-unitt)) return NULL; unibuf[unitt] = 0; - if(!(d=(UBYTE *)MikMod_malloc(unipc))) return NULL; + if(!(d=MikMod_malloc(unipc))) return NULL; memcpy(d,unibuf,unipc); - return d; + return (UBYTE *)d; } int UniInit(void) @@ -296,7 +296,7 @@ int UniInit(void) void UniCleanup(void) { - if(unibuf) MikMod_free(unibuf); + MikMod_free(unibuf); unibuf = NULL; } diff --git a/apps/plugins/mikmod/npertab.c b/apps/plugins/mikmod/npertab.c index 4aa5ef9a17..b106b2adf8 100644 --- a/apps/plugins/mikmod/npertab.c +++ b/apps/plugins/mikmod/npertab.c @@ -6,12 +6,12 @@ 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 @@ -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. @@ -32,7 +32,7 @@ #include "mikmod_internals.h" -UWORD npertab[7 * OCTAVE] = { +const UWORD npertab[7 * OCTAVE] = { /* Octaves 6 -> 0 */ /* C C# D D# E F F# G G# A A# B */ 0x6b0,0x650,0x5f4,0x5a0,0x54c,0x500,0x4b8,0x474,0x434,0x3f8,0x3c0,0x38a, diff --git a/apps/plugins/mikmod/sloader.c b/apps/plugins/mikmod/sloader.c index 8c1070cba1..af7f623799 100644 --- a/apps/plugins/mikmod/sloader.c +++ b/apps/plugins/mikmod/sloader.c @@ -6,12 +6,12 @@ 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 @@ -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 provided by the "registered" sample loader. @@ -56,7 +56,7 @@ typedef struct ITPACK { int SL_Init(SAMPLOAD* s) { 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; if(s->infmt & SF_16BITS) sl_rlength>>=1; @@ -68,16 +68,15 @@ int SL_Init(SAMPLOAD* s) void SL_Exit(SAMPLOAD *s) { if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR); - if(sl_buffer) { - MikMod_free(sl_buffer); - sl_buffer=NULL; - } + + MikMod_free(sl_buffer); + sl_buffer=NULL; } /* 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 bits = status->bits; 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->last = last; status->buf = buf; - return (dest-sl_buffer); + return (dest-out); } /* 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; UWORD bits = status->bits; UWORD bufbits = status->bufbits; @@ -219,7 +218,7 @@ static int read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD status->bufbits = bufbits; status->last = last; 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) @@ -231,9 +230,11 @@ static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor int result,c_block=0; /* compression bytes until next block */ ITPACK status; UWORD incnt = 0; - - memset(&status, 0, sizeof(status)); /* initialize status */ - + + status.buf = 0; + status.last = 0; + status.bufbits = 0; + status.bits = 0; while(length) { stodo=(lengthRead(reader,sl_buffer,sizeof(SBYTE)*stodo); src = (SBYTE*)sl_buffer; dest = sl_buffer; @@ -288,7 +297,7 @@ static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor sl_old = sl_buffer[t]; } - if((infmt^outfmt) & SF_SIGNED) + if((infmt^outfmt) & SF_SIGNED) for(t=0;tinfmt,smp->outfmt,smp->scalefactor, - length,smp->reader,0); + length,smp->reader,0); } /* Registers a sample for loading when SL_LoadSamples() is called. */ @@ -357,7 +366,7 @@ SAMPLOAD* SL_RegisterSample(SAMPLE* s,int type,MREADER* reader) cruise = sndfxlist; } else return NULL; - + /* Allocate and add structure to the END of the list */ if(!(news=(SAMPLOAD*)MikMod_malloc(sizeof(SAMPLOAD)))) return NULL; @@ -407,7 +416,7 @@ static ULONG SampleTotal(SAMPLOAD* samplist,int type) static ULONG RealSpeed(SAMPLOAD *s) { return(s->sample->speed/(s->scalefactor?s->scalefactor:1)); -} +} static int DitherSamples(SAMPLOAD* samplist,int type) { @@ -417,7 +426,7 @@ static int DitherSamples(SAMPLOAD* samplist,int type) if(!samplist) return 0; - if((maxsize=MD_SampleSpace(type)*1024)) + if((maxsize=MD_SampleSpace(type)*1024) != 0) while(SampleTotal(samplist,type)>maxsize) { /* First Pass - check for any 16 bit samples */ s = samplist; @@ -473,15 +482,15 @@ static int DitherSamples(SAMPLOAD* samplist,int type) int SL_LoadSamples(void) { - int ok; + int rc; _mm_critical = 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; - return ok; + return rc; } void SL_Sample16to8(SAMPLOAD* s) @@ -518,5 +527,4 @@ void SL_HalveSample(SAMPLOAD* s,int factor) s->sample->loopend = s->loopend / s->scalefactor; } - /* ex:set ts=4: */ diff --git a/apps/plugins/mikmod/virtch.c b/apps/plugins/mikmod/virtch.c index 6e8174016c..f2fd528b00 100644 --- a/apps/plugins/mikmod/virtch.c +++ b/apps/plugins/mikmod/virtch.c @@ -6,12 +6,12 @@ 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 @@ -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. @@ -33,28 +33,23 @@ (b) Interpolation of sample data during mixing (c) Dolby Surround Sound */ -#if 0 -#include -#endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" -#include "mikmod.h" /* Constant definitions ==================== - BITSHIFT + BITSHIFT Controls the maximum volume of the sound output. All data is shifted right by BITSHIFT after being mixed. Higher values result in quieter sound and less chance of distortion. @@ -130,164 +125,176 @@ static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, #else #define NATIVE SLONG #endif + #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; SLONG lvolsel = vnf->lvolsel; while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *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 sample; SLONG remain = todo; - // Dest can be misaligned ... + /* Dest can be misaligned */ while(!IS_ALIGNED_16(dest)) { - sample=srce[(index += increment) >> FRACBITS]; + sample=srce[idx >> FRACBITS]; + idx += increment; *dest++ += vol[0] * sample; *dest++ += vol[1] * sample; todo--; + if(!todo) return idx; } - // Srce is always aligned ... + /* Srce is always aligned */ #if defined HAVE_SSE2 - remain = todo&3; + remain = todo&3; { - __m128i v0 = _mm_set_epi16(0, vol[1], - 0, vol[0], - 0, vol[1], - 0, vol[0]); + __m128i v0 = _mm_set_epi16(0, vol[1], + 0, vol[0], + 0, vol[1], + 0, vol[0]); for(todo>>=2;todo; todo--) { - SWORD s0 = srce[(index += increment) >> FRACBITS]; - SWORD s1 = srce[(index += increment) >> FRACBITS]; - SWORD s2 = srce[(index += increment) >> FRACBITS]; - SWORD s3 = srce[(index += increment) >> FRACBITS]; + SWORD s0 = srce[idx >> FRACBITS]; + SWORD s1 = srce[(idx += increment) >> FRACBITS]; + SWORD s2 = srce[(idx += increment) >> FRACBITS]; + SWORD s3 = srce[(idx += increment) >> FRACBITS]; __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 v3 = _mm_load_si128((__m128i*)(dest+0)); __m128i v4 = _mm_load_si128((__m128i*)(dest+4)); _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))); - dest+=8; + dest+=8; + idx += increment; } } #elif defined HAVE_ALTIVEC 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]; - + 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--) { - // Load constants - s[0] = srce[(index += increment) >> FRACBITS]; - s[1] = srce[(index += increment) >> FRACBITS]; - s[2] = srce[(index += increment) >> FRACBITS]; - s[3] = srce[(index += increment) >> FRACBITS]; + vector short int r1; + vector signed short v1, v2; + vector signed int v3, v4, v5, v6; + + /* 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; - - vector short int r1 = vec_ld(0, s); - vector signed short v1 = vec_perm(r1, r1, (vector unsigned char)(0*2, 0*2+1, // s0 - 4*2, 4*2+1, // 0 - 0*2, 0*2+1, // s0 - 4*2, 4*2+1, // 0 - 1*2, 1*2+1, // s1 - 4*2, 4*2+1, // 0 - 1*2, 1*2+1, // s1 - 4*2, 4*2+1 // 0 - )); - - vector signed short 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 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); + + r1 = vec_ld(0, s); + v1 = vec_perm(r1, r1, (vector unsigned char) + (0*2, 0*2+1, /* s0 */ + 4*2, 4*2+1, /* 0 */ + 0*2, 0*2+1, /* s0 */ + 4*2, 4*2+1, /* 0 */ + 1*2, 1*2+1, /* s1 */ + 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 */ + ) ); + + v3 = vec_ld(0, dest); + v4 = vec_ld(0, dest + 4); + v5 = vec_mule(v0, v1); + v6 = vec_mule(v0, v2); + + vec_st(vec_add(v3, v5), 0, dest); vec_st(vec_add(v4, v6), 0x10, dest); dest+=8; + idx += increment; } } -#endif // HAVE_ALTIVEC +#endif /* HAVE_ALTIVEC */ - // Remaining bits ... + /* Remaining bits */ while(remain--) { - sample=srce[(index += increment) >> FRACBITS]; + sample=srce[idx >> FRACBITS]; + idx += increment; *dest++ += vol[0] * sample; *dest++ += vol[1] * sample; } - return index; + return idx; } #endif /*========== 32 bit sample mixers - only for 32 bit platforms */ #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 (md_mode & DMODE_SIMDMIXER) - { - return MixSIMDMonoNormal(srce, dest, index, increment, todo); + if (md_mode & DMODE_SIMDMIXER) { + return MixSIMDMonoNormal(srce, dest, idx, increment, todo); } else #endif { SWORD sample; SLONG lvolsel = vnf->lvolsel; - + while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; - + sample = srce[idx >> FRACBITS]; + idx += increment; + *dest++ += lvolsel * sample; } } - return index; + return idx; } -// FIXME: This mixer should works also on 64-bit platform -// Hint : changes SLONG / SLONGLONG mess with size_t -static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) +/* FIXME: This mixer should works also on 64-bit platform */ +/* Hint : changes SLONG / SLONGLONG mess with intptr */ +static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo) { #if defined HAVE_ALTIVEC || defined HAVE_SSE2 - if (md_mode & DMODE_SIMDMIXER) - { - return MixSIMDStereoNormal(srce, dest, index, increment, todo); + if (md_mode & DMODE_SIMDMIXER) { + return MixSIMDStereoNormal(srce, dest, idx, increment, todo); } else #endif @@ -297,17 +304,17 @@ static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG i SLONG rvolsel = vnf->rvolsel; while(todo--) { - sample=srce[(index += increment) >> FRACBITS]; + sample=srce[idx >> FRACBITS]; + idx += increment; *dest++ += lvolsel * sample; *dest++ += rvolsel * sample; } } - return index; + return idx; } - -static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) +static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; @@ -315,25 +322,26 @@ static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG if (lvolsel>=rvolsel) { while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *dest++ += lvolsel*sample; *dest++ -= lvolsel*sample; } - } else { + } + else { while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *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 lvolsel = vnf->lvolsel; @@ -342,33 +350,33 @@ static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG inc if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) - * sample >> CLICK_SHIFT; + * sample >> CLICK_SHIFT; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *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 lvolsel = vnf->lvolsel; @@ -379,13 +387,13 @@ static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG i SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) - * sample >> CLICK_SHIFT; + * sample >> CLICK_SHIFT; *dest++ += ((rvolsel << CLICK_SHIFT) + oldrvol * rampvol) * sample >> CLICK_SHIFT; if (!--rampvol) @@ -393,22 +401,22 @@ static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG i } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += lvolsel * 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 lvolsel = vnf->lvolsel; @@ -427,13 +435,13 @@ static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG if (rampvol) { oldvol -= vol; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; sample=((vol << CLICK_SHIFT) + oldvol * rampvol) - * sample >> CLICK_SHIFT; + * sample >> CLICK_SHIFT; *dest++ += sample; *dest++ -= sample; @@ -442,55 +450,55 @@ static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += vol*sample; *dest++ -= vol*sample; } - return index; + return idx; } #endif /*========== 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; SLONG lvolsel = vnf->lvolsel; while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *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; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; while(todo--) { - sample=srce[index >> FRACBITS]; - index += increment; + sample=srce[idx >> FRACBITS]; + idx += increment; *dest++ += lvolsel * 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; SLONG lvolsel = vnf->lvolsel; @@ -498,25 +506,26 @@ static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG index if(vnf->lvolsel>=vnf->rvolsel) { while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *dest++ += lvolsel*sample; *dest++ -= lvolsel*sample; } - } else { + } + else { while(todo--) { - sample = srce[index >> FRACBITS]; - index += increment; + sample = srce[idx >> FRACBITS]; + idx += increment; *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 lvolsel = vnf->lvolsel; @@ -525,10 +534,10 @@ static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLO if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; @@ -537,21 +546,21 @@ static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLO } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *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 lvolsel = vnf->lvolsel; @@ -562,10 +571,10 @@ static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,S SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; @@ -576,22 +585,22 @@ static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,S } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += lvolsel * 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 lvolsel = vnf->lvolsel; @@ -610,13 +619,13 @@ static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index if (rampvol) { oldvol -= vol; while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; sample=((vol << CLICK_SHIFT) + oldvol * rampvol) - * sample >> CLICK_SHIFT; + * sample >> CLICK_SHIFT; *dest++ += sample; *dest++ -= sample; if (!--rampvol) @@ -624,19 +633,19 @@ static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index } vnf->rampvol = rampvol; if (todo < 0) - return index; + return idx; } while(todo--) { - sample=(SLONG)srce[index>>FRACBITS]+ - ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) - *(index&FRACMASK)>>FRACBITS); - index += increment; + sample=(SLONG)srce[idx>>FRACBITS]+ + ((SLONG)(srce[(idx>>FRACBITS)+1]-srce[idx>>FRACBITS]) + *(idx&FRACMASK)>>FRACBITS); + idx += increment; *dest++ += vol*sample; *dest++ -= vol*sample; } - return index; + return idx; } static void (*MixReverb)(SLONG* srce,NATIVE count); @@ -673,7 +682,7 @@ static void MixReverb_Normal(SLONG* srce,NATIVE count) /* left channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ - RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; + RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; } } @@ -710,10 +719,10 @@ static void MixReverb_Stereo(SLONG* srce,NATIVE count) /* left channel then right channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ - RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; + RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ - RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; + RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; } } @@ -839,58 +848,56 @@ static void Mix32To8(SBYTE* dste,const SLONG *srce,NATIVE count) #if defined HAVE_ALTIVEC || defined HAVE_SSE2 -// Mix 32bit input to floating point. 32 samples per iteration -// PC: ?, Mac OK -static void Mix32ToFP_SIMD(float* dste,SLONG* srce,NATIVE count) +/* Mix 32bit input to floating point. 32 samples per iteration */ +/* PC: ?, Mac OK */ +static void Mix32ToFP_SIMD(float* dste,const SLONG* srce,NATIVE count) { - int remain=count; + const float k = ((1.0f / 32768.0f) / (1 << FP_SHIFT)); + int remain=count; + simd_m128 x1, x2, xk; while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce)) { - float x1; - EXTRACT_SAMPLE_FP(x1,FP_SHIFT); - CHECK_SAMPLE_FP(x1,1.0f); - PUT_SAMPLE_FP(x1); + float xf; + EXTRACT_SAMPLE_FP(xf,FP_SHIFT); + CHECK_SAMPLE_FP(xf,1.0f); + PUT_SAMPLE_FP(xf); count--; - if (!count) - { - return; - } + if (!count) return; } - remain = count&7; - - const float k = ((1.0f / 32768.0f) / (1 << FP_SHIFT)); - simd_m128 x1, x2; - simd_m128 xk = LOAD_PS1_SIMD(&k); // Scale factor + remain = count&7; + + xk = LOAD_PS1_SIMD(&k); /* Scale factor */ for(count>>=3;count;count--) { - 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 - PUT_SAMPLE_SIMD_F(dste, x1); // Store 4 samples - PUT_SAMPLE_SIMD_F(dste+4, x2); // Store 4 samples - srce+=8; - dste+=8; - } + 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 */ + PUT_SAMPLE_SIMD_F(dste, x1); /* Store 4 samples */ + PUT_SAMPLE_SIMD_F(dste+4, x2); /* Store 4 samples */ + srce+=8; + dste+=8; + } if (remain&4) { - EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); // Load 4 samples - PUT_SAMPLE_SIMD_F(dste, x1); // Store 4 samples - srce+=4; - dste+=4; - remain &= 3; - } + EXTRACT_SAMPLE_SIMD_F(srce, x1, FP_SHIFT, xk); /* Load 4 samples */ + PUT_SAMPLE_SIMD_F(dste, x1); /* Store 4 samples */ + srce+=4; + dste+=4; + remain &= 3; + } while(remain--) { - float x1; - EXTRACT_SAMPLE_FP(x1,FP_SHIFT); - CHECK_SAMPLE_FP(x1,1.0f); - PUT_SAMPLE_FP(x1); + float xf; + EXTRACT_SAMPLE_FP(xf,FP_SHIFT); + CHECK_SAMPLE_FP(xf,1.0f); + 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; while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce)) @@ -900,34 +907,31 @@ static void Mix32To16_SIMD(SWORD* dste,SLONG* srce,NATIVE count) CHECK_SAMPLE(x1,32768); PUT_SAMPLE(x1); count--; - if (!count) - { - return; - } + if (!count) return; } remain = count&7; - for(count>>=3;count;count--) + for(count>>=3;count;count--) { simd_m128i x1,x2; - EXTRACT_SAMPLE_SIMD_16(srce, x1); // Load 4 samples - EXTRACT_SAMPLE_SIMD_16(srce+4, x2); // Load 4 samples - PUT_SAMPLE_SIMD_W(dste, x1, x2); // Store 8 samples + EXTRACT_SAMPLE_SIMD_16(srce, x1); /* Load 4 samples */ + EXTRACT_SAMPLE_SIMD_16(srce+4, x2); /* Load 4 samples */ + PUT_SAMPLE_SIMD_W(dste, x1, x2); /* Store 8 samples */ srce+=8; dste+=8; } if (remain) - Mix32To16(dste, srce, remain); + Mix32To16(dste, srce, remain); } -// Mix 32bit input to 8bit. 128 samples per iteration -// PC:OK, Mac: Ok -static void Mix32To8_SIMD(SBYTE* dste,SLONG* srce,NATIVE count) -{ +/* Mix 32bit input to 8bit. 128 samples per iteration */ +/* PC:OK, Mac: Ok */ +static void Mix32To8_SIMD(SBYTE* dste,const SLONG* srce,NATIVE count) +{ int remain=count; - + while(!IS_ALIGNED_16(dste) || !IS_ALIGNED_16(srce)) { SWORD x1; @@ -935,32 +939,29 @@ static void Mix32To8_SIMD(SBYTE* dste,SLONG* srce,NATIVE count) CHECK_SAMPLE(x1,128); PUT_SAMPLE(x1+128); count--; - if (!count) - { - return; - } + if (!count) return; } - + remain = count&15; for(count>>=4;count;count--) { - simd_m128i x1,x2,x3,x4; - EXTRACT_SAMPLE_SIMD_8(srce, x1); // 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+12, x4); // Load 4 samples - PUT_SAMPLE_SIMD_B(dste, x1, x2, x3, x4); // Store 16 samples - srce+=16; - dste+=16; + simd_m128i x1,x2,x3,x4; + EXTRACT_SAMPLE_SIMD_8(srce, x1); /* 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+12, x4); /* Load 4 samples */ + PUT_SAMPLE_SIMD_B(dste, x1, x2, x3, x4); /* Store 16 samples */ + srce+=16; + dste+=16; } + if (remain) - Mix32To8(dste, srce, remain); + Mix32To8(dste, srce, remain); } #endif - static void AddChannel(SLONG* ptr,NATIVE todo) { SLONGLONG end,done; @@ -1050,65 +1051,64 @@ static void AddChannel(SLONG* ptr,NATIVE todo) if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=Mix32SurroundInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); else vnf->current=Mix32StereoInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=Mix32MonoInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } else if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=Mix32SurroundNormal - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); else { #if defined HAVE_ALTIVEC || defined HAVE_SSE2 - if (md_mode & DMODE_SIMDMIXER) + if (md_mode & DMODE_SIMDMIXER) vnf->current=MixSIMDStereoNormal - (s,ptr,vnf->current,vnf->increment,done); - - else + (s,ptr,vnf->current,vnf->increment,done); + else #endif vnf->current=Mix32StereoNormal - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } } else vnf->current=Mix32MonoNormal - (s,ptr,vnf->current,vnf->increment,done); - } else + (s,ptr,vnf->current,vnf->increment,done); + } + else #endif - { + { if((md_mode & DMODE_INTERP)) { if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=MixSurroundInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); else vnf->current=MixStereoInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=MixMonoInterp - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } else if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=MixSurroundNormal - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); else { #if defined HAVE_ALTIVEC || defined HAVE_SSE2 - if (md_mode & DMODE_SIMDMIXER) + if (md_mode & DMODE_SIMDMIXER) vnf->current=MixSIMDStereoNormal - (s,ptr,vnf->current,vnf->increment,done); - - else + (s,ptr,vnf->current,vnf->increment,done); + else #endif vnf->current=MixStereoNormal - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } } else vnf->current=MixMonoNormal - (s,ptr,vnf->current,vnf->increment,done); + (s,ptr,vnf->current,vnf->increment,done); } } else /* update sample position */ @@ -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_ #include "virtch_common.c" #undef _IN_VIRTCH_ @@ -1190,7 +1217,6 @@ void VC1_WriteSamples(SBYTE* buf,ULONG todo) vc_callback((unsigned char*)vc_tickbuf, portion); } - #if defined HAVE_ALTIVEC || defined HAVE_SSE2 if (md_mode & DMODE_SIMDMIXER) { @@ -1219,20 +1245,23 @@ void VC1_WriteSamples(SBYTE* buf,ULONG todo) int VC1_Init(void) { +#ifndef NO_HQMIXER VC_SetupPointers(); - - //if (md_mode&DMODE_HQMIXER) - // return VC2_Init(); - if(!(Samples=(SWORD**)MikMod_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) { + if (md_mode&DMODE_HQMIXER) + return VC2_Init(); +#endif + + if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } - if(!vc_tickbuf) - if(!(vc_tickbuf=(SLONG*)MikMod_malloc((TICKLSIZE+32)*sizeof(SLONG)))) { + if(!vc_tickbuf) { + if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } + } MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal; MixLowPass=(md_mode&DMODE_STEREO)?MixLowPass_Stereo:MixLowPass_Normal; @@ -1264,14 +1293,17 @@ int VC1_PlayStart(void) if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+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(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; - if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; - if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+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(!(RVbufR8=(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(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; + if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; + if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; + if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+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(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; + } RVRindex = 0; return 0; @@ -1279,23 +1311,23 @@ int VC1_PlayStart(void) void VC1_PlayStop(void) { - if(RVbufL1) MikMod_free(RVbufL1); - if(RVbufL2) MikMod_free(RVbufL2); - if(RVbufL3) MikMod_free(RVbufL3); - if(RVbufL4) MikMod_free(RVbufL4); - if(RVbufL5) MikMod_free(RVbufL5); - if(RVbufL6) MikMod_free(RVbufL6); - if(RVbufL7) MikMod_free(RVbufL7); - if(RVbufL8) MikMod_free(RVbufL8); + MikMod_free(RVbufL1); + MikMod_free(RVbufL2); + MikMod_free(RVbufL3); + MikMod_free(RVbufL4); + MikMod_free(RVbufL5); + MikMod_free(RVbufL6); + MikMod_free(RVbufL7); + MikMod_free(RVbufL8); RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; - if(RVbufR1) MikMod_free(RVbufR1); - if(RVbufR2) MikMod_free(RVbufR2); - if(RVbufR3) MikMod_free(RVbufR3); - if(RVbufR4) MikMod_free(RVbufR4); - if(RVbufR5) MikMod_free(RVbufR5); - if(RVbufR6) MikMod_free(RVbufR6); - if(RVbufR7) MikMod_free(RVbufR7); - if(RVbufR8) MikMod_free(RVbufR8); + MikMod_free(RVbufR1); + MikMod_free(RVbufR2); + MikMod_free(RVbufR3); + MikMod_free(RVbufR4); + MikMod_free(RVbufR5); + MikMod_free(RVbufR6); + MikMod_free(RVbufR7); + MikMod_free(RVbufR8); 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(vinf) MikMod_free(vinf); - if(!(vinf= MikMod_calloc(sizeof(VINFO),vc_softchn))) return 1; + MikMod_free(vinf); + if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1; for(t=0;t +#endif +#include + +#include "mikmod_internals.h" + +/* + Constant Definitions + ==================== + + MAXVOL_FACTOR (was BITSHIFT in virtch.c) + Controls the maximum volume of the output data. All mixed data is + divided by this number after mixing, so larger numbers result in + quieter mixing. Smaller numbers will increase the likeliness of + distortion on loud modules. + + REVERBERATION + Larger numbers result in shorter reverb duration. Longer reverb + durations can cause unwanted static and make the reverb sound more + like a crappy echo. + + SAMPLING_SHIFT + Specified the shift multiplier which controls by how much the mixing + rate is multiplied while mixing. Higher values can improve quality by + smoothing the sound and reducing pops and clicks. Note, this is a shift + value, so a value of 2 becomes a mixing-rate multiplier of 4, and a + value of 3 = 8, etc. + + FRACBITS + The number of bits per integer devoted to the fractional part of the + number. Generally, this number should not be changed for any reason. + + !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0 + +*/ + +#define BITSHIFT 9 +#define MAXVOL_FACTOR (1< sample has to be restarted */ + UBYTE active; /* =1 -> sample is playing */ + UWORD flags; /* 16/8 bits looping/one-shot */ + SWORD handle; /* identifies the sample */ + ULONG start; /* start index */ + ULONG size; /* samplesize */ + ULONG reppos; /* loop start */ + ULONG repend; /* loop end */ + ULONG frq; /* current frequency */ + int vol; /* current volume */ + int pan; /* current panning position */ + + int click; + int rampvol; + SLONG lastvalL,lastvalR; + int lvolsel,rvolsel; /* Volume factor in range 0-255 */ + int oldlvol,oldrvol; + + SLONGLONG current; /* current index in the sample */ + SLONGLONG increment; /* increment value */ +} VINFO; + +static SWORD **Samples; +static VINFO *vinf=NULL,*vnf; +static long tickleft,samplesthatfit,vc_memory=0; +static int vc_softchn; +static SLONGLONG idxsize,idxlpos,idxlend; +static SLONG *vc_tickbuf=NULL; +static UWORD vc_mode; + +#ifdef _MSC_VER +/* Weird bug in compiler */ /* FIXME is this still needed? */ +typedef void (*MikMod_callback_t)(unsigned char *data, size_t len); +#endif + +/* Reverb control variables */ + +static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; +static ULONG RVRindex; + +/* For Mono or Left Channel */ +static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL, + *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL; + +/* For Stereo only (Right Channel) */ +static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, + *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL; + +#ifdef NATIVE_64BIT_INT +#define NATIVE SLONGLONG +#else +#define NATIVE SLONG +#endif + +/*========== 32 bit sample mixers - only for 32 bit platforms */ +#ifndef NATIVE_64BIT_INT + +static SLONG Mix32MonoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,SLONG todo) +{ + SWORD sample=0; + SLONG i,f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)( (((SLONG)(srce[i]*(FRACMASK+1L-f)) + + ((SLONG)srce[i+1]*f)) >> FRACBITS)); + idx+=increment; + + if(vnf->rampvol) { + *dest++ += (long)( + ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * + (SLONG)sample ) >> CLICK_SHIFT ); + vnf->rampvol--; + } else + if(vnf->click) { + *dest++ += (long)( + ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONG)sample ) + + (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); + vnf->click--; + } else + *dest++ +=vnf->lvolsel*sample; + } + vnf->lastvalL=vnf->lvolsel * sample; + + return idx; +} + +static SLONG Mix32StereoNormal(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) +{ + SWORD sample=0; + SLONG i,f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONG)srce[i+1] * f)) >> FRACBITS)); + idx += increment; + + if(vnf->rampvol) { + *dest++ += (long)( + ( ( ((SLONG)vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONG)sample ) >> CLICK_SHIFT ); + *dest++ += (long)( + ( ( ((SLONG)vnf->oldrvol*vnf->rampvol) + + (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONG)sample ) >> CLICK_SHIFT ); + vnf->rampvol--; + } else + if(vnf->click) { + *dest++ += (long)( + ( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONG)sample ) + (vnf->lastvalL * vnf->click) ) + >> CLICK_SHIFT ); + *dest++ += (long)( + ( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONG)sample ) + (vnf->lastvalR * vnf->click) ) + >> CLICK_SHIFT ); + vnf->click--; + } else { + *dest++ +=vnf->lvolsel*sample; + *dest++ +=vnf->rvolsel*sample; + } + } + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->rvolsel*sample; + + return idx; +} + +static SLONG Mix32StereoSurround(const SWORD* const srce,SLONG* dest,SLONG idx,SLONG increment,ULONG todo) +{ + SWORD sample=0; + long whoop; + SLONG i, f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONG)srce[i+1]*f)) >> FRACBITS)); + idx+=increment; + + if(vnf->rampvol) { + whoop=(long)( + ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * + (SLONG)sample) >> CLICK_SHIFT ); + *dest++ +=whoop; + *dest++ -=whoop; + vnf->rampvol--; + } else + if(vnf->click) { + whoop = (long)( + ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONG)sample) + + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); + *dest++ +=whoop; + *dest++ -=whoop; + vnf->click--; + } else { + *dest++ +=vnf->lvolsel*sample; + *dest++ -=vnf->lvolsel*sample; + } + } + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->lvolsel*sample; + + return idx; +} +#endif + +/*========== 64 bit mixers */ + +static SLONGLONG MixMonoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,SLONG todo) +{ + SWORD sample=0; + SLONGLONG i,f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)((((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); + idx+=increment; + + if(vnf->rampvol) { + *dest++ += (long)( + ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * + (SLONGLONG)sample ) >> CLICK_SHIFT ); + vnf->rampvol--; + } else + if(vnf->click) { + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample ) + + (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); + vnf->click--; + } else + *dest++ +=vnf->lvolsel*sample; + } + vnf->lastvalL=vnf->lvolsel * sample; + + return idx; +} + +/* Slowest part... */ + +#if defined HAVE_SSE2 || defined HAVE_ALTIVEC + +static __inline SWORD GetSample(const SWORD* const srce, SLONGLONG idx) +{ + SLONGLONG i=idx>>FRACBITS; + SLONGLONG f=idx&FRACMASK; + return (SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); +} + +static SLONGLONG MixSIMDStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) +{ + SWORD vol[8] = {vnf->lvolsel, vnf->rvolsel}; + SWORD sample=0; + SLONG remain = todo; + + /* Dest can be misaligned */ + while(!IS_ALIGNED_16(dest)) { + sample=srce[idx >> FRACBITS]; + idx += increment; + *dest++ += vol[0] * sample; + *dest++ += vol[1] * sample; + todo--; + if(!todo) goto end; + } + + /* Srce is always aligned */ + +#if defined HAVE_SSE2 + remain = todo&3; + { + __m128i v0 = _mm_set_epi16(0, vol[1], + 0, vol[0], + 0, vol[1], + 0, vol[0]); + for(todo>>=2;todo; todo--) + { + SWORD s0 = GetSample(srce, idx); + SWORD s1 = GetSample(srce, idx += increment); + SWORD s2 = GetSample(srce, idx += increment); + SWORD s3 = GetSample(srce, idx += increment); + __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 v3 = _mm_load_si128((__m128i*)(dest+0)); + __m128i v4 = _mm_load_si128((__m128i*)(dest+4)); + _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))); + dest+=8; + idx += increment; + } + } + +#elif defined HAVE_ALTIVEC + remain = todo&3; + { + 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--) + { + vector short int r1; + vector signed short v1, v2; + vector signed int v3, v4, v5, v6; + + /* Load constants */ + s[0] = GetSample(srce, idx); + s[1] = GetSample(srce, idx += increment); + s[2] = GetSample(srce, idx += increment); + s[3] = GetSample(srce, idx += increment); + s[4] = 0; + + r1 = vec_ld(0, s); + v1 = vec_perm(r1, r1, (vector unsigned char) + (0*2, 0*2+1, /* s0 */ + 4*2, 4*2+1, /* 0 */ + 0*2, 0*2+1, /* s0 */ + 4*2, 4*2+1, /* 0 */ + 1*2, 1*2+1, /* s1 */ + 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 */ + ) ); + + v3 = vec_ld(0, dest); + v4 = vec_ld(0x10, dest); + v5 = vec_mule(v0, v1); + v6 = vec_mule(v0, v2); + + vec_st(vec_add(v3, v5), 0, dest); + vec_st(vec_add(v4, v6), 0x10, dest); + + dest+=8; + idx += increment; + } + } +#endif /* HAVE_ALTIVEC */ + + /* Remaining bits */ + while(remain--) { + sample=GetSample(srce, idx); + idx+= increment; + *dest++ += vol[0] * sample; + *dest++ += vol[1] * sample; + } +end: + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->rvolsel*sample; + return idx; +} + +static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) +{ + SWORD sample=0; + SLONGLONG i,f; + + if (vnf->rampvol) + while(todo) { + todo--; + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); + idx += increment; + + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + + (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); + vnf->rampvol--; + + if (!vnf->rampvol) + break; + } + + if (vnf->click) + while(todo) { + todo--; + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); + idx += increment; + + *dest++ += (long)( + ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) + >> CLICK_SHIFT ); + + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) + >> CLICK_SHIFT ); + vnf->click--; + + if (!vnf->click) + break; + } + + if (todo) + { + if (md_mode & DMODE_SIMDMIXER) { + return MixSIMDStereoNormal(srce, dest, idx, increment, todo); + } + while(todo) + { + i=idx>>FRACBITS, + f=idx&FRACMASK; + sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); + idx += increment; + + *dest++ +=vnf->lvolsel*sample; + *dest++ +=vnf->rvolsel*sample; + todo--; + } + } + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->rvolsel*sample; + + return idx; +} + +#else /* HAVE_SSE2 || HAVE_ALTIVEC */ +static SLONGLONG MixStereoNormal(const SWORD* const srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) +{ + SWORD sample=0; + SLONGLONG i,f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS)); + idx += increment; + + if(vnf->rampvol) { + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + + (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) + ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); + vnf->rampvol--; + } else + if(vnf->click) { + *dest++ += (long)( + ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) + >> CLICK_SHIFT ); + *dest++ += (long)( + ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) + >> CLICK_SHIFT ); + vnf->click--; + } else { + *dest++ +=vnf->lvolsel*sample; + *dest++ +=vnf->rvolsel*sample; + } + } + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->rvolsel*sample; + + return idx; +} +#endif /* HAVE_SSE2 || HAVE_ALTIVEC */ + + +static SLONGLONG MixStereoSurround(const SWORD* srce,SLONG* dest,SLONGLONG idx,SLONGLONG increment,ULONG todo) +{ + SWORD sample=0; + long whoop; + SLONGLONG i, f; + + while(todo--) { + i=idx>>FRACBITS,f=idx&FRACMASK; + sample=(SWORD)(((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + + ((SLONGLONG)srce[i+1]*f)) >> FRACBITS)); + idx+=increment; + + if(vnf->rampvol) { + whoop=(long)( + ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * + (SLONGLONG)sample) >> CLICK_SHIFT ); + *dest++ +=whoop; + *dest++ -=whoop; + vnf->rampvol--; + } else + if(vnf->click) { + whoop = (long)( + ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * + (SLONGLONG)sample) + + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); + *dest++ +=whoop; + *dest++ -=whoop; + vnf->click--; + } else { + *dest++ +=vnf->lvolsel*sample; + *dest++ -=vnf->lvolsel*sample; + } + } + vnf->lastvalL=vnf->lvolsel*sample; + vnf->lastvalR=vnf->lvolsel*sample; + + return idx; +} + +static void(*Mix32toFP)(float* dste,const SLONG *srce,NATIVE count); +static void(*Mix32to16)(SWORD* dste,const SLONG *srce,NATIVE count); +static void(*Mix32to8)(SBYTE* dste,const SLONG *srce,NATIVE count); +static void(*MixReverb)(SLONG *srce,NATIVE count); + +/* Reverb macros */ +#define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n +#define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7) +#define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7) + +static void MixReverb_Normal(SLONG *srce,NATIVE count) +{ + NATIVE speedup; + int ReverbPct; + unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; + + ReverbPct=58+(md_reverb*4); + + COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); + COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); + + while(count--) { + /* Compute the left channel echo buffers */ + speedup = *srce >> 3; + + COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); + COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); + + /* Prepare to compute actual finalized data */ + RVRindex++; + + COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); + COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); + + /* left channel */ + *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ + RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; + } +} + +static void MixReverb_Stereo(SLONG *srce,NATIVE count) +{ + NATIVE speedup; + int ReverbPct; + unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; + + ReverbPct=58+(md_reverb*4); + + COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); + COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); + + while(count--) { + /* Compute the left channel echo buffers */ + speedup = *srce >> 3; + + COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); + COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); + + /* Compute the right channel echo buffers */ + speedup = srce[1] >> 3; + + COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4); + COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8); + + /* Prepare to compute actual finalized data */ + RVRindex++; + + COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); + COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); + + /* left channel */ + *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ + RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; + + /* right channel */ + *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ + RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; + } +} + +static void (*MixLowPass)(SLONG* srce,NATIVE count); + +static int nLeftNR, nRightNR; + +static void MixLowPass_Stereo(SLONG* srce,NATIVE count) +{ + int n1 = nLeftNR, n2 = nRightNR; + SLONG *pnr = srce; + int nr=count; + for (; nr; nr--) + { + int vnr = pnr[0] >> 1; + pnr[0] = vnr + n1; + n1 = vnr; + vnr = pnr[1] >> 1; + pnr[1] = vnr + n2; + n2 = vnr; + pnr += 2; + } + nLeftNR = n1; + nRightNR = n2; +} + +static void MixLowPass_Normal(SLONG* srce,NATIVE count) +{ + int n1 = nLeftNR; + SLONG *pnr = srce; + int nr=count; + for (; nr; nr--) + { + int vnr = pnr[0] >> 1; + pnr[0] = vnr + n1; + n1 = vnr; + pnr ++; + } + nLeftNR = n1; +} + +/* Mixing macros */ +#define EXTRACT_SAMPLE_FP(var,attenuation) var=*srce++*((1.0f / 32768.0f) / (MAXVOL_FACTOR*attenuation)) +#define CHECK_SAMPLE_FP(var,bound) var=(var>bound)?bound:(var<-bound)?-bound:var + +static void Mix32ToFP_Normal(float* dste,const SLONG *srce,NATIVE count) +{ + float x1,x2,tmpx; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx=0.0f; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); + + CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); + + tmpx+=x1+x2; + } + *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); + } +} + +static void Mix32ToFP_Stereo(float* dste,const SLONG *srce,NATIVE count) +{ + float x1,x2,x3,x4,tmpx,tmpy; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx=tmpy=0.0f; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE_FP(x1,1.0f); EXTRACT_SAMPLE_FP(x2,1.0f); + EXTRACT_SAMPLE_FP(x3,1.0f); EXTRACT_SAMPLE_FP(x4,1.0f); + + CHECK_SAMPLE_FP(x1,1.0f); CHECK_SAMPLE_FP(x2,1.0f); + CHECK_SAMPLE_FP(x3,1.0f); CHECK_SAMPLE_FP(x4,1.0f); + + tmpx+=x1+x3; + tmpy+=x2+x4; + } + *dste++ =tmpx*(1.0f/SAMPLING_FACTOR); + *dste++ =tmpy*(1.0f/SAMPLING_FACTOR); + } +} + +/* Mixing macros */ +#define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation) +#define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var + +static void Mix32To16_Normal(SWORD* dste,const SLONG *srce,NATIVE count) +{ + NATIVE x1,x2,tmpx; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx=0; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); + + CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); + + tmpx+=x1+x2; + } + *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); + } +} + + +static void Mix32To16_Stereo(SWORD* dste,const SLONG *srce,NATIVE count) +{ + NATIVE x1,x2,x3,x4,tmpx,tmpy; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx=tmpy=0; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); + EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1); + + CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); + CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768); + + tmpx+=x1+x3; + tmpy+=x2+x4; + } + *dste++ =(SWORD)(tmpx/SAMPLING_FACTOR); + *dste++ =(SWORD)(tmpy/SAMPLING_FACTOR); + } +} + +static void Mix32To8_Normal(SBYTE* dste,const SLONG *srce,NATIVE count) +{ + NATIVE x1,x2,tmpx; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx = 0; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); + + CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); + + tmpx+=x1+x2; + } + *dste++ = (SBYTE)((tmpx/SAMPLING_FACTOR)+128); + } +} + +static void Mix32To8_Stereo(SBYTE* dste,const SLONG *srce,NATIVE count) +{ + NATIVE x1,x2,x3,x4,tmpx,tmpy; + int i; + + for(count/=SAMPLING_FACTOR;count;count--) { + tmpx=tmpy=0; + + for(i=SAMPLING_FACTOR/2;i;i--) { + EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); + EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256); + + CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); + CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128); + + tmpx+=x1+x3; + tmpy+=x2+x4; + } + *dste++ =(SBYTE)((tmpx/SAMPLING_FACTOR)+128); + *dste++ =(SBYTE)((tmpy/SAMPLING_FACTOR)+128); + } +} + +#if defined HAVE_SSE2 +#define SHIFT_MIX_TO_16 (BITSHIFT + 16 - 16) +/* TEST: Ok */ +static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) +{ + int remain = count; + + /* Check unaligned dste buffer. srce is always aligned. */ + while(!IS_ALIGNED_16(dste)) + { + Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); + dste+=2; + srce+=8; + count--; + if(!count) return; + } + + /* dste and srce aligned. srce is always aligned. */ + remain = count & 15; + /* count / 2 for 1 sample */ + + for(count>>=4;count;count--) + { + /* Load 32bit sample. 1st average */ + __m128i v0 = _mm_add_epi32( + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+0)), SHIFT_MIX_TO_16), + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+4)), SHIFT_MIX_TO_16) + ); /* v0: s0.l+s2.l | s0.r+s2.r | s1.l+s3.l | s1.r+s3.r */ + + /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ + __m128i v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); + /* v1: s0.l+s2.l / 4 | s0.r+s2.r / 4 | s1.l+s3.l+s0.l+s2.l / 4 | s1.r+s3.r+s0.r+s2.r / 4 */ + + __m128i v2 = _mm_add_epi32( + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+8)), SHIFT_MIX_TO_16), + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+12)), SHIFT_MIX_TO_16) + ); /* v2: s4.l+s6.l | s4.r+s6.r | s5.l+s7.l | s5.r+s7.r */ + + __m128i v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ + /* v3: s4.l+s6.l /4 | s4.r+s6.r / 4| s5.l+s7.l+s4.l+s6.l / 4 | s5.r+s7.r+s4.r+s6.l / 4 */ + + /* pack two stereo samples in one */ + __m128i v4 = _mm_unpacklo_epi64(v1, v3); /* v4 = avg(s0,s1,s2,s3) | avg(s4,s5,s6,s7) */ + + __m128i v6; + + /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ + v0 = _mm_add_epi32( + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+16)), SHIFT_MIX_TO_16), + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+20)), SHIFT_MIX_TO_16) + ); /* 128bit = 2 stereo samples */ + + /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ + v1 = _mm_srai_epi32(_mm_add_epi32(v0, mm_hiqq(v0)), 2); + + v2 = _mm_add_epi32( + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+24)), SHIFT_MIX_TO_16), + _mm_srai_epi32(_mm_loadu_si128((__m128i const *)(srce+28)), SHIFT_MIX_TO_16) + ); + + v3 = _mm_srai_epi32(_mm_add_epi32(v2, mm_hiqq(v2)), 2); /* Upper 64bit is unused */ + + /* pack two stereo samples in one */ + v6 = _mm_unpacklo_epi64(v1, v3); /* v6 = avg(s8,s9,s10,s11) | avg(s12,s13,s14,s15) */ + + _mm_store_si128((__m128i*)dste, _mm_packs_epi32(v4, v6)); /* 4 interpolated stereo sample 32bit to 4 */ + + dste+=8; + srce+=32; /* 32 = 4 * 8 */ + } + + /* FIXME: THIS PART WRITES PAST DST !! */ + if (remain) + { + Mix32To16_Stereo(dste, srce, remain); + } +} + +#elif defined HAVE_ALTIVEC +#define SHIFT_MIX_TO_16 vec_splat_u32(BITSHIFT + 16 - 16) +/* TEST: Ok */ +static void Mix32To16_Stereo_SIMD_4Tap(SWORD* dste, const SLONG* srce, NATIVE count) +{ + int remain = count; + + /* Check unaligned dste buffer. srce is always aligned. */ + while(!IS_ALIGNED_16(dste)) + { + Mix32To16_Stereo(dste, srce, SAMPLING_FACTOR); + dste+=2; + srce+=8; + count--; + if(!count) return; + } + + /* dste and srce aligned. srce is always aligned. */ + remain = count & 15; + for(count>>=4;count;count--) + { + /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ + vector signed int v0 = vec_add( + vec_sra(vec_ld(0, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ + vec_sra(vec_ld(0x10, srce), SHIFT_MIX_TO_16) + ); /* 128bit = 2 stereo samples */ + + /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ + vector signed int v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); + + vector signed int v2 = vec_add( + vec_sra(vec_ld(0x20, srce), SHIFT_MIX_TO_16), + vec_sra(vec_ld(0x30, srce), SHIFT_MIX_TO_16) + ); + + vector signed int v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ + + /* pack two stereo samples in one */ + vector signed int v6, v4 = vec_unpacklo(v1, v3); /* v4 = lo64(v1) | lo64(v3) */ + + /* Load 32bit sample. 1st average (s0.l+s2.l, s0.r+s2.r, s1.l+s3.l, s1.r+s3.r) */ + v0 = vec_add( + vec_sra(vec_ld(0x40, srce), SHIFT_MIX_TO_16), /* 128bit = 2 stereo samples */ + vec_sra(vec_ld(0x50, srce), SHIFT_MIX_TO_16) + ); /* 128bit = 2 stereo samples */ + + /* 2nd average (s0.l+s2.l+s1.l+s3.l / 4, s0.r+s2.r+s1.r+s3.r / 4). Upper 64bit is unused (1 stereo sample) */ + v1 = vec_sra(vec_add(v0, vec_hiqq(v0)), vec_splat_u32(2)); + + v2 = vec_add( + vec_sra(vec_ld(0x60, srce), SHIFT_MIX_TO_16), + vec_sra(vec_ld(0x70, srce), SHIFT_MIX_TO_16) + ); + + v3 = vec_sra(vec_add(v2, vec_hiqq(v2)), vec_splat_u32(2)); /* Upper 64bit is unused */ + + /* pack two stereo samples in one */ + v6 = vec_unpacklo(v1, v3); + + vec_st(vec_packs(v4, v6), 0, dste); /* 4 interpolated stereo sample 32bit to 4 interpolated stereo sample 16bit + saturation */ + + dste+=8; + srce+=32; /* 32 = 4 * 8 */ + } + + if (remain) + { + Mix32To16_Stereo(dste, srce, remain); + } +} + +#endif + + +static void AddChannel(SLONG* ptr,NATIVE todo) +{ + SLONGLONG end,done; + SWORD *s; + + if(!(s=Samples[vnf->handle])) { + vnf->current = vnf->active = 0; + vnf->lastvalL = vnf->lastvalR = 0; + return; + } + + /* update the 'current' index so the sample loops, or stops playing if it + reached the end of the sample */ + while(todo>0) { + SLONGLONG endpos; + + if(vnf->flags & SF_REVERSE) { + /* The sample is playing in reverse */ + if((vnf->flags&SF_LOOP)&&(vnf->currentflags & SF_BIDI) { + /* sample is doing bidirectional loops, so 'bounce' the + current index against the idxlpos */ + vnf->current = idxlpos+(idxlpos-vnf->current); + vnf->flags &= ~SF_REVERSE; + vnf->increment = -vnf->increment; + } else + /* normal backwards looping, so set the current position to + loopend index */ + vnf->current=idxlend-(idxlpos-vnf->current); + } else { + /* the sample is not looping, so check if it reached index 0 */ + if(vnf->current < 0) { + /* playing index reached 0, so stop playing this sample */ + vnf->current = vnf->active = 0; + break; + } + } + } else { + /* The sample is playing forward */ + if((vnf->flags & SF_LOOP) && + (vnf->current >= idxlend)) { + /* the sample is looping, check the loopend index */ + if(vnf->flags & SF_BIDI) { + /* sample is doing bidirectional loops, so 'bounce' the + current index against the idxlend */ + vnf->flags |= SF_REVERSE; + vnf->increment = -vnf->increment; + vnf->current = idxlend-(vnf->current-idxlend); + } else + /* normal backwards looping, so set the current position + to loopend index */ + vnf->current=idxlpos+(vnf->current-idxlend); + } else { + /* sample is not looping, so check if it reached the last + position */ + if(vnf->current >= idxsize) { + /* yes, so stop playing this sample */ + vnf->current = vnf->active = 0; + break; + } + } + } + + end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0: + (vnf->flags&SF_LOOP)?idxlend:idxsize; + + /* if the sample is not blocked... */ + if((end==vnf->current)||(!vnf->increment)) + done=0; + else { + done=MIN((end-vnf->current)/vnf->increment+1,todo); + if(done<0) done=0; + } + + if(!done) { + vnf->active = 0; + break; + } + + endpos=vnf->current+done*vnf->increment; + + if(vnf->vol || vnf->rampvol) { +#ifndef NATIVE_64BIT_INT + /* use the 32 bit mixers as often as we can (they're much faster) */ + if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) { + if(vc_mode & DMODE_STEREO) { + if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) + vnf->current=(SLONGLONG)Mix32StereoSurround + (s,ptr,vnf->current,vnf->increment,done); + else + vnf->current=Mix32StereoNormal + (s,ptr,vnf->current,vnf->increment,done); + } else + vnf->current=Mix32MonoNormal + (s,ptr,vnf->current,vnf->increment,done); + } + else +#endif + { + if(vc_mode & DMODE_STEREO) { + if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) + vnf->current=MixStereoSurround + (s,ptr,vnf->current,vnf->increment,done); + else + vnf->current=MixStereoNormal + (s,ptr,vnf->current,vnf->increment,done); + } else + vnf->current=MixMonoNormal + (s,ptr,vnf->current,vnf->increment,done); + } + } else { + vnf->lastvalL = vnf->lastvalR = 0; + /* update sample position */ + vnf->current=endpos; + } + + todo -= done; + ptr += (vc_mode & DMODE_STEREO)?(done<<1):done; + } +} + +#define _IN_VIRTCH_ + +#define VC1_SilenceBytes VC2_SilenceBytes +#define VC1_WriteSamples VC2_WriteSamples +#define VC1_WriteBytes VC2_WriteBytes +#define VC1_Exit VC2_Exit +#define VC1_VoiceSetVolume VC2_VoiceSetVolume +#define VC1_VoiceGetVolume VC2_VoiceGetVolume +#define VC1_VoiceSetPanning VC2_VoiceSetPanning +#define VC1_VoiceGetPanning VC2_VoiceGetPanning +#define VC1_VoiceSetFrequency VC2_VoiceSetFrequency +#define VC1_VoiceGetFrequency VC2_VoiceGetFrequency +#define VC1_VoicePlay VC2_VoicePlay +#define VC1_VoiceStop VC2_VoiceStop +#define VC1_VoiceStopped VC2_VoiceStopped +#define VC1_VoiceGetPosition VC2_VoiceGetPosition +#define VC1_SampleUnload VC2_SampleUnload +#define VC1_SampleLoad VC2_SampleLoad +#define VC1_SampleSpace VC2_SampleSpace +#define VC1_SampleLength VC2_SampleLength +#define VC1_VoiceRealVolume VC2_VoiceRealVolume + +#include "virtch_common.c" +#undef _IN_VIRTCH_ + +void VC2_WriteSamples(SBYTE* buf,ULONG todo) +{ + int left,portion=0; + SBYTE *buffer; + int t,pan,vol; + + todo*=SAMPLING_FACTOR; + + while(todo) { + if(!tickleft) { + if(vc_mode & DMODE_SOFT_MUSIC) md_player(); + tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L); + tickleft&=~(SAMPLING_FACTOR-1); + } + left = MIN(tickleft, (int)todo); + buffer = buf; + tickleft -= left; + todo -= left; + buf += samples2bytes(left)/SAMPLING_FACTOR; + + while(left) { + portion = MIN(left, samplesthatfit); + memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2)); + for(t=0;tkick) { + vnf->current=((SLONGLONG)(vnf->start))<kick = 0; + vnf->active = 1; + vnf->click = CLICK_BUFFER; + vnf->rampvol = 0; + } + + if(!vnf->frq) vnf->active = 0; + + if(vnf->active) { + vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT)) + /md_mixfreq; + if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment; + vol = vnf->vol; pan = vnf->pan; + + vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel; + if(vc_mode & DMODE_STEREO) { + if(pan!=PAN_SURROUND) { + vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8; + vnf->rvolsel=(vol*pan)>>8; + } else { + vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480; + } + } else + vnf->lvolsel=vol; + + idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<repend)?((SLONGLONG)(vnf->repend)<reppos)<15) md_reverb=15; + MixReverb(vc_tickbuf,portion); + } + + if (vc_callback) { + vc_callback((unsigned char*)vc_tickbuf, portion); + } + + if(vc_mode & DMODE_FLOAT) + Mix32toFP((float*)buffer,vc_tickbuf,portion); + else if(vc_mode & DMODE_16BITS) + Mix32to16((SWORD*)buffer,vc_tickbuf,portion); + else + Mix32to8((SBYTE*)buffer,vc_tickbuf,portion); + + buffer += samples2bytes(portion) / SAMPLING_FACTOR; + left -= portion; + } + } +} + +int VC2_Init(void) +{ + VC_SetupPointers(); + + if (!(md_mode&DMODE_HQMIXER)) + return VC1_Init(); + + if(!(Samples=(SWORD**)MikMod_amalloc(MAXSAMPLEHANDLES*sizeof(SWORD*)))) { + _mm_errno = MMERR_INITIALIZING_MIXER; + return 1; + } + if(!vc_tickbuf) { + if(!(vc_tickbuf=(SLONG*)MikMod_amalloc((TICKLSIZE+32)*sizeof(SLONG)))) { + _mm_errno = MMERR_INITIALIZING_MIXER; + return 1; + } + } + + if(md_mode & DMODE_STEREO) { + Mix32toFP = Mix32ToFP_Stereo; +#if ((defined HAVE_ALTIVEC || defined HAVE_SSE2) && (SAMPLING_FACTOR == 4)) + if (md_mode & DMODE_SIMDMIXER) + Mix32to16 = Mix32To16_Stereo_SIMD_4Tap; + else +#endif + Mix32to16 = Mix32To16_Stereo; + Mix32to8 = Mix32To8_Stereo; + MixReverb = MixReverb_Stereo; + MixLowPass = MixLowPass_Stereo; + } else { + Mix32toFP = Mix32ToFP_Normal; + Mix32to16 = Mix32To16_Normal; + Mix32to8 = Mix32To8_Normal; + MixReverb = MixReverb_Normal; + MixLowPass = MixLowPass_Normal; + } + + md_mode |= DMODE_INTERP; + vc_mode = md_mode; + return 0; +} + +int VC2_PlayStart(void) +{ + md_mode|=DMODE_INTERP; + + samplesthatfit = TICKLSIZE; + if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; + tickleft = 0; + + RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10); + RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10); + RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10); + RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10); + RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10); + RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10); + RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10); + RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10); + + if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; + if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; + if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; + if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; + if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; + if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+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; + + /* 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(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; + if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; + if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; + if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+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(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; + } + + RVRindex = 0; + return 0; +} + +void VC2_PlayStop(void) +{ + MikMod_free(RVbufL1); + MikMod_free(RVbufL2); + MikMod_free(RVbufL3); + MikMod_free(RVbufL4); + MikMod_free(RVbufL5); + MikMod_free(RVbufL6); + MikMod_free(RVbufL7); + MikMod_free(RVbufL8); + MikMod_free(RVbufR1); + MikMod_free(RVbufR2); + MikMod_free(RVbufR3); + MikMod_free(RVbufR4); + MikMod_free(RVbufR5); + MikMod_free(RVbufR6); + MikMod_free(RVbufR7); + MikMod_free(RVbufR8); + + RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; + RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; +} + +int VC2_SetNumVoices(void) +{ + int t; + + md_mode|=DMODE_INTERP; + + if(!(vc_softchn=md_softchn)) return 0; + + MikMod_free(vinf); + if(!(vinf=(VINFO*)MikMod_calloc(vc_softchn,sizeof(VINFO)))) return 1; + + for(t=0;t32) vinf[voice].rampvol=CLICK_BUFFER; @@ -353,9 +359,8 @@ void VC1_VoiceSetPanning(UBYTE voice,ULONG pan) void VC1_SampleUnload(SWORD handle) { - if (handlesample; int handle; - ULONG t, length,loopstart,loopend; + ULONG t, length,loopstart,loopend,looplen; 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 */ for(handle=0;handleloopend > s->length) s->loopend = s->length; @@ -390,22 +400,26 @@ SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type) SL_SampleSigned(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; return -1; } /* 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; + } /* Unclick sample */ if(s->flags & SF_LOOP) { + looplen = loopend - loopstart;/* handle short samples */ if(s->flags & SF_BIDI) - for(t=0;t<16;t++) + for(t=0;t<16 && tlength*((s->flags&SF_16BITS)?2:1))+16; @@ -456,11 +470,8 @@ ULONG VC1_VoiceRealVolume(UBYTE voice) return abs(k-j); } +#endif /* _VIRTCH_COMMON_ */ -#endif - -MikMod_callback_t vc_callback; - -#endif +#endif /* _IN_VIRTCH_ */ /* ex:set ts=4: */ diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config index 96228085c9..84f096a409 100644 --- a/apps/plugins/viewers.config +++ b/apps/plugins/viewers.config @@ -44,7 +44,6 @@ asy,viewers/mikmod,7 dsm,viewers/mikmod,7 far,viewers/mikmod,7 gdm,viewers/mikmod,7 -gt2,viewers/mikmod,7 imf,viewers/mikmod,7 it,viewers/mikmod,7 m15,viewers/mikmod,7 @@ -57,6 +56,7 @@ stm,viewers/mikmod,7 stx,viewers/mikmod,7 ult,viewers/mikmod,7 uni,viewers/mikmod,7 +umx,viewers/mikmod,7 xm,viewers/mikmod,7 pd,viewers/pdbox,2 rsp,viewers/searchengine,8 -- cgit v1.2.3