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

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_stm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   Screamtracker 2 (STM) 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. /* sample information */
  40. typedef struct STMSAMPLE {
  41. CHAR  filename[12];
  42. UBYTE unused;       /* 0x00 */
  43. UBYTE instdisk;     /* Instrument disk */
  44. UWORD reserved;
  45. UWORD length;       /* Sample length */
  46. UWORD loopbeg;      /* Loop start point */
  47. UWORD loopend;      /* Loop end point */
  48. UBYTE volume;       /* Volume */
  49. UBYTE reserved2;
  50. UWORD c2spd;        /* Good old c2spd */
  51. ULONG reserved3;
  52. UWORD isa;
  53. } STMSAMPLE;
  54. /* header */
  55. typedef struct STMHEADER {
  56. CHAR  songname[20];
  57. CHAR  trackername[8]; /* !Scream! for ST 2.xx  */
  58. UBYTE unused;         /* 0x1A  */
  59. UBYTE filetype;       /* 1=song, 2=module */
  60. UBYTE ver_major;
  61. UBYTE ver_minor;
  62. UBYTE inittempo;      /* initspeed= stm inittempo>>4  */
  63. UBYTE numpat;         /* number of patterns  */
  64. UBYTE globalvol;     
  65. UBYTE reserved[13];
  66. STMSAMPLE sample[31]; /* STM sample data */
  67. UBYTE patorder[128];  /* Docs say 64 - actually 128 */
  68. } STMHEADER;
  69. typedef struct STMNOTE {
  70. UBYTE note,insvol,volcmd,cmdinf;
  71. } STMNOTE;
  72. /*========== Loader variables */
  73. static STMNOTE *stmbuf = NULL;
  74. static STMHEADER *mh = NULL;
  75. /* tracker identifiers */
  76. static CHAR* STM_Version[STM_NTRACKERS] = {
  77. "Screamtracker 2",
  78. "Converted by MOD2STM (STM format)",
  79. "Wuzamod (STM format)"
  80. };
  81. /*========== Loader code */
  82. BOOL STM_Test(void)
  83. {
  84. UBYTE str[44];
  85. int t;
  86. _mm_fseek(modreader,20,SEEK_SET);
  87. _mm_read_UBYTES(str,44,modreader);
  88. if(str[9]!=2) return 0; /* STM Module = filetype 2 */
  89. /* Prevent false positives for S3M files */
  90. if(!memcmp(str+40,"SCRM",4))
  91. return 0;
  92. for (t=0;t<STM_NTRACKERS;t++)
  93. if(!memcmp(str,STM_Signatures[t],8))
  94. return 1;
  95. return 0;
  96. }
  97. BOOL STM_Init(void)
  98. {
  99. if(!(mh=(STMHEADER*)_mm_malloc(sizeof(STMHEADER)))) return 0;
  100. if(!(stmbuf=(STMNOTE*)_mm_calloc(64U*4,sizeof(STMNOTE)))) return 0;
  101. return 1;
  102. }
  103. static void STM_Cleanup(void)
  104. {
  105. _mm_free(mh);
  106. _mm_free(stmbuf);
  107. }
  108. static void STM_ConvertNote(STMNOTE *n)
  109. {
  110. UBYTE note,ins,vol,cmd,inf;
  111. /* extract the various information from the 4 bytes that make up a note */
  112. note = n->note;
  113. ins  = n->insvol>>3;
  114. vol  = (n->insvol&7)+((n->volcmd&0x70)>>1);
  115. cmd  = n->volcmd&15;
  116. inf  = n->cmdinf;
  117. if((ins)&&(ins<32)) UniInstrument(ins-1);
  118. /* special values of [SBYTE0] are handled here 
  119.    we have no idea if these strange values will ever be encountered.
  120.    but it appears as those stms sound correct. */
  121. if((note==254)||(note==252)) {
  122. UniPTEffect(0xc,0); /* note cut */
  123. n->volcmd|=0x80;
  124. } else
  125. /* if note < 251, then all three bytes are stored in the file */
  126.   if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf));
  127. if((!(n->volcmd&0x80))&&(vol<65)) UniPTEffect(0xc,vol);
  128. if(cmd!=255)
  129. switch(cmd) {
  130. case 1: /* Axx set speed to xx */
  131. UniPTEffect(0xf,inf>>4);
  132. break;
  133. case 2: /* Bxx position jump */
  134. UniPTEffect(0xb,inf);
  135. break;
  136. case 3: /* Cxx patternbreak to row xx */
  137. UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
  138. break;
  139. case 4: /* Dxy volumeslide */
  140. UniEffect(UNI_S3MEFFECTD,inf);
  141. break;
  142. case 5: /* Exy toneslide down */
  143. UniEffect(UNI_S3MEFFECTE,inf);
  144. break;
  145. case 6: /* Fxy toneslide up */
  146. UniEffect(UNI_S3MEFFECTF,inf);
  147. break;
  148. case 7: /* Gxx Tone portamento,speed xx */
  149. UniPTEffect(0x3,inf);
  150. break;
  151. case 8: /* Hxy vibrato */
  152. UniPTEffect(0x4,inf);
  153. break;
  154. case 9: /* Ixy tremor, ontime x, offtime y */
  155. UniEffect(UNI_S3MEFFECTI,inf);
  156. break;
  157. case 0: /* protracker arpeggio */
  158. if(!inf) break;
  159. /* fall through */
  160. case 0xa: /* Jxy arpeggio */
  161. UniPTEffect(0x0,inf);
  162. break;
  163. case 0xb: /* Kxy Dual command H00 & Dxy */
  164. UniPTEffect(0x4,0);
  165. UniEffect(UNI_S3MEFFECTD,inf);
  166. break;
  167. case 0xc: /* Lxy Dual command G00 & Dxy */
  168. UniPTEffect(0x3,0);
  169. UniEffect(UNI_S3MEFFECTD,inf);
  170. break;
  171. /* Support all these above, since ST2 can LOAD these values but can
  172.    actually only play up to J - and J is only half-way implemented
  173.    in ST2 */
  174. case 0x18: /* Xxx amiga panning command 8xx */
  175. UniPTEffect(0x8,inf);
  176. of.flags |= UF_PANNING;
  177. break;
  178. }
  179. }
  180. static UBYTE *STM_ConvertTrack(STMNOTE *n)
  181. {
  182. int t;
  183. UniReset();
  184. for(t=0;t<64;t++) {
  185. STM_ConvertNote(n);
  186. UniNewline();
  187. n+=of.numchn;
  188. }
  189. return UniDup();
  190. }
  191. static BOOL STM_LoadPatterns(void)
  192. {
  193. int t,s,tracks=0;
  194. if(!AllocPatterns()) return 0;
  195. if(!AllocTracks()) return 0;
  196. /* Allocate temporary buffer for loading and converting the patterns */
  197. for(t=0;t<of.numpat;t++) {
  198. for(s=0;s<(64U*of.numchn);s++) {
  199. stmbuf[s].note   = _mm_read_UBYTE(modreader);
  200. stmbuf[s].insvol = _mm_read_UBYTE(modreader);
  201. stmbuf[s].volcmd = _mm_read_UBYTE(modreader);
  202. stmbuf[s].cmdinf = _mm_read_UBYTE(modreader);
  203. }
  204. if(_mm_eof(modreader)) {
  205. _mm_errno = MMERR_LOADING_PATTERN;
  206. return 0;
  207. }
  208. for(s=0;s<of.numchn;s++)
  209. if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
  210. }
  211. return 1;
  212. }
  213. BOOL STM_Load(BOOL curious)
  214. {
  215. int t; 
  216. ULONG MikMod_ISA; /* We must generate our own ISA, it's not stored in stm */
  217. SAMPLE *q;
  218. /* try to read stm header */
  219. _mm_read_string(mh->songname,20,modreader);
  220. _mm_read_string(mh->trackername,8,modreader);
  221. mh->unused      =_mm_read_UBYTE(modreader);
  222. mh->filetype    =_mm_read_UBYTE(modreader);
  223. mh->ver_major   =_mm_read_UBYTE(modreader);
  224. mh->ver_minor   =_mm_read_UBYTE(modreader);
  225. mh->inittempo   =_mm_read_UBYTE(modreader);
  226. if(!mh->inittempo) {
  227. _mm_errno=MMERR_NOT_A_MODULE;
  228. return 0;
  229. }
  230. mh->numpat      =_mm_read_UBYTE(modreader);
  231. mh->globalvol   =_mm_read_UBYTE(modreader);
  232. _mm_read_UBYTES(mh->reserved,13,modreader);
  233. for(t=0;t<31;t++) {
  234. STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
  235. _mm_read_string(s->filename,12,modreader);
  236. s->unused   =_mm_read_UBYTE(modreader);
  237. s->instdisk =_mm_read_UBYTE(modreader);
  238. s->reserved =_mm_read_I_UWORD(modreader);
  239. s->length   =_mm_read_I_UWORD(modreader);
  240. s->loopbeg  =_mm_read_I_UWORD(modreader);
  241. s->loopend  =_mm_read_I_UWORD(modreader);
  242. s->volume   =_mm_read_UBYTE(modreader);
  243. s->reserved2=_mm_read_UBYTE(modreader);
  244. s->c2spd    =_mm_read_I_UWORD(modreader);
  245. s->reserved3=_mm_read_I_ULONG(modreader);
  246. s->isa      =_mm_read_I_UWORD(modreader);
  247. }
  248. _mm_read_UBYTES(mh->patorder,128,modreader);
  249. if(_mm_eof(modreader)) {
  250. _mm_errno = MMERR_LOADING_HEADER;
  251. return 0;
  252. }
  253. /* set module variables */
  254. for(t=0;t<STM_NTRACKERS;t++)
  255. if(!memcmp(mh->trackername,STM_Signatures[t],8)) break;
  256. of.modtype   = strdup(STM_Version[t]);
  257. of.songname  = DupStr(mh->songname,20,1); /* make a cstr of songname */
  258. of.numpat    = mh->numpat;
  259. of.inittempo = 125;                     /* mh->inittempo+0x1c; */
  260. of.initspeed = mh->inittempo>>4;
  261. of.numchn    = 4;                       /* get number of channels */
  262. of.reppos    = 0;
  263. of.flags    |= UF_S3MSLIDES;
  264. of.bpmlimit  = 32;
  265. t=0;
  266. if(!AllocPositions(0x80)) return 0;
  267. /* 99 terminates the patorder list */
  268. while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) {
  269. of.positions[t]=mh->patorder[t];
  270. t++;
  271. }
  272. if(mh->patorder[t]<=99) t++;
  273. of.numpos=t;
  274. of.numtrk=of.numpat*of.numchn;
  275. of.numins=of.numsmp=31;
  276. if(!AllocSamples()) return 0;
  277. if(!STM_LoadPatterns()) return 0;
  278. MikMod_ISA=_mm_ftell(modreader);
  279. MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
  280. for(q=of.samples,t=0;t<of.numsmp;t++,q++) {
  281. /* load sample info */
  282. q->samplename = DupStr(mh->sample[t].filename,12,1);
  283. q->speed      = (mh->sample[t].c2spd * 8363) / 8448;
  284. q->volume     = mh->sample[t].volume;
  285. q->length     = mh->sample[t].length;
  286. if (/*(!mh->sample[t].volume)||*/(q->length==1)) q->length=0;
  287. q->loopstart  = mh->sample[t].loopbeg;
  288. q->loopend    = mh->sample[t].loopend;
  289. q->seekpos    = MikMod_ISA;
  290. MikMod_ISA+=q->length;
  291. MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
  292. /* contrary to the STM specs, sample data is signed */
  293. q->flags = SF_SIGNED;
  294. if(q->loopend && q->loopend != 0xffff)
  295. q->flags|=SF_LOOP;
  296. }
  297. return 1;
  298. }
  299. CHAR *STM_LoadTitle(void)
  300. {
  301. CHAR s[20];
  302. _mm_fseek(modreader,0,SEEK_SET);
  303. if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
  304. return(DupStr(s,20,1));
  305. }
  306. /*========== Loader information */
  307. MIKMODAPI MLOADER load_stm={
  308. NULL,
  309. "STM",
  310. "STM (Scream Tracker)",
  311. STM_Init,
  312. STM_Test,
  313. STM_Load,
  314. STM_Cleanup,
  315. STM_LoadTitle
  316. };
  317. /* ex:set ts=4: */