load_669.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:8k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* MikMod sound library
  2. (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
  3. AUTHORS for complete list.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  17. 02111-1307, USA.
  18. */
  19. /*==============================================================================
  20.   $Id: load_669.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   Composer 669 module loader
  22. ==============================================================================*/
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #include <stdio.h>
  30. #ifdef HAVE_MEMORY_H
  31. #include <memory.h>
  32. #endif
  33. #include <string.h>
  34. #include "mikmod_internals.h"
  35. #ifdef SUNOS
  36. extern int fprintf(FILE *, const char *, ...);
  37. #endif
  38. /*========== Module structure */
  39. /* header */
  40. typedef struct S69HEADER {   
  41. UBYTE marker[2];
  42. CHAR message[108];
  43. UBYTE nos;
  44. UBYTE nop;
  45. UBYTE looporder;
  46. UBYTE orders[0x80];
  47. UBYTE tempos[0x80];
  48. UBYTE breaks[0x80];
  49. } S69HEADER;
  50. /* sample information */
  51. typedef struct S69SAMPLE {
  52. CHAR filename[13];
  53. SLONG length;
  54. SLONG loopbeg;
  55. SLONG loopend;
  56. } S69SAMPLE;
  57. /* encoded note */
  58. typedef struct S69NOTE {
  59. UBYTE a,b,c;
  60. } S69NOTE;
  61. /*========== Loader variables */
  62. /* current pattern */
  63. static S69NOTE* s69pat=NULL;
  64. /* Module header */
  65. static S69HEADER* mh=NULL;
  66. /* file type identification */
  67. static CHAR* S69_Version[]={
  68. "Composer 669",
  69. "Extended 669"
  70. };
  71. /*========== Loader code */
  72. BOOL S69_Test(void)
  73. {
  74. UBYTE buf[0x80];
  75. if(!_mm_read_UBYTES(buf,2,modreader))
  76. return 0;
  77. /* look for id */
  78. if(!memcmp(buf,"if",2) || !memcmp(buf,"JN",2)) {
  79. int i;
  80. /* skip song message */
  81. _mm_fseek(modreader,108,SEEK_CUR);
  82. /* sanity checks */
  83. if(_mm_read_UBYTE(modreader) > 64) return 0;
  84. if(_mm_read_UBYTE(modreader) > 128) return 0;
  85. if(_mm_read_UBYTE(modreader) > 127) return 0;
  86. /* check order table */
  87. if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
  88. for(i=0;i<0x80;i++)
  89. if((buf[i]>=0x80)&&(buf[i]!=0xff)) return 0;
  90. /* check tempos table */
  91. if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
  92. for(i=0;i<0x80;i++)
  93. if((!buf[i])||(buf[i]>32)) return 0;
  94. /* check pattern length table */
  95. if(!_mm_read_UBYTES(buf,0x80,modreader)) return 0;
  96. for(i=0;i<0x80;i++)
  97. if(buf[i]>0x3f) return 0;
  98. } else
  99. return 0;
  100. return 1;
  101. }
  102. BOOL S69_Init(void)
  103. {
  104. if(!(s69pat=(S69NOTE *)_mm_malloc(64*8*sizeof(S69NOTE)))) return 0;
  105. if(!(mh=(S69HEADER *)_mm_malloc(sizeof(S69HEADER)))) return 0;
  106. return 1;
  107. }
  108. void S69_Cleanup(void)
  109. {
  110. _mm_free(s69pat);
  111. _mm_free(mh);
  112. }
  113. static BOOL S69_LoadPatterns(void)
  114. {
  115. int track,row,channel;
  116. UBYTE note,inst,vol,effect,lastfx,lastval;
  117. S69NOTE *cur;
  118. int tracks=0;
  119. if(!AllocPatterns()) return 0;
  120. if(!AllocTracks()) return 0;
  121. for(track=0;track<of.numpat;track++) {
  122. /* set pattern break locations */
  123. of.pattrows[track]=mh->breaks[track]+1;
  124. /* load the 669 pattern */
  125. cur=s69pat;
  126. for(row=0;row<64;row++) {
  127. for(channel=0;channel<8;channel++,cur++) {
  128. cur->a = _mm_read_UBYTE(modreader);
  129. cur->b = _mm_read_UBYTE(modreader);
  130. cur->c = _mm_read_UBYTE(modreader);
  131. }
  132. }
  133. if(_mm_eof(modreader)) {
  134. _mm_errno = MMERR_LOADING_PATTERN;
  135. return 0;
  136. }
  137. /* translate the pattern */
  138. for(channel=0;channel<8;channel++) {
  139. UniReset();
  140. /* set pattern tempo */
  141. UniPTEffect(0xf,78);
  142. UniPTEffect(0xf,mh->tempos[track]);
  143. lastfx=0xff,lastval=0;
  144. for(row=0;row<=mh->breaks[track];row++) {
  145. int a,b,c;
  146. /* fetch the encoded note */
  147. a=s69pat[(row*8)+channel].a;
  148. b=s69pat[(row*8)+channel].b;
  149. c=s69pat[(row*8)+channel].c;
  150. /* decode it */
  151. note=a>>2;
  152. inst=((a&0x3)<<4)|((b&0xf0)>>4);
  153. vol=b&0xf;
  154. if (a<0xff) {
  155. if (a<0xfe) {
  156. UniInstrument(inst);
  157. UniNote(note+2*OCTAVE);
  158. lastfx=0xff; /* reset background effect memory */
  159. }
  160. UniPTEffect(0xc,vol<<2);
  161. }
  162. if ((c!=0xff)||(lastfx!=0xff)) {
  163. if(c==0xff)
  164. c=lastfx,effect=lastval;
  165. else
  166. effect=c&0xf;
  167. switch(c>>4) {
  168. case 0: /* porta up */
  169. UniPTEffect(0x1,effect);
  170. lastfx=c,lastval=effect;
  171. break;
  172. case 1: /* porta down */
  173. UniPTEffect(0x2,effect);
  174. lastfx=c,lastval=effect;
  175. break;
  176. case 2: /* porta to note */
  177. UniPTEffect(0x3,effect);
  178. lastfx=c,lastval=effect;
  179. break;
  180. case 3: /* frequency adjust */
  181. /* DMP converts this effect to S3M FF1. Why not ? */
  182. UniEffect(UNI_S3MEFFECTF,0xf0|effect);
  183. break;
  184. case 4: /* vibrato */
  185. UniPTEffect(0x4,effect);
  186. lastfx=c,lastval=effect;
  187. break;
  188. case 5: /* set speed */
  189. if (effect)
  190. UniPTEffect(0xf,effect);
  191. else 
  192.   if(mh->marker[0]!=0x69) {
  193. #ifdef MIKMOD_DEBUG
  194. fprintf(stderr,"r669: unsupported super fast tempo at pat=%d row=%d chan=%dn",
  195.        track,row,channel);
  196. #endif
  197. }
  198. break;
  199. }
  200. }
  201. UniNewline();
  202. }
  203. if(!(of.tracks[tracks++]=UniDup())) return 0;
  204. }
  205. }
  206. return 1;
  207. }
  208. BOOL S69_Load(BOOL curious)
  209. {
  210. int i;
  211. SAMPLE *current;
  212. S69SAMPLE sample;
  213. /* module header */
  214. _mm_read_UBYTES(mh->marker,2,modreader);
  215. _mm_read_UBYTES(mh->message,108,modreader);
  216. mh->nos=_mm_read_UBYTE(modreader);
  217. mh->nop=_mm_read_UBYTE(modreader);
  218. mh->looporder=_mm_read_UBYTE(modreader);
  219. _mm_read_UBYTES(mh->orders,0x80,modreader);
  220. for(i=0;i<0x80;i++)
  221. if ((mh->orders[i]>=0x80)&&(mh->orders[i]!=0xff)) {
  222. _mm_errno=MMERR_NOT_A_MODULE;
  223. return 1;
  224. }
  225. _mm_read_UBYTES(mh->tempos,0x80,modreader);
  226. for(i=0;i<0x80;i++)
  227. if ((!mh->tempos[i])||(mh->tempos[i]>32)) {
  228. _mm_errno=MMERR_NOT_A_MODULE;
  229. return 1;
  230. }
  231. _mm_read_UBYTES(mh->breaks,0x80,modreader);
  232. for(i=0;i<0x80;i++)
  233. if (mh->breaks[i]>0x3f) {
  234. _mm_errno=MMERR_NOT_A_MODULE;
  235. return 1;
  236. }
  237. /* set module variables */
  238. of.initspeed=4;
  239. of.inittempo=78;
  240. of.songname=DupStr(mh->message,36,1);
  241. of.modtype=strdup(S69_Version[memcmp(mh->marker,"JN",2)==0]);
  242. of.numchn=8;
  243. of.numpat=mh->nop;
  244. of.numins=of.numsmp=mh->nos;
  245. of.numtrk=of.numchn*of.numpat;
  246. of.flags=UF_XMPERIODS|UF_LINEAR;
  247. for(i=   35;(i>=   0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
  248. for(i=36+35;(i>=36+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
  249. for(i=72+35;(i>=72+0)&&(mh->message[i]==' ');i--) mh->message[i]=0;
  250. if((mh->message[0])||(mh->message[36])||(mh->message[72]))
  251. if((of.comment=(CHAR*)_mm_malloc(3*(36+1)+1))) {
  252. strncpy(of.comment,mh->message,36);
  253. strcat(of.comment,"r");
  254. if (mh->message[36]) strncat(of.comment,mh->message+36,36);
  255. strcat(of.comment,"r");
  256. if (mh->message[72]) strncat(of.comment,mh->message+72,36);
  257. strcat(of.comment,"r");
  258. of.comment[3*(36+1)]=0;
  259. }
  260. if(!AllocPositions(0x80)) return 0;
  261. for(i=0;i<0x80;i++) {
  262. if(mh->orders[i]>=mh->nop) break;
  263. of.positions[i]=mh->orders[i];
  264. }
  265. of.numpos=i;
  266. of.reppos=mh->looporder<of.numpos?mh->looporder:0;
  267. if(!AllocSamples()) return 0;
  268. current=of.samples;
  269. for(i=0;i<of.numins;i++) {
  270. /* sample information */
  271. _mm_read_UBYTES((UBYTE*)sample.filename,13,modreader);
  272. sample.length=_mm_read_I_SLONG(modreader);
  273. sample.loopbeg=_mm_read_I_SLONG(modreader);
  274. sample.loopend=_mm_read_I_SLONG(modreader);
  275. if (sample.loopend==0xfffff) sample.loopend=0;
  276. if((sample.length<0)||(sample.loopbeg<-1)||(sample.loopend<-1)) {
  277. _mm_errno = MMERR_LOADING_HEADER;
  278. return 0;
  279. }
  280. current->samplename=DupStr(sample.filename,13,1);
  281. current->seekpos=0;
  282. current->speed=0;
  283. current->length=sample.length;
  284. current->loopstart=sample.loopbeg;
  285. current->loopend=sample.loopend;
  286. current->flags=(sample.loopbeg<sample.loopend)?SF_LOOP:0;
  287. current->volume=64;
  288. current++;
  289. }
  290. if(!S69_LoadPatterns()) return 0;
  291. return 1;
  292. }
  293. CHAR *S69_LoadTitle(void)
  294. {
  295. CHAR s[36];
  296. _mm_fseek(modreader,2,SEEK_SET);
  297. if(!_mm_read_UBYTES(s,36,modreader)) return NULL;
  298. return(DupStr(s,36,1));
  299. }
  300. /*========== Loader information */
  301. MIKMODAPI MLOADER load_669={
  302. NULL,
  303. "669",
  304. "669 (Composer 669, Unis 669)",
  305. S69_Init,
  306. S69_Test,
  307. S69_Load,
  308. S69_Cleanup,
  309. S69_LoadTitle
  310. };
  311. /* ex:set ts=4: */