diff options
Diffstat (limited to 'apps/plugins/mikmod/mloader.c')
-rw-r--r-- | apps/plugins/mikmod/mloader.c | 319 |
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); } |