diff options
| author | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
|---|---|---|
| committer | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
| commit | 26f2bfde03420edad4de1f22cb3d515dc063b20d (patch) | |
| tree | 4a8c4abaf4795f38da70a4657c1a0fb3ba9debeb /apps/plugins/mikmod/load_far.c | |
| parent | d192bdf11e06e50645ecb5726658d4b691480a9a (diff) | |
| download | rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.zip rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.gz rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.bz2 rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.xz | |
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mikmod/load_far.c')
| -rw-r--r-- | apps/plugins/mikmod/load_far.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_far.c b/apps/plugins/mikmod/load_far.c new file mode 100644 index 0000000..69d48d6 --- /dev/null +++ b/apps/plugins/mikmod/load_far.c @@ -0,0 +1,346 @@ +/* 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: load_far.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ + + Farandole (FAR) module loader + +==============================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <stdio.h> +#ifdef HAVE_MEMORY_H +#include <memory.h> +#endif +#include <string.h> + +#include "mikmod_internals.h" + +#ifdef SUNOS +extern int fprintf(FILE *, const char *, ...); +#endif + +/*========== Module structure */ + +typedef struct FARHEADER1 { + UBYTE id[4]; /* file magic */ + CHAR songname[40]; /* songname */ + CHAR blah[3]; /* 13,10,26 */ + UWORD headerlen; /* remaining length of header in bytes */ + UBYTE version; + UBYTE onoff[16]; + UBYTE edit1[9]; + UBYTE speed; + UBYTE panning[16]; + UBYTE edit2[4]; + UWORD stlen; +} FARHEADER1; + +typedef struct FARHEADER2 { + UBYTE orders[256]; + UBYTE numpat; + UBYTE snglen; + UBYTE loopto; + UWORD patsiz[256]; +} FARHEADER2; + +typedef struct FARSAMPLE { + CHAR samplename[32]; + ULONG length; + UBYTE finetune; + UBYTE volume; + ULONG reppos; + ULONG repend; + UBYTE type; + UBYTE loop; +} FARSAMPLE; + +typedef struct FARNOTE { + UBYTE note,ins,vol,eff; +} FARNOTE; + +/*========== Loader variables */ + +static CHAR FAR_Version[] = "Farandole"; +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}; + +/*========== Loader code */ + +int FAR_Test(void) +{ + UBYTE id[47]; + + if(!_mm_read_UBYTES(id,47,modreader)) return 0; + if((memcmp(id,FARSIG,4))||(memcmp(id+44,FARSIG+4,3))) return 0; + return 1; +} + +int FAR_Init(void) +{ + if(!(mh1 = (FARHEADER1*)MikMod_malloc(sizeof(FARHEADER1)))) return 0; + if(!(mh2 = (FARHEADER2*)MikMod_malloc(sizeof(FARHEADER2)))) return 0; + if(!(pat = (FARNOTE*)MikMod_malloc(256*16*4*sizeof(FARNOTE)))) return 0; + + return 1; +} + +void FAR_Cleanup(void) +{ + MikMod_free(mh1); + MikMod_free(mh2); + MikMod_free(pat); +} + +static UBYTE *FAR_ConvertTrack(FARNOTE* n,int rows) +{ + int t,vibdepth=1; + + UniReset(); + for(t=0;t<rows;t++) { + if(n->note) { + UniInstrument(n->ins); + UniNote(n->note+3*OCTAVE-1); + } + if (n->vol&0xf) UniPTEffect(0xc,(n->vol&0xf)<<2); + if (n->eff) + switch(n->eff>>4) { + case 0x3: /* porta to note */ + UniPTEffect(0x3,(n->eff&0xf)<<4); + break; + case 0x4: /* retrigger */ + UniPTEffect(0x0e, 0x90 | (n->eff & 0x0f)); + break; + case 0x5: /* set vibrato depth */ + vibdepth=n->eff&0xf; + break; + case 0x6: /* vibrato */ + UniPTEffect(0x4,((n->eff&0xf)<<4)|vibdepth); + break; + case 0x7: /* volume slide up */ + UniPTEffect(0xa,(n->eff&0xf)<<4); + break; + case 0x8: /* volume slide down */ + UniPTEffect(0xa,n->eff&0xf); + break; + case 0xb: /* panning */ + UniPTEffect(0xe,0x80|(n->eff&0xf)); + break; + case 0xf: /* set speed */ + UniPTEffect(0xf,n->eff&0xf); + break; + + /* others not yet implemented */ + default: +#ifdef MIKMOD_DEBUG + fprintf(stderr,"\rFAR: unsupported effect %02X\n",n->eff); +#endif + break; + } + + UniNewline(); + n+=16; + } + return UniDup(); +} + +int FAR_Load(int curious) +{ + int t,u,tracks=0; + SAMPLE *q; + FARSAMPLE s; + FARNOTE *crow; + UBYTE smap[8]; + + /* try to read module header (first part) */ + _mm_read_UBYTES(mh1->id,4,modreader); + _mm_read_SBYTES(mh1->songname,40,modreader); + _mm_read_SBYTES(mh1->blah,3,modreader); + mh1->headerlen = _mm_read_I_UWORD (modreader); + mh1->version = _mm_read_UBYTE (modreader); + _mm_read_UBYTES(mh1->onoff,16,modreader); + _mm_read_UBYTES(mh1->edit1,9,modreader); + mh1->speed = _mm_read_UBYTE(modreader); + _mm_read_UBYTES(mh1->panning,16,modreader); + _mm_read_UBYTES(mh1->edit2,4,modreader); + mh1->stlen = _mm_read_I_UWORD (modreader); + + /* init modfile data */ + of.modtype = StrDup(FAR_Version); + of.songname = DupStr(mh1->songname,40,1); + of.numchn = 16; + of.initspeed = mh1->speed; + of.inittempo = 80; + of.reppos = 0; + of.flags |= UF_PANNING; + for(t=0;t<16;t++) of.panning[t]=mh1->panning[t]<<4; + + /* read songtext into comment field */ + if(mh1->stlen) + if (!ReadLinedComment(mh1->stlen, 66)) return 0; + + /* try to read module header (second part) */ + _mm_read_UBYTES(mh2->orders,256,modreader); + mh2->numpat = _mm_read_UBYTE(modreader); + mh2->snglen = _mm_read_UBYTE(modreader); + mh2->loopto = _mm_read_UBYTE(modreader); + _mm_read_I_UWORDS(mh2->patsiz,256,modreader); + + of.numpos = mh2->snglen; + if(!AllocPositions(of.numpos)) return 0; + for(t=0;t<of.numpos;t++) { + if(mh2->orders[t]==0xff) break; + of.positions[t] = mh2->orders[t]; + } + + /* count number of patterns stored in file */ + of.numpat = 0; + for(t=0;t<256;t++) + if(mh2->patsiz[t]) + if((t+1)>of.numpat) of.numpat=t+1; + of.numtrk = of.numpat*of.numchn; + + /* seek across eventual new data */ + _mm_fseek(modreader,mh1->headerlen-(869+mh1->stlen),SEEK_CUR); + + /* alloc track and pattern structures */ + if(!AllocTracks()) return 0; + if(!AllocPatterns()) return 0; + + for(t=0;t<of.numpat;t++) { + UBYTE rows=0,tempo; + + memset(pat,0,256*16*4*sizeof(FARNOTE)); + if(mh2->patsiz[t]) { + rows = _mm_read_UBYTE(modreader); + tempo = _mm_read_UBYTE(modreader); + + crow = pat; + /* file often allocates 64 rows even if there are less in pattern */ + if (mh2->patsiz[t]<2+(rows*16*4)) { + _mm_errno = MMERR_LOADING_PATTERN; + return 0; + } + for(u=(mh2->patsiz[t]-2)/4;u;u--,crow++) { + crow->note = _mm_read_UBYTE(modreader); + crow->ins = _mm_read_UBYTE(modreader); + crow->vol = _mm_read_UBYTE(modreader); + crow->eff = _mm_read_UBYTE(modreader); + } + + if(_mm_eof(modreader)) { + _mm_errno = MMERR_LOADING_PATTERN; + return 0; + } + + crow=pat; + of.pattrows[t] = rows; + for(u=16;u;u--,crow++) + if(!(of.tracks[tracks++]=FAR_ConvertTrack(crow,rows))) { + _mm_errno=MMERR_LOADING_PATTERN; + return 0; + } + } else + tracks+=16; + } + + /* read sample map */ + if(!_mm_read_UBYTES(smap,8,modreader)) { + _mm_errno = MMERR_LOADING_HEADER; + return 0; + } + + /* count number of samples used */ + of.numins = 0; + for(t=0;t<64;t++) + if(smap[t>>3]&(1<<(t&7))) of.numins=t+1; + of.numsmp = of.numins; + + /* alloc sample structs */ + if(!AllocSamples()) return 0; + + q = of.samples; + for(t=0;t<of.numsmp;t++) { + q->speed = 8363; + q->flags = SF_SIGNED; + if(smap[t>>3]&(1<<(t&7))) { + _mm_read_SBYTES(s.samplename,32,modreader); + s.length = _mm_read_I_ULONG(modreader); + s.finetune = _mm_read_UBYTE(modreader); + s.volume = _mm_read_UBYTE(modreader); + s.reppos = _mm_read_I_ULONG(modreader); + s.repend = _mm_read_I_ULONG(modreader); + s.type = _mm_read_UBYTE(modreader); + s.loop = _mm_read_UBYTE(modreader); + + q->samplename = DupStr(s.samplename,32,1); + q->length = s.length; + q->loopstart = s.reppos; + q->loopend = s.repend; + q->volume = s.volume<<2; + + if(s.type&1) q->flags|=SF_16BITS; + if(s.loop&8) q->flags|=SF_LOOP; + + q->seekpos = _mm_ftell(modreader); + _mm_fseek(modreader,q->length,SEEK_CUR); + } else + q->samplename = DupStr(NULL,0,0); + q++; + } + return 1; +} + +CHAR *FAR_LoadTitle(void) +{ + CHAR s[40]; + + _mm_fseek(modreader,4,SEEK_SET); + if(!_mm_read_UBYTES(s,40,modreader)) return NULL; + + return(DupStr(s,40,1)); +} + +/*========== Loader information */ + +MIKMODAPI MLOADER load_far={ + NULL, + "FAR", + "FAR (Farandole Composer)", + FAR_Init, + FAR_Test, + FAR_Load, + FAR_Cleanup, + FAR_LoadTitle +}; + +/* ex:set ts=4: */ |