📄 load_669.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_669.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $ Composer 669 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 SUNOSextern int fprintf(FILE *, const char *, ...);#endif/*========== Module structure *//* header */typedef struct S69HEADER { UBYTE marker[2]; CHAR message[108]; UBYTE nos; UBYTE nop; UBYTE looporder; UBYTE orders[0x80]; UBYTE tempos[0x80]; UBYTE breaks[0x80];} S69HEADER;/* sample information */typedef struct S69SAMPLE { CHAR filename[13]; SLONG length; SLONG loopbeg; SLONG loopend;} S69SAMPLE;/* encoded note */typedef struct S69NOTE { UBYTE a,b,c;} S69NOTE;/*========== Loader variables *//* current pattern */static S69NOTE* s69pat=NULL;/* Module header */static S69HEADER* mh=NULL;/* file type identification */static CHAR* S69_Version[]={ "Composer 669", "Extended 669"};/*========== Loader code */BOOL S69_Test(void){ UBYTE buf[0x80]; if(!_mm_read_UBYTES(buf,2,modreader)) return 0; /* look for id */ if(!memcmp(buf,"if",2) || !memcmp(buf,"JN",2)) { int i; /* skip song message */ _mm_fseek(modreader,108,SEEK_CUR); /* sanity checks */ if(_mm_read_UBYTE(modreader) > 64) return 0; if(_mm_read_UBYTE(modreader) > 128) return 0; if(_mm_read_UBYTE(modreader) > 127) return 0; /* check order table */ if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0; for(i=0;i<0x80;i++) if((buf[i]>=0x80)&&(buf[i]!=0xff)) return 0; /* check tempos table */ if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0; for(i=0;i<0x80;i++) if((!buf[i])||(buf[i]>32)) return 0; /* check pattern length table */ if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0; for(i=0;i<0x80;i++) if(buf[i]>0x3f) return 0; } else return 0; return 1;}BOOL S69_Init(void){ if(!(s69pat=(S69NOTE *)_mm_malloc(64*8*sizeof(S69NOTE)))) return 0; if(!(mh=(S69HEADER *)_mm_malloc(sizeof(S69HEADER)))) return 0; return 1;}void S69_Cleanup(void){ _mm_free(s69pat); _mm_free(mh);}static BOOL S69_LoadPatterns(void){ int track,row,channel; UBYTE note,inst,vol,effect,lastfx,lastval; S69NOTE *cur; int tracks=0; if(!AllocPatterns()) return 0; if(!AllocTracks()) return 0; for(track=0;track<of.numpat;track++) { /* set pattern break locations */ of.pattrows[track]=mh->breaks[track]+1; /* load the 669 pattern */ cur=s69pat; for(row=0;row<64;row++) { for(channel=0;channel<8;channel++,cur++) { cur->a = _mm_read_UBYTE(modreader); cur->b = _mm_read_UBYTE(modreader); cur->c = _mm_read_UBYTE(modreader); } } if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } /* translate the pattern */ for(channel=0;channel<8;channel++) { UniReset(); /* set pattern tempo */ UniPTEffect(0xf,78); UniPTEffect(0xf,mh->tempos[track]); lastfx=0xff,lastval=0; for(row=0;row<=mh->breaks[track];row++) { int a,b,c; /* fetch the encoded note */ a=s69pat[(row*8)+channel].a; b=s69pat[(row*8)+channel].b; c=s69pat[(row*8)+channel].c; /* decode it */ note=a>>2; inst=((a&0x3)<<4)|((b&0xf0)>>4); vol=b&0xf; if (a<0xff) { if (a<0xfe) { UniInstrument(inst); UniNote(note+2*OCTAVE); lastfx=0xff; /* reset background effect memory */ } UniPTEffect(0xc,vol<<2); } if ((c!=0xff)||(lastfx!=0xff)) { if(c==0xff) c=lastfx,effect=lastval; else effect=c&0xf; switch(c>>4) { case 0: /* porta up */ UniPTEffect(0x1,effect); lastfx=c,lastval=effect; break; case 1: /* porta down */ UniPTEffect(0x2,effect); lastfx=c,lastval=effect; break; case 2: /* porta to note */ UniPTEffect(0x3,effect); lastfx=c,lastval=effect; break; case 3: /* frequency adjust */ /* DMP converts this effect to S3M FF1. Why not ? */ UniEffect(UNI_S3MEFFECTF,0xf0|effect); break; case 4: /* vibrato */ UniPTEffect(0x4,effect); lastfx=c,lastval=effect; break; case 5: /* set speed */ if (effect) UniPTEffect(0xf,effect); else if(mh->marker[0]!=0x69) {#ifdef MIKMOD_DEBUG fprintf(stderr,"\r669: unsupported super fast tempo at pat=%d row=%d chan=%d\n", track,row,channel);#endif } break; } } UniNewline(); } if(!(of.tracks[tracks++]=UniDup())) return 0; } } return 1;}BOOL S69_Load(BOOL curious){ int i; SAMPLE *current; S69SAMPLE sample; /* module header */ _mm_read_UBYTES(mh->marker,2,modreader); _mm_read_UBYTES(mh->message,108,modreader); mh->nos=_mm_read_UBYTE(modreader); mh->nop=_mm_read_UBYTE(modreader); mh->looporder=_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->orders,0x80,modreader); for(i=0;i<0x80;i++) if ((mh->orders[i]>=0x80)&&(mh->orders[i]!=0xff)) { _mm_errno=MMERR_NOT_A_MODULE; return 1; } _mm_read_UBYTES(mh->tempos,0x80,modreader); for(i=0;i<0x80;i++) if ((!mh->tempos[i])||(mh->tempos[i]>32)) { _mm_errno=MMERR_NOT_A_MODULE; return 1; } _mm_read_UBYTES(mh->breaks,0x80,modreader); for(i=0;i<0x80;i++) if (mh->breaks[i]>0x3f) { _mm_errno=MMERR_NOT_A_MODULE; return 1; } /* set module variables */ of.initspeed=4; of.inittempo=78; of.songname=DupStr(mh->message,36,1); of.modtype=strdup(S69_Version[memcmp(mh->marker,"JN",2)==0]); of.numchn=8; of.numpat=mh->nop; of.numins=of.numsmp=mh->nos; of.numtrk=of.numchn*of.numpat; of.flags=UF_XMPERIODS|UF_LINEAR; for(i= 35;(i>= 0)&&(mh->message[i]==' ');i--) mh->message[i]=0; for(i=36+35;(i>=36+0)&&(mh->message[i]==' ');i--) mh->message[i]=0; for(i=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0; if((mh->message[0])||(mh->message[36])||(mh->message[72])) if((of.comment=(CHAR*)_mm_malloc(3*(36+1)+1))) { strncpy(of.comment,mh->message,36); strcat(of.comment,"\r"); if (mh->message[36]) strncat(of.comment,mh->message+36,36); strcat(of.comment,"\r"); if (mh->message[72]) strncat(of.comment,mh->message+72,36); strcat(of.comment,"\r"); of.comment[3*(36+1)]=0; } if(!AllocPositions(0x80)) return 0; for(i=0;i<0x80;i++) { if(mh->orders[i]>=mh->nop) break; of.positions[i]=mh->orders[i]; } of.numpos=i; of.reppos=mh->looporder<of.numpos?mh->looporder:0; if(!AllocSamples()) return 0; current=of.samples; for(i=0;i<of.numins;i++) { /* sample information */ _mm_read_UBYTES((UBYTE*)sample.filename,13,modreader); sample.length=_mm_read_I_SLONG(modreader); sample.loopbeg=_mm_read_I_SLONG(modreader); sample.loopend=_mm_read_I_SLONG(modreader); if (sample.loopend==0xfffff) sample.loopend=0; if((sample.length<0)||(sample.loopbeg<-1)||(sample.loopend<-1)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } current->samplename=DupStr(sample.filename,13,1); current->seekpos=0; current->speed=0; current->length=sample.length; current->loopstart=sample.loopbeg; current->loopend=sample.loopend; current->flags=(sample.loopbeg<sample.loopend)?SF_LOOP:0; current->volume=64; current++; } if(!S69_LoadPatterns()) return 0; return 1;}CHAR *S69_LoadTitle(void){ CHAR s[36]; _mm_fseek(modreader,2,SEEK_SET); if(!_mm_read_UBYTES(s,36,modreader)) return NULL; return(DupStr(s,36,1));}/*========== Loader information */MIKMODAPI MLOADER load_669={ NULL, "669", "669 (Composer 669, Unis 669)", S69_Init, S69_Test, S69_Load, S69_Cleanup, S69_LoadTitle};/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -