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

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_s3m.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   Screamtracker (S3M) 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 S3MHEADER {
  41. CHAR  songname[28];
  42. UBYTE t1a;
  43. UBYTE type;
  44. UBYTE unused1[2];
  45. UWORD ordnum;
  46. UWORD insnum;
  47. UWORD patnum;
  48. UWORD flags;
  49. UWORD tracker;
  50. UWORD fileformat;
  51. CHAR  scrm[4];
  52. UBYTE mastervol;
  53. UBYTE initspeed;
  54. UBYTE inittempo;
  55. UBYTE mastermult;
  56. UBYTE ultraclick;
  57. UBYTE pantable;
  58. UBYTE unused2[8];
  59. UWORD special;
  60. UBYTE channels[32];
  61. } S3MHEADER;
  62. /* sample information */
  63. typedef struct S3MSAMPLE {
  64. UBYTE type;
  65. CHAR  filename[12];
  66. UBYTE memsegh;
  67. UWORD memsegl;
  68. ULONG length;
  69. ULONG loopbeg;
  70. ULONG loopend;
  71. UBYTE volume;
  72. UBYTE dsk;
  73. UBYTE pack;
  74. UBYTE flags;
  75. ULONG c2spd;
  76. UBYTE unused[12];
  77. CHAR  sampname[28];
  78. CHAR  scrs[4];
  79. } S3MSAMPLE;
  80. typedef struct S3MNOTE {
  81. UBYTE note,ins,vol,cmd,inf;
  82. } S3MNOTE;
  83. /*========== Loader variables */
  84. static S3MNOTE   *s3mbuf  = NULL; /* pointer to a complete S3M pattern */
  85. static S3MHEADER *mh      = NULL;
  86. static UWORD     *paraptr = NULL; /* parapointer array (see S3M docs) */
  87. static unsigned int tracker; /* tracker id */
  88. /* tracker identifiers */
  89. #define NUMTRACKERS 4
  90. static CHAR* S3M_Version[] = {
  91. "Screamtracker x.xx",
  92. "Imago Orpheus x.xx (S3M format)",
  93. "Impulse Tracker x.xx (S3M format)",
  94. "Unknown tracker x.xx (S3M format)",
  95. "Impulse Tracker 2.14p3 (S3M format)",
  96. "Impulse Tracker 2.14p4 (S3M format)"
  97. };
  98. /* version number position in above array */
  99. static int numeric[NUMTRACKERS]={14,14,16,16};
  100. /*========== Loader code */
  101. BOOL S3M_Test(void)
  102. {
  103. UBYTE id[4];
  104. _mm_fseek(modreader,0x2c,SEEK_SET);
  105. if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  106. if(!memcmp(id,"SCRM",4)) return 1;
  107. return 0;
  108. }
  109. BOOL S3M_Init(void)
  110. {
  111. if(!(s3mbuf=(S3MNOTE*)_mm_malloc(32*64*sizeof(S3MNOTE)))) return 0;
  112. if(!(mh=(S3MHEADER*)_mm_malloc(sizeof(S3MHEADER)))) return 0;
  113. if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
  114. memset(poslookup,-1,256);
  115. return 1;
  116. }
  117. void S3M_Cleanup(void)
  118. {
  119. _mm_free(s3mbuf);
  120. _mm_free(paraptr);
  121. _mm_free(poslookup);
  122. _mm_free(mh);
  123. _mm_free(origpositions);
  124. }
  125. /* Because so many s3m files have 16 channels as the set number used, but really
  126.    only use far less (usually 8 to 12 still), I had to make this function, which
  127.    determines the number of channels that are actually USED by a pattern.
  128.    For every channel that's used, it sets the appropriate array entry of the
  129.    global variable 'remap'
  130.    NOTE: You must first seek to the file location of the pattern before calling
  131.          this procedure.
  132.    Returns 1 on fail.                                                         */
  133. static BOOL S3M_GetNumChannels(void)
  134. {
  135. int row=0,flag,ch;
  136. while(row<64) {
  137. flag=_mm_read_UBYTE(modreader);
  138. if(_mm_eof(modreader)) {
  139. _mm_errno = MMERR_LOADING_PATTERN;
  140. return 1;
  141. }
  142. if(flag) {
  143. ch=flag&31;
  144. if(mh->channels[ch]<32) remap[ch] = 0;
  145. if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  146. if(flag&64) _mm_read_UBYTE(modreader);
  147. if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  148. } else row++;
  149. }
  150. return 0;
  151. }    
  152. static BOOL S3M_ReadPattern(void)
  153. {
  154. int row=0,flag,ch;
  155. S3MNOTE *n,dummy;
  156. /* clear pattern data */
  157. memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
  158. while(row<64) {
  159. flag=_mm_read_UBYTE(modreader);
  160. if(_mm_eof(modreader)) {
  161. _mm_errno = MMERR_LOADING_PATTERN;
  162. return 0;
  163. }
  164. if(flag) {
  165. ch=remap[flag&31];
  166. if(ch!=-1)
  167. n=&s3mbuf[(64U*ch)+row];
  168. else
  169. n=&dummy;
  170. if(flag&32) {
  171. n->note=_mm_read_UBYTE(modreader);
  172. n->ins=_mm_read_UBYTE(modreader);
  173. }
  174. if(flag&64) {
  175. n->vol=_mm_read_UBYTE(modreader);
  176. if (n->vol>64) n->vol=64;
  177. }
  178. if(flag&128) {
  179. n->cmd=_mm_read_UBYTE(modreader);
  180. n->inf=_mm_read_UBYTE(modreader);
  181. }
  182. } else row++;
  183. }
  184. return 1;
  185. }
  186. static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
  187. {
  188. int t;
  189. UniReset();
  190. for(t=0;t<64;t++) {
  191. UBYTE note,ins,vol;
  192. note=tr[t].note;
  193. ins=tr[t].ins;
  194. vol=tr[t].vol;
  195. if((ins)&&(ins!=255)) UniInstrument(ins-1);
  196. if(note!=255) {
  197. if(note==254) {
  198. UniPTEffect(0xc,0); /* note cut command */
  199. vol=255;
  200. } else
  201. UniNote(((note>>4)*OCTAVE)+(note&0xf)); /* normal note */
  202. }
  203. if(vol<255) UniPTEffect(0xc,vol);
  204. S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,
  205. tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE);
  206. UniNewline();
  207. }
  208. return UniDup();
  209. }
  210. BOOL S3M_Load(BOOL curious)
  211. {
  212. int t,u,track = 0;
  213. SAMPLE *q;
  214. UBYTE pan[32];
  215. /* try to read module header */
  216. _mm_read_string(mh->songname,28,modreader);
  217. mh->t1a         =_mm_read_UBYTE(modreader);
  218. mh->type        =_mm_read_UBYTE(modreader);
  219. _mm_read_UBYTES(mh->unused1,2,modreader);
  220. mh->ordnum      =_mm_read_I_UWORD(modreader);
  221. mh->insnum      =_mm_read_I_UWORD(modreader);
  222. mh->patnum      =_mm_read_I_UWORD(modreader);
  223. mh->flags       =_mm_read_I_UWORD(modreader);
  224. mh->tracker     =_mm_read_I_UWORD(modreader);
  225. mh->fileformat  =_mm_read_I_UWORD(modreader);
  226. _mm_read_string(mh->scrm,4,modreader);
  227. mh->mastervol   =_mm_read_UBYTE(modreader);
  228. mh->initspeed   =_mm_read_UBYTE(modreader);
  229. mh->inittempo   =_mm_read_UBYTE(modreader);
  230. mh->mastermult  =_mm_read_UBYTE(modreader);
  231. mh->ultraclick  =_mm_read_UBYTE(modreader);
  232. mh->pantable    =_mm_read_UBYTE(modreader);
  233. _mm_read_UBYTES(mh->unused2,8,modreader);
  234. mh->special     =_mm_read_I_UWORD(modreader);
  235. _mm_read_UBYTES(mh->channels,32,modreader);
  236. if(_mm_eof(modreader)) {
  237. _mm_errno = MMERR_LOADING_HEADER;
  238. return 0;
  239. }
  240. /* then we can decide the module type */
  241. tracker=mh->tracker>>12;
  242. if((!tracker)||(tracker>=NUMTRACKERS))
  243. tracker=NUMTRACKERS-1; /* unknown tracker */
  244. else {
  245. if(mh->tracker>=0x3217)
  246. tracker=NUMTRACKERS+1; /* IT 2.14p4 */
  247. else if(mh->tracker>=0x3216)
  248. tracker=NUMTRACKERS; /* IT 2.14p3 */
  249. else tracker--;
  250. }
  251. of.modtype = strdup(S3M_Version[tracker]);
  252. if(tracker<NUMTRACKERS) {
  253. of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';
  254. of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';
  255. of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0';
  256. }
  257. /* set module variables */
  258. of.songname    = DupStr(mh->songname,28,0);
  259. of.numpat      = mh->patnum;
  260. of.reppos      = 0;
  261. of.numins      = of.numsmp = mh->insnum;
  262. of.initspeed   = mh->initspeed;
  263. of.inittempo   = mh->inittempo;
  264. of.initvolume  = mh->mastervol<<1;
  265. of.flags      |= UF_ARPMEM | UF_PANNING;
  266. if((mh->tracker==0x1300)||(mh->flags&64))
  267. of.flags|=UF_S3MSLIDES;
  268. of.bpmlimit    = 32;
  269. /* read the order data */
  270. if(!AllocPositions(mh->ordnum)) return 0;
  271. if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
  272. for(t=0;t<mh->ordnum;t++) {
  273. origpositions[t]=_mm_read_UBYTE(modreader);
  274. if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
  275. origpositions[t]=255/*mh->patnum-1*/;
  276. }
  277. if(_mm_eof(modreader)) {
  278. _mm_errno = MMERR_LOADING_HEADER;
  279. return 0;
  280. }
  281. poslookupcnt=mh->ordnum;
  282. S3MIT_CreateOrders(curious);
  283. if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
  284. return 0;
  285. /* read the instrument+pattern parapointers */
  286. _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
  287. if(mh->pantable==252) {
  288. /* read the panning table (ST 3.2 addition.  See below for further
  289.    portions of channel panning [past reampper]). */
  290. _mm_read_UBYTES(pan,32,modreader);
  291. }
  292. if(_mm_eof(modreader)) {
  293. _mm_errno = MMERR_LOADING_HEADER;
  294. return 0;
  295. }
  296. /* load samples */
  297. if(!AllocSamples()) return 0;
  298. q = of.samples;
  299. for(t=0;t<of.numins;t++) {
  300. S3MSAMPLE s;
  301. /* seek to instrument position */
  302. _mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
  303. /* and load sample info */
  304. s.type      =_mm_read_UBYTE(modreader);
  305. _mm_read_string(s.filename,12,modreader);
  306. s.memsegh   =_mm_read_UBYTE(modreader);
  307. s.memsegl   =_mm_read_I_UWORD(modreader);
  308. s.length    =_mm_read_I_ULONG(modreader);
  309. s.loopbeg   =_mm_read_I_ULONG(modreader);
  310. s.loopend   =_mm_read_I_ULONG(modreader);
  311. s.volume    =_mm_read_UBYTE(modreader);
  312. s.dsk       =_mm_read_UBYTE(modreader);
  313. s.pack      =_mm_read_UBYTE(modreader);
  314. s.flags     =_mm_read_UBYTE(modreader);
  315. s.c2spd     =_mm_read_I_ULONG(modreader);
  316. _mm_read_UBYTES(s.unused,12,modreader);
  317. _mm_read_string(s.sampname,28,modreader);
  318. _mm_read_string(s.scrs,4,modreader);
  319. /* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
  320. if (s.length > 64000)
  321. s.length = 64000;
  322. if(_mm_eof(modreader)) {
  323. _mm_errno = MMERR_LOADING_SAMPLEINFO;
  324. return 0;
  325. }
  326. q->samplename = DupStr(s.sampname,28,0);
  327. q->speed      = s.c2spd;
  328. q->length     = s.length;
  329. q->loopstart  = s.loopbeg;
  330. q->loopend    = s.loopend;
  331. q->volume     = s.volume;
  332. q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  333. if(s.flags&1) q->flags |= SF_LOOP;
  334. if(s.flags&4) q->flags |= SF_16BITS;
  335. if(mh->fileformat==1) q->flags |= SF_SIGNED;
  336. /* don't load sample if it doesn't have the SCRS tag */
  337. if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
  338. q++;
  339. }
  340. /* determine the number of channels actually used. */
  341. of.numchn = 0;
  342. memset(remap,-1,32*sizeof(UBYTE));
  343. for(t=0;t<of.numpat;t++) {
  344. /* seek to pattern position (+2 skip pattern length) */
  345. _mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  346. if(S3M_GetNumChannels()) return 0;
  347. }
  348. /* build the remap array  */
  349. for(t=0;t<32;t++)
  350. if(!remap[t]) 
  351. remap[t]=of.numchn++;
  352. /* set panning positions after building remap chart! */
  353. for(t=0;t<32;t++) 
  354. if((mh->channels[t]<32)&&(remap[t]!=-1)) {
  355. if(mh->channels[t]<8)
  356. of.panning[remap[t]]=0x30;
  357. else
  358. of.panning[remap[t]]=0xc0;
  359. }
  360. if(mh->pantable==252)
  361. /* set panning positions according to panning table (new for st3.2) */
  362. for(t=0;t<32;t++)
  363. if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
  364. of.panning[remap[t]]=(pan[t]&0xf)<<4;
  365. /* load pattern info */
  366. of.numtrk=of.numpat*of.numchn;
  367. if(!AllocTracks()) return 0;
  368. if(!AllocPatterns()) return 0;
  369. for(t=0;t<of.numpat;t++) {
  370. /* seek to pattern position (+2 skip pattern length) */
  371. _mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  372. if(!S3M_ReadPattern()) return 0;
  373. for(u=0;u<of.numchn;u++)
  374. if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  375. }
  376. return 1;
  377. }
  378. CHAR *S3M_LoadTitle(void)
  379. {
  380. CHAR s[28];
  381. _mm_fseek(modreader,0,SEEK_SET);
  382. if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
  383. return(DupStr(s,28,0));
  384. }
  385. /*========== Loader information */
  386. MIKMODAPI MLOADER load_s3m={
  387. NULL,
  388. "S3M",
  389. "S3M (Scream Tracker 3)",
  390. S3M_Init,
  391. S3M_Test,
  392. S3M_Load,
  393. S3M_Cleanup,
  394. S3M_LoadTitle
  395. };
  396. /* ex:set ts=4: */