summaryrefslogtreecommitdiffstats
path: root/apps/plugins/mikmod/mloader.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/mloader.c')
-rw-r--r--apps/plugins/mikmod/mloader.c319
1 files changed, 198 insertions, 121 deletions
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<len;i++)
if(of.comment[i]=='\r') of.comment[i]='\n';
@@ -122,44 +135,44 @@ int ReadComment(UWORD len)
int ReadLinedComment(UWORD len,UWORD linelen)
{
- CHAR *tempcomment,*line,*storage;
- UWORD total=0,t,lines;
- int i;
-
- lines = (len + linelen - 1) / linelen;
- if (len) {
- if(!(tempcomment=(CHAR*)MikMod_malloc(len+1))) return 0;
- if(!(storage=(CHAR*)MikMod_malloc(linelen+1))) {
- MikMod_free(tempcomment);
- return 0;
- }
- memset(tempcomment, ' ', len);
- _mm_read_UBYTES(tempcomment,len,modreader);
-
- /* compute message length */
- for(line=tempcomment,total=t=0;t<lines;t++,line+=linelen) {
- for(i=linelen;(i>=0)&&(line[i]==' ');i--) line[i]=0;
- for(i=0;i<linelen;i++) if (!line[i]) break;
- total+=1+i;
- }
-
- if(total>lines) {
- 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<lines;t++,line+=linelen) {
- for(i=0;i<linelen;i++) if(!(storage[i]=line[i])) break;
- storage[i]=0; /* if (i==linelen) */
- strcat(of.comment,storage);strcat(of.comment,"\r");
+ _mm_read_UBYTES(buf,len,modreader);
+ storage[cnt] = 0;
+ for (line = 0, fpos = 0, cpos = 0; line < numlines; line++, fpos += linelen, cpos += (linelen + 1))
+ {
+ cnt = len - fpos;
+ if (cnt > 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;t<of.numins;t++) {
- for(n=0;n<INSTNOTES;n++) {
+ for(n=0;n<INSTNOTES;n++) {
/* Init note / sample lookup table */
of.instruments[t].samplenote[n] = n;
of.instruments[t].samplenumber[n] = t;
- }
+ }
of.instruments[t].globvol = 64;
}
return 1;
@@ -257,8 +270,8 @@ static int ML_LoadSamples(void)
}
/* Creates a CSTR out of a character buffer of 'len' bytes, but strips any
- terminating non-printing characters like 0, spaces etc. */
-CHAR *DupStr(CHAR* s,UWORD len,int strict)
+ terminating non-printing characters like 0, spaces etc. */
+CHAR *DupStr(const CHAR* s, UWORD len, int strict)
{
UWORD t;
CHAR *d=NULL;
@@ -277,48 +290,42 @@ CHAR *DupStr(CHAR* s,UWORD len,int strict)
/* When the buffer wasn't completely empty, allocate a cstring and copy the
buffer into that string, except for any control-chars */
- if((d=(CHAR*)MikMod_malloc(sizeof(CHAR)*(len+1)))) {
+ if((d=(CHAR*)MikMod_malloc(sizeof(CHAR)*(len+1))) != NULL) {
for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t];
d[len]=0;
}
return d;
}
-CHAR *StrDup(CHAR *s)
-{
- size_t l = strlen(s) + 1;
- CHAR *d = MikMod_malloc(l);
- strcpy(d, s);
- return d;
-}
-
static void ML_XFreeSample(SAMPLE *s)
{
if(s->handle>=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;t<mf->numtrk;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;t<mf->numsmp;t++)
+ for(t=0;t<mf->numsmp;t++) {
+ MikMod_free(mf->samples[t].samplename);
if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]);
+ }
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(maxchan<mf->numchn) 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);
}