X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=libs%2Fmikmod%2Fplayercode%2Fmloader.c;fp=libs%2Fmikmod%2Fplayercode%2Fmloader.c;h=684b8f22d775e4dddf4d89b0bff9fb9abdd05e25;hp=0000000000000000000000000000000000000000;hb=cf94899f4f4d8535074db6421245b973d2fcde8c;hpb=8024ae981f39d370af5cceb3cb97f62820b0a120 diff --git a/libs/mikmod/playercode/mloader.c b/libs/mikmod/playercode/mloader.c new file mode 100644 index 0000000..684b8f2 --- /dev/null +++ b/libs/mikmod/playercode/mloader.c @@ -0,0 +1,670 @@ +/* MikMod sound library + (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file + AUTHORS for complete list. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +/*============================================================================== + + $Id$ + + These routines are used to access the available module loaders + +==============================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +#include "mikmod_internals.h" + +#ifdef SUNOS +extern int fprintf(FILE *, const char *, ...); +#endif + +MREADER *modreader; +MODULE of; + +static MLOADER *firstloader=NULL; + +static MUNPACKER unpackers[] = { + PP20_Unpack, + MMCMP_Unpack, + XPK_Unpack, + S404_Unpack, + NULL +}; + +const UWORD finetune[16] = { + 8363,8413,8463,8529,8581,8651,8723,8757, + 7895,7941,7985,8046,8107,8169,8232,8280 +}; + +MIKMODAPI CHAR* MikMod_InfoLoader(void) +{ + int len=0; + MLOADER *l; + CHAR *list=NULL; + + MUTEX_LOCK(lists); + /* compute size of buffer */ + for(l = firstloader; l; l = l->next) + len += 1 + (l->next ? 1 : 0) + strlen(l->version); + + if(len) + 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; +} + +void _mm_registerloader(MLOADER* ldr) +{ + MLOADER *cruise=firstloader; + + if(cruise) { + while(cruise->next) cruise = cruise->next; + cruise->next=ldr; + } else + firstloader=ldr; +} + +MIKMODAPI void MikMod_RegisterLoader(struct MLOADER* ldr) +{ + /* if we try to register an invalid loader, or an already registered loader, + ignore this attempt */ + if ((!ldr)||(ldr->next)) + return; + + MUTEX_LOCK(lists); + _mm_registerloader(ldr); + MUTEX_UNLOCK(lists); +} + +BOOL ReadComment(UWORD len) +{ + if(len) { + int i; + + 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; + } + + /* convert message */ + for(line=tempcomment,t=0;tlength) SL_RegisterSample(s,MD_MUSIC,modreader); + + return 1; +} + +/* Creates a CSTR out of a character buffer of 'len' bytes, but strips any + terminating non-printing characters like 0, spaces etc. */ +CHAR *DupStr(const CHAR* s, UWORD len, BOOL strict) +{ + UWORD t; + CHAR *d=NULL; + + /* Scan for last printing char in buffer [includes high ascii up to 254] */ + while(len) { + if(s[len-1]>0x20) break; + len--; + } + + /* Scan forward for possible NULL character */ + if(strict) { + for(t=0;thandle>=0) + MD_SampleUnload(s->handle); + +/* moved samplename freeing to our caller ML_FreeEx(), + * because we are called conditionally. */ +} + +static void ML_XFreeInstrument(INSTRUMENT *i) +{ + MikMod_free(i->insname); +} + +static void ML_FreeEx(MODULE *mf) +{ + UWORD t; + + MikMod_free(mf->songname); + MikMod_free(mf->comment); + + MikMod_free(mf->modtype); + MikMod_free(mf->positions); + MikMod_free(mf->patterns); + MikMod_free(mf->pattrows); + + if(mf->tracks) { + for(t=0;tnumtrk;t++) + MikMod_free(mf->tracks[t]); + MikMod_free(mf->tracks); + } + if(mf->instruments) { + for(t=0;tnumins;t++) + ML_XFreeInstrument(&mf->instruments[t]); + MikMod_free(mf->instruments); + } + if(mf->samples) { + 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)); + if(mf!=&of) MikMod_free(mf); +} + +static MODULE *ML_AllocUniMod(void) +{ + return (MODULE *) MikMod_malloc(sizeof(MODULE)); +} + +static BOOL ML_TryUnpack(MREADER *reader,void **out,long *outlen) +{ + int i; + + *out = NULL; + *outlen = 0; + + for(i=0;unpackers[i]!=NULL;++i) { + _mm_rewind(reader); + if(unpackers[i](reader,out,outlen)) return 1; + } + return 0; +} + +static void Player_Free_internal(MODULE *mf) +{ + if(mf) { + Player_Exit_internal(mf); + ML_FreeEx(mf); + } +} + +MIKMODAPI void Player_Free(MODULE *mf) +{ + MUTEX_LOCK(vars); + Player_Free_internal(mf); + MUTEX_UNLOCK(vars); +} + +static CHAR* Player_LoadTitle_internal(MREADER *reader) +{ + MLOADER *l; + CHAR *title; + void *unpk; + long newlen; + + modreader=reader; + _mm_errno = 0; + _mm_critical = 0; + _mm_iobase_setcur(modreader); + + if(ML_TryUnpack(modreader,&unpk,&newlen)) { + if(!(modreader=_mm_new_mem_reader(unpk,newlen))) { + modreader=reader; + MikMod_free(unpk); + return NULL; + } + } + + /* 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) { + title = l->LoadTitle(); + } + else { + _mm_errno = MMERR_NOT_A_MODULE; + if(_mm_errorhandler) _mm_errorhandler(); + title = NULL; + } + + if (modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + return title; +} + +MIKMODAPI CHAR* Player_LoadTitleFP(FILE *fp) +{ + CHAR* result=NULL; + MREADER* reader; + + if(fp && (reader=_mm_new_file_reader(fp)) != NULL) { + MUTEX_LOCK(lists); + result=Player_LoadTitle_internal(reader); + MUTEX_UNLOCK(lists); + _mm_delete_file_reader(reader); + } + return result; +} + +MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len) +{ + CHAR *result=NULL; + MREADER* reader; + + 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); + MUTEX_UNLOCK(lists); + } + return result; +} + +MIKMODAPI CHAR* Player_LoadTitle(const CHAR* filename) +{ + CHAR* result=NULL; + FILE* fp; + MREADER* reader; + + if((fp=_mm_fopen(filename,"rb")) != NULL) { + if((reader=_mm_new_file_reader(fp)) != NULL) { + MUTEX_LOCK(lists); + result=Player_LoadTitle_internal(reader); + MUTEX_UNLOCK(lists); + _mm_delete_file_reader(reader); + } + _mm_fclose(fp); + } + return result; +} + +/* Loads a module given an reader */ +static MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,BOOL curious) +{ + int t; + MLOADER *l; + BOOL ok; + MODULE *mf; + void *unpk; + long newlen; + + modreader = reader; + _mm_errno = 0; + _mm_critical = 0; + _mm_iobase_setcur(modreader); + + if(ML_TryUnpack(modreader,&unpk,&newlen)) { + if(!(modreader=_mm_new_mem_reader(unpk,newlen))) { + modreader=reader; + MikMod_free(unpk); + return NULL; + } + } + + /* 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) { + _mm_errno = MMERR_NOT_A_MODULE; + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + if(_mm_errorhandler) _mm_errorhandler(); + _mm_rewind(modreader); + _mm_iobase_revert(modreader); + return NULL; + } + + /* init unitrk routines */ + if(!UniInit()) { + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + if(_mm_errorhandler) _mm_errorhandler(); + _mm_rewind(modreader); + _mm_iobase_revert(modreader); + return NULL; + } + + /* init the module structure with vanilla settings */ + memset(&of,0,sizeof(MODULE)); + of.bpmlimit = 33; + of.initvolume = 128; + for (t = 0; t < UF_MAXCHAN; t++) of.chanvol[t] = 64; + for (t = 0; t < UF_MAXCHAN; t++) + of.panning[t] = ((t + 1) & 2) ? PAN_RIGHT : PAN_LEFT; + + /* init module loader and load the header / patterns */ + if (!l->Init || l->Init()) { + _mm_rewind(modreader); + ok = l->Load(curious); + if (ok) { + /* propagate inflags=flags for in-module samples */ + for (t = 0; t < of.numsmp; t++) + if (of.samples[t].inflags == 0) + of.samples[t].inflags = of.samples[t].flags; + } + } else + ok = 0; + + /* free loader and unitrk allocations */ + if (l->Cleanup) l->Cleanup(); + UniCleanup(); + + if(ok) ok = ML_LoadSamples(); + if(ok) ok = ((mf=ML_AllocUniMod()) != NULL); + if(!ok) { + ML_FreeEx(&of); + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + if(_mm_errorhandler) _mm_errorhandler(); + _mm_rewind(modreader); + _mm_iobase_revert(modreader); + 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)) + for (t = 0; t < of.numchn; t++) + of.panning[t] = ((t + 1) & 2) ? PAN_HALFRIGHT : PAN_HALFLEFT; + + /* Copy the static MODULE contents into the dynamic MODULE struct. */ + memcpy(mf,&of,sizeof(MODULE)); + + if(maxchan>0) { + if(!(mf->flags&UF_NNA)&&(mf->numchnnumchn; + else + if((mf->numvoices)&&(mf->numvoicesnumvoices; + + if(maxchannumchn) mf->flags |= UF_NNA; + + ok = !MikMod_SetNumVoices_internal(maxchan,-1); + } + + if(ok) ok = !SL_LoadSamples(); + if(ok) ok = !Player_Init(mf); + + if(modreader!=reader) { + _mm_delete_mem_reader(modreader); + modreader=reader; + MikMod_free(unpk); + } + _mm_iobase_revert(modreader); + + if(!ok) { + Player_Free_internal(mf); + return NULL; + } + return mf; +} + +MIKMODAPI MODULE* Player_LoadGeneric(MREADER *reader,int maxchan,BOOL curious) +{ + MODULE* result; + + MUTEX_LOCK(vars); + MUTEX_LOCK(lists); + result=Player_LoadGeneric_internal(reader,maxchan,curious); + MUTEX_UNLOCK(lists); + MUTEX_UNLOCK(vars); + + return result; +} + +MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,BOOL curious) +{ + MODULE* result=NULL; + MREADER* reader; + + 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); + } + return result; +} + +/* Loads a module given a file pointer. + File is loaded from the current file seek position. */ +MIKMODAPI MODULE* Player_LoadFP(FILE* fp,int maxchan,BOOL curious) +{ + MODULE* result=NULL; + struct MREADER* reader; + + if (fp && (reader=_mm_new_file_reader(fp)) != NULL) { + result=Player_LoadGeneric(reader,maxchan,curious); + _mm_delete_file_reader(reader); + } + return result; +} + +/* Open a module via its filename. The loader will initialize the specified + song-player 'player'. */ +MIKMODAPI MODULE* Player_Load(const CHAR* filename,int maxchan,BOOL curious) +{ + FILE *fp; + MODULE *mf=NULL; + + if((fp=_mm_fopen(filename,"rb")) != NULL) { + mf=Player_LoadFP(fp,maxchan,curious); + _mm_fclose(fp); + } + return mf; +} + +/* ex:set ts=4: */