From 26f2bfde03420edad4de1f22cb3d515dc063b20d Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Sun, 12 Dec 2010 15:03:30 +0000 Subject: 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 --- apps/plugins/mikmod/load_ult.c | 339 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 apps/plugins/mikmod/load_ult.c (limited to 'apps/plugins/mikmod/load_ult.c') diff --git a/apps/plugins/mikmod/load_ult.c b/apps/plugins/mikmod/load_ult.c new file mode 100644 index 0000000000..aca2407a4a --- /dev/null +++ b/apps/plugins/mikmod/load_ult.c @@ -0,0 +1,339 @@ +/* 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_ult.c,v 1.3 2010/01/12 03:30:32 realtech Exp $ + + Ultratracker (ULT) module loader + +==============================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +#include "mikmod_internals.h" + +#ifdef SUNOS +extern int fprintf(FILE *, const char *, ...); +#endif + +/*========== Module structure */ + +/* header */ +typedef struct ULTHEADER { + CHAR id[16]; + CHAR songtitle[32]; + UBYTE reserved; +} ULTHEADER; + +/* sample information */ +typedef struct ULTSAMPLE { + CHAR samplename[32]; + CHAR dosname[12]; + SLONG loopstart; + SLONG loopend; + SLONG sizestart; + SLONG sizeend; + UBYTE volume; + UBYTE flags; + UWORD speed; + SWORD finetune; +} ULTSAMPLE; + +typedef struct ULTEVENT { + UBYTE note,sample,eff,dat1,dat2; +} ULTEVENT; + +/*========== Loader variables */ + +#define ULTS_16BITS 4 +#define ULTS_LOOP 8 +#define ULTS_REVERSE 16 + +#define ULT_VERSION_LEN 18 +static CHAR ULT_Version[ULT_VERSION_LEN]="Ultra Tracker v1.x"; + +static ULTEVENT ev; + +/*========== Loader code */ + +int ULT_Test(void) +{ + CHAR id[16]; + + if(!_mm_read_string(id,15,modreader)) return 0; + if(strncmp(id,"MAS_UTrack_V00",14)) return 0; + if((id[14]<'1')||(id[14]>'4')) return 0; + return 1; +} + +int ULT_Init(void) +{ + return 1; +} + +void ULT_Cleanup(void) +{ +} + +static UBYTE ReadUltEvent(ULTEVENT* event) +{ + UBYTE flag,rep=1; + + flag = _mm_read_UBYTE(modreader); + if(flag==0xfc) { + rep = _mm_read_UBYTE(modreader); + event->note =_mm_read_UBYTE(modreader); + } else + event->note = flag; + + event->sample =_mm_read_UBYTE(modreader); + event->eff =_mm_read_UBYTE(modreader); + event->dat1 =_mm_read_UBYTE(modreader); + event->dat2 =_mm_read_UBYTE(modreader); + + return rep; +} + +int ULT_Load(int curious) +{ + int t,u,tracks=0; + SAMPLE *q; + ULTSAMPLE s; + ULTHEADER mh; + UBYTE nos,noc,rbnop; + + /* try to read module header */ + _mm_read_string(mh.id,15,modreader); + _mm_read_string(mh.songtitle,32,modreader); + mh.reserved=_mm_read_UBYTE(modreader); + + if(_mm_eof(modreader)) { + _mm_errno = MMERR_LOADING_HEADER; + return 0; + } + + ULT_Version[ULT_VERSION_LEN-1]='3'+(mh.id[14]-'1'); + of.modtype = DupStr(ULT_Version,ULT_VERSION_LEN,1); + of.initspeed = 6; + of.inittempo = 125; + of.reppos = 0; + + /* read songtext */ + if ((mh.id[14]>'1')&&(mh.reserved)) + if(!ReadLinedComment(mh.reserved * 32, 32)) return 0; + + nos=_mm_read_UBYTE(modreader); + if(_mm_eof(modreader)) { + _mm_errno = MMERR_LOADING_HEADER; + return 0; + } + + of.songname=DupStr(mh.songtitle,32,1); + of.numins=of.numsmp=nos; + + if(!AllocSamples()) return 0; + q = of.samples; + for(t=0;t='4')?_mm_read_I_UWORD(modreader):8363; + s.finetune =_mm_read_I_SWORD(modreader); + + if(_mm_eof(modreader)) { + _mm_errno = MMERR_LOADING_SAMPLEINFO; + return 0; + } + + q->samplename=DupStr(s.samplename,32,1); + /* The correct formula for the coefficient would be + pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point + here, we'll use a first order approximation here. + 1/567290 == Ln(2)/OCTAVE/32768 */ + q->speed=s.speed+s.speed*(((SLONG)s.speed*(SLONG)s.finetune)/567290); + q->length = s.sizeend-s.sizestart; + q->volume = s.volume>>2; + q->loopstart = s.loopstart; + q->loopend = s.loopend; + q->flags = SF_SIGNED; + if(s.flags&ULTS_LOOP) q->flags|=SF_LOOP; + if(s.flags&ULTS_16BITS) { + s.sizeend+=(s.sizeend-s.sizestart); + s.sizestart<<=1; + q->flags|=SF_16BITS; + q->loopstart>>=1; + q->loopend>>=1; + } + q++; + } + + if(!AllocPositions(256)) return 0; + for(t=0;t<256;t++) + of.positions[t]=_mm_read_UBYTE(modreader); + for(t=0;t<256;t++) + if(of.positions[t]==255) { + of.positions[t]=LAST_PATTERN; + break; + } + of.numpos=t; + + noc=_mm_read_UBYTE(modreader); + rbnop=_mm_read_UBYTE(modreader); + + of.numchn=++noc; + of.numpat=++rbnop; + of.numtrk=of.numchn*of.numpat; + if(!AllocTracks()) return 0; + if(!AllocPatterns()) return 0; + for(u=0;u=UF_MAXCHAN) + of.numchn=UF_MAXCHAN - 1; + + /* read pan position table for v1.5 and higher */ + if(mh.id[14]>='3') { + for(t=0;t>4; + switch(eff) { + case 0x3: /* tone portamento */ + UniEffect(UNI_ITEFFECTG,ev.dat2); + break; + case 0x5: + break; + case 0x9: /* sample offset */ + offset=(ev.dat2<<8)|((ev.eff&0xf)==9?ev.dat1:0); + UniEffect(UNI_ULTEFFECT9,offset); + break; + case 0xb: /* panning */ + UniPTEffect(8,ev.dat2*0xf); + of.flags |= UF_PANNING; + break; + case 0xc: /* volume */ + UniPTEffect(eff,ev.dat2>>2); + break; + default: + UniPTEffect(eff,ev.dat2); + break; + } + + /* second effect */ + eff=ev.eff&0xf; + switch(eff) { + case 0x3: /* tone portamento */ + UniEffect(UNI_ITEFFECTG,ev.dat1); + break; + case 0x5: + break; + case 0x9: /* sample offset */ + if((ev.eff>>4)!=9) + UniEffect(UNI_ULTEFFECT9,((UWORD)ev.dat1)<<8); + break; + case 0xb: /* panning */ + UniPTEffect(8,ev.dat1*0xf); + of.flags |= UF_PANNING; + break; + case 0xc: /* volume */ + UniPTEffect(eff,ev.dat1>>2); + break; + default: + UniPTEffect(eff,ev.dat1); + break; + } + + UniNewline(); + row++; + } + } + if(!(of.tracks[t]=UniDup())) return 0; + } + return 1; +} + +CHAR *ULT_LoadTitle(void) +{ + CHAR s[32]; + + _mm_fseek(modreader,15,SEEK_SET); + if(!_mm_read_UBYTES(s,32,modreader)) return NULL; + + return(DupStr(s,32,1)); +} + +/*========== Loader information */ + +MIKMODAPI MLOADER load_ult={ + NULL, + "ULT", + "ULT (UltraTracker)", + ULT_Init, + ULT_Test, + ULT_Load, + ULT_Cleanup, + ULT_LoadTitle +}; + + +/* ex:set ts=4: */ -- cgit v1.2.3