load_stm.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:9k
源码类别:
Windows CE
开发平台:
C/C++
- /* 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_stm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
- Screamtracker 2 (STM) 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 */
- /* sample information */
- typedef struct STMSAMPLE {
- CHAR filename[12];
- UBYTE unused; /* 0x00 */
- UBYTE instdisk; /* Instrument disk */
- UWORD reserved;
- UWORD length; /* Sample length */
- UWORD loopbeg; /* Loop start point */
- UWORD loopend; /* Loop end point */
- UBYTE volume; /* Volume */
- UBYTE reserved2;
- UWORD c2spd; /* Good old c2spd */
- ULONG reserved3;
- UWORD isa;
- } STMSAMPLE;
- /* header */
- typedef struct STMHEADER {
- CHAR songname[20];
- CHAR trackername[8]; /* !Scream! for ST 2.xx */
- UBYTE unused; /* 0x1A */
- UBYTE filetype; /* 1=song, 2=module */
- UBYTE ver_major;
- UBYTE ver_minor;
- UBYTE inittempo; /* initspeed= stm inittempo>>4 */
- UBYTE numpat; /* number of patterns */
- UBYTE globalvol;
- UBYTE reserved[13];
- STMSAMPLE sample[31]; /* STM sample data */
- UBYTE patorder[128]; /* Docs say 64 - actually 128 */
- } STMHEADER;
- typedef struct STMNOTE {
- UBYTE note,insvol,volcmd,cmdinf;
- } STMNOTE;
- /*========== Loader variables */
- static STMNOTE *stmbuf = NULL;
- static STMHEADER *mh = NULL;
- /* tracker identifiers */
- static CHAR* STM_Version[STM_NTRACKERS] = {
- "Screamtracker 2",
- "Converted by MOD2STM (STM format)",
- "Wuzamod (STM format)"
- };
- /*========== Loader code */
- BOOL STM_Test(void)
- {
- UBYTE str[44];
- int t;
- _mm_fseek(modreader,20,SEEK_SET);
- _mm_read_UBYTES(str,44,modreader);
- if(str[9]!=2) return 0; /* STM Module = filetype 2 */
- /* Prevent false positives for S3M files */
- if(!memcmp(str+40,"SCRM",4))
- return 0;
- for (t=0;t<STM_NTRACKERS;t++)
- if(!memcmp(str,STM_Signatures[t],8))
- return 1;
- return 0;
- }
- BOOL STM_Init(void)
- {
- if(!(mh=(STMHEADER*)_mm_malloc(sizeof(STMHEADER)))) return 0;
- if(!(stmbuf=(STMNOTE*)_mm_calloc(64U*4,sizeof(STMNOTE)))) return 0;
- return 1;
- }
- static void STM_Cleanup(void)
- {
- _mm_free(mh);
- _mm_free(stmbuf);
- }
- static void STM_ConvertNote(STMNOTE *n)
- {
- UBYTE note,ins,vol,cmd,inf;
- /* extract the various information from the 4 bytes that make up a note */
- note = n->note;
- ins = n->insvol>>3;
- vol = (n->insvol&7)+((n->volcmd&0x70)>>1);
- cmd = n->volcmd&15;
- inf = n->cmdinf;
- if((ins)&&(ins<32)) UniInstrument(ins-1);
- /* special values of [SBYTE0] are handled here
- we have no idea if these strange values will ever be encountered.
- but it appears as those stms sound correct. */
- if((note==254)||(note==252)) {
- UniPTEffect(0xc,0); /* note cut */
- n->volcmd|=0x80;
- } else
- /* if note < 251, then all three bytes are stored in the file */
- if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf));
- if((!(n->volcmd&0x80))&&(vol<65)) UniPTEffect(0xc,vol);
- if(cmd!=255)
- switch(cmd) {
- case 1: /* Axx set speed to xx */
- UniPTEffect(0xf,inf>>4);
- break;
- case 2: /* Bxx position jump */
- UniPTEffect(0xb,inf);
- break;
- case 3: /* Cxx patternbreak to row xx */
- UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
- break;
- case 4: /* Dxy volumeslide */
- UniEffect(UNI_S3MEFFECTD,inf);
- break;
- case 5: /* Exy toneslide down */
- UniEffect(UNI_S3MEFFECTE,inf);
- break;
- case 6: /* Fxy toneslide up */
- UniEffect(UNI_S3MEFFECTF,inf);
- break;
- case 7: /* Gxx Tone portamento,speed xx */
- UniPTEffect(0x3,inf);
- break;
- case 8: /* Hxy vibrato */
- UniPTEffect(0x4,inf);
- break;
- case 9: /* Ixy tremor, ontime x, offtime y */
- UniEffect(UNI_S3MEFFECTI,inf);
- break;
- case 0: /* protracker arpeggio */
- if(!inf) break;
- /* fall through */
- case 0xa: /* Jxy arpeggio */
- UniPTEffect(0x0,inf);
- break;
- case 0xb: /* Kxy Dual command H00 & Dxy */
- UniPTEffect(0x4,0);
- UniEffect(UNI_S3MEFFECTD,inf);
- break;
- case 0xc: /* Lxy Dual command G00 & Dxy */
- UniPTEffect(0x3,0);
- UniEffect(UNI_S3MEFFECTD,inf);
- break;
- /* Support all these above, since ST2 can LOAD these values but can
- actually only play up to J - and J is only half-way implemented
- in ST2 */
- case 0x18: /* Xxx amiga panning command 8xx */
- UniPTEffect(0x8,inf);
- of.flags |= UF_PANNING;
- break;
- }
- }
- static UBYTE *STM_ConvertTrack(STMNOTE *n)
- {
- int t;
- UniReset();
- for(t=0;t<64;t++) {
- STM_ConvertNote(n);
- UniNewline();
- n+=of.numchn;
- }
- return UniDup();
- }
- static BOOL STM_LoadPatterns(void)
- {
- int t,s,tracks=0;
- if(!AllocPatterns()) return 0;
- if(!AllocTracks()) return 0;
- /* Allocate temporary buffer for loading and converting the patterns */
- for(t=0;t<of.numpat;t++) {
- for(s=0;s<(64U*of.numchn);s++) {
- stmbuf[s].note = _mm_read_UBYTE(modreader);
- stmbuf[s].insvol = _mm_read_UBYTE(modreader);
- stmbuf[s].volcmd = _mm_read_UBYTE(modreader);
- stmbuf[s].cmdinf = _mm_read_UBYTE(modreader);
- }
- if(_mm_eof(modreader)) {
- _mm_errno = MMERR_LOADING_PATTERN;
- return 0;
- }
- for(s=0;s<of.numchn;s++)
- if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
- }
- return 1;
- }
- BOOL STM_Load(BOOL curious)
- {
- int t;
- ULONG MikMod_ISA; /* We must generate our own ISA, it's not stored in stm */
- SAMPLE *q;
- /* try to read stm header */
- _mm_read_string(mh->songname,20,modreader);
- _mm_read_string(mh->trackername,8,modreader);
- mh->unused =_mm_read_UBYTE(modreader);
- mh->filetype =_mm_read_UBYTE(modreader);
- mh->ver_major =_mm_read_UBYTE(modreader);
- mh->ver_minor =_mm_read_UBYTE(modreader);
- mh->inittempo =_mm_read_UBYTE(modreader);
- if(!mh->inittempo) {
- _mm_errno=MMERR_NOT_A_MODULE;
- return 0;
- }
- mh->numpat =_mm_read_UBYTE(modreader);
- mh->globalvol =_mm_read_UBYTE(modreader);
- _mm_read_UBYTES(mh->reserved,13,modreader);
- for(t=0;t<31;t++) {
- STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
- _mm_read_string(s->filename,12,modreader);
- s->unused =_mm_read_UBYTE(modreader);
- s->instdisk =_mm_read_UBYTE(modreader);
- s->reserved =_mm_read_I_UWORD(modreader);
- s->length =_mm_read_I_UWORD(modreader);
- s->loopbeg =_mm_read_I_UWORD(modreader);
- s->loopend =_mm_read_I_UWORD(modreader);
- s->volume =_mm_read_UBYTE(modreader);
- s->reserved2=_mm_read_UBYTE(modreader);
- s->c2spd =_mm_read_I_UWORD(modreader);
- s->reserved3=_mm_read_I_ULONG(modreader);
- s->isa =_mm_read_I_UWORD(modreader);
- }
- _mm_read_UBYTES(mh->patorder,128,modreader);
- if(_mm_eof(modreader)) {
- _mm_errno = MMERR_LOADING_HEADER;
- return 0;
- }
- /* set module variables */
- for(t=0;t<STM_NTRACKERS;t++)
- if(!memcmp(mh->trackername,STM_Signatures[t],8)) break;
- of.modtype = strdup(STM_Version[t]);
- of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
- of.numpat = mh->numpat;
- of.inittempo = 125; /* mh->inittempo+0x1c; */
- of.initspeed = mh->inittempo>>4;
- of.numchn = 4; /* get number of channels */
- of.reppos = 0;
- of.flags |= UF_S3MSLIDES;
- of.bpmlimit = 32;
- t=0;
- if(!AllocPositions(0x80)) return 0;
- /* 99 terminates the patorder list */
- while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) {
- of.positions[t]=mh->patorder[t];
- t++;
- }
- if(mh->patorder[t]<=99) t++;
- of.numpos=t;
- of.numtrk=of.numpat*of.numchn;
- of.numins=of.numsmp=31;
- if(!AllocSamples()) return 0;
- if(!STM_LoadPatterns()) return 0;
- MikMod_ISA=_mm_ftell(modreader);
- MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
- for(q=of.samples,t=0;t<of.numsmp;t++,q++) {
- /* load sample info */
- q->samplename = DupStr(mh->sample[t].filename,12,1);
- q->speed = (mh->sample[t].c2spd * 8363) / 8448;
- q->volume = mh->sample[t].volume;
- q->length = mh->sample[t].length;
- if (/*(!mh->sample[t].volume)||*/(q->length==1)) q->length=0;
- q->loopstart = mh->sample[t].loopbeg;
- q->loopend = mh->sample[t].loopend;
- q->seekpos = MikMod_ISA;
- MikMod_ISA+=q->length;
- MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
- /* contrary to the STM specs, sample data is signed */
- q->flags = SF_SIGNED;
- if(q->loopend && q->loopend != 0xffff)
- q->flags|=SF_LOOP;
- }
- return 1;
- }
- CHAR *STM_LoadTitle(void)
- {
- CHAR s[20];
- _mm_fseek(modreader,0,SEEK_SET);
- if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
- return(DupStr(s,20,1));
- }
- /*========== Loader information */
- MIKMODAPI MLOADER load_stm={
- NULL,
- "STM",
- "STM (Scream Tracker)",
- STM_Init,
- STM_Test,
- STM_Load,
- STM_Cleanup,
- STM_LoadTitle
- };
- /* ex:set ts=4: */