📄 mloader.c
字号:
/* MikMod sound library (c) 1998, 1999 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: mloader.c 1497 2004-12-21 17:38:38Z slouken $ These routines are used to access the available module loaders==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <string.h>#include "mikmod_internals.h" MREADER *modreader; MODULE of;static MLOADER *firstloader=NULL;UWORD finetune[16]={ 8363,8413,8463,8529,8581,8651,8723,8757, 7895,7941,7985,8046,8107,8169,8232,8280};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=_mm_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); } 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;}void _mm_unregisterloaders(void){ MLOADER *cruise=firstloader, *ldr; while ( cruise ) { ldr = cruise; cruise = cruise->next; ldr->next = NULL; } firstloader = NULL;}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*)_mm_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'; of.comment[len]=0; /* just in case */ } if(!of.comment[0]) { free(of.comment); of.comment=NULL; } return 1;}BOOL ReadLinedComment(UWORD lines,UWORD linelen){ CHAR *tempcomment,*line,*storage; UWORD total=0,t,len=lines*linelen; int i; if (lines) { if(!(tempcomment=(CHAR*)_mm_malloc(len+1))) return 0; if(!(storage=(CHAR*)_mm_malloc(linelen+1))) { free(tempcomment); return 0; } _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*)_mm_malloc(total+1))) { free(storage); free(tempcomment); 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"); } free(storage); free(tempcomment); } } return 1;}BOOL AllocPositions(int total){ if(!total) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } if(!(of.positions=_mm_calloc(total,sizeof(UWORD)))) return 0; return 1;}BOOL AllocPatterns(void){ int s,t,tracks = 0; if((!of.numpat)||(!of.numchn)) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } /* Allocate track sequencing array */ if(!(of.patterns=(UWORD*)_mm_calloc((ULONG)(of.numpat+1)*of.numchn,sizeof(UWORD)))) return 0; if(!(of.pattrows=(UWORD*)_mm_calloc(of.numpat+1,sizeof(UWORD)))) return 0; for(t=0;t<=of.numpat;t++) { of.pattrows[t]=64; for(s=0;s<of.numchn;s++) of.patterns[(t*of.numchn)+s]=tracks++; } return 1;}BOOL AllocTracks(void){ if(!of.numtrk) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } if(!(of.tracks=(UBYTE **)_mm_calloc(of.numtrk,sizeof(UBYTE *)))) return 0; return 1;}BOOL AllocInstruments(void){ int t,n; if(!of.numins) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } if(!(of.instruments=(INSTRUMENT*)_mm_calloc(of.numins,sizeof(INSTRUMENT)))) return 0; for(t=0;t<of.numins;t++) { 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;}BOOL AllocSamples(void){ UWORD u; if(!of.numsmp) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } if(!(of.samples=(SAMPLE*)_mm_calloc(of.numsmp,sizeof(SAMPLE)))) return 0; for(u=0;u<of.numsmp;u++) { of.samples[u].panning = 128; /* center */ of.samples[u].handle = -1; of.samples[u].globvol = 64; of.samples[u].volume = 64; } return 1;}static BOOL ML_LoadSamples(void){ SAMPLE *s; int u; for(u=of.numsmp,s=of.samples;u;u--,s++) if(s->length) 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(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;t<len;t++) if (!s[t]) break; if (t<len) len=t; } /* 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*)_mm_malloc(sizeof(CHAR)*(len+1)))) { for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t]; d[len]=0; } return d;}static void ML_XFreeSample(SAMPLE *s){ if(s->handle>=0) MD_SampleUnload(s->handle); if(s->samplename) free(s->samplename);}static void ML_XFreeInstrument(INSTRUMENT *i){ if(i->insname) free(i->insname);}static void ML_FreeEx(MODULE *mf){ UWORD t; if(mf->songname) free(mf->songname); if(mf->comment) free(mf->comment); if(mf->modtype) free(mf->modtype); if(mf->positions) free(mf->positions); if(mf->patterns) free(mf->patterns); if(mf->pattrows) free(mf->pattrows); if(mf->tracks) { for(t=0;t<mf->numtrk;t++) if(mf->tracks[t]) free(mf->tracks[t]); free(mf->tracks); } if(mf->instruments) { for(t=0;t<mf->numins;t++) ML_XFreeInstrument(&mf->instruments[t]); free(mf->instruments); } if(mf->samples) { for(t=0;t<mf->numsmp;t++) if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]); free(mf->samples); } memset(mf,0,sizeof(MODULE)); if(mf!=&of) free(mf);}static MODULE *ML_AllocUniMod(void){ MODULE *mf; return (mf=_mm_malloc(sizeof(MODULE)));}void Player_Free_internal(MODULE *mf){ if(mf) { Player_Exit_internal(mf); ML_FreeEx(mf); }}void Player_Free(MODULE *mf){ MUTEX_LOCK(vars); Player_Free_internal(mf); MUTEX_UNLOCK(vars);}static CHAR* Player_LoadTitle_internal(MREADER *reader){ MLOADER *l; modreader=reader; _mm_errno = 0; _mm_critical = 0; _mm_iobase_setcur(modreader); /* 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(_mm_errorhandler) _mm_errorhandler(); return NULL; } return l->LoadTitle();}CHAR* Player_LoadTitle(CHAR* filename){ CHAR* result=NULL; FILE* fp; MREADER* reader; if((fp=_mm_fopen(filename,"rb"))) { if((reader=_mm_new_file_reader(fp))) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); _mm_delete_file_reader(reader); } fclose(fp); } return result;}/* Loads a module given an reader */MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,BOOL curious){ int t; MLOADER *l; BOOL ok; MODULE *mf; modreader = reader; _mm_errno = 0; _mm_critical = 0; _mm_iobase_setcur(modreader); /* 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(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(); return NULL; } /* init unitrk routines */ if(!UniInit()) { if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(); return NULL; } /* load the song using the song's loader variable */ memset(&of,0,sizeof(MODULE)); of.initvolume = 128; /* init panning array */ for(t=0; t<64; t++) of.panning[t] = ((t+1)&2) ? 255 : 0; for(t=0; t<64; t++) of.chanvol[t] = 64; /* init module loader and load the header / patterns */ if(l->Init()) { _mm_rewind(modreader); ok = l->Load(curious); } else ok = 0; /* free loader and unitrk allocations */ l->Cleanup(); UniCleanup(); if(!ok) { ML_FreeEx(&of); if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(); return NULL; } if(!ML_LoadSamples()) { ML_FreeEx(&of); if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(); return NULL; } if(!(mf=ML_AllocUniMod())) { ML_FreeEx(&of); _mm_rewind(modreader);_mm_iobase_revert(); if(_mm_errorhandler) _mm_errorhandler(); return NULL; } /* Copy the static MODULE contents into the dynamic MODULE struct. */ memcpy(mf,&of,sizeof(MODULE)); _mm_iobase_revert(); if(maxchan>0) { if(!(mf->flags&UF_NNA)&&(mf->numchn<maxchan)) maxchan = mf->numchn; else if((mf->numvoices)&&(mf->numvoices<maxchan)) maxchan = mf->numvoices; if(maxchan<mf->numchn) mf->flags |= UF_NNA; if(MikMod_SetNumVoices_internal(maxchan,-1)) { Player_Free(mf); return NULL; } } if(SL_LoadSamples()) { Player_Free_internal(mf); return NULL; } if(Player_Init(mf)) { Player_Free_internal(mf); mf=NULL; } return mf;}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;}/* Loads a module given a file pointer. File is loaded from the current file seek position. */MODULE* Player_LoadFP(FILE* fp,int maxchan,BOOL curious){ MODULE* result=NULL; struct MREADER* reader=_mm_new_file_reader (fp); if (reader) { 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'. */MODULE* Player_Load(CHAR* filename,int maxchan,BOOL curious){ FILE *fp; MODULE *mf=NULL; if((fp=_mm_fopen(filename,"rb"))) { mf=Player_LoadFP(fp,maxchan,curious); fclose(fp); } return mf;}/* SDL_RWops compatability *//* Open a module via an SDL_rwop. The loader will initialize the specified song-player 'player'. */MODULE* Player_LoadRW(SDL_RWops *rw,int maxchan,BOOL curious){ MODULE* result=NULL; struct MREADER* reader=_mm_new_rwops_reader (rw); if (reader) { result=Player_LoadGeneric(reader,maxchan,curious); _mm_delete_rwops_reader(reader); } return result;}/* End SDL_RWops compatability *//* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -