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

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_stx.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   STMIK 0.2 (STX) module loader
  22. ==============================================================================*/
  23. /*
  24. Written by Claudio Matsuoka <claudio@helllabs.org>
  25. */
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include <stdio.h>
  33. #ifdef HAVE_MEMORY_H
  34. #include <memory.h>
  35. #endif
  36. #include <string.h>
  37. #include "mikmod_internals.h"
  38. #ifdef SUNOS
  39. extern int fprintf(FILE *, const char *, ...);
  40. #endif
  41. /*========== Module structure */
  42. /* header */
  43. typedef struct STXHEADER {
  44. CHAR  songname[20];
  45. CHAR  trackername[8];
  46. UWORD patsize;
  47. UWORD unknown1;
  48. UWORD patptr;
  49. UWORD insptr;
  50. UWORD chnptr; /* not sure */
  51. UWORD unknown2;
  52. UWORD unknown3;
  53. UBYTE mastermult;
  54. UBYTE initspeed;
  55. UWORD unknown4;
  56. UWORD unknown5;
  57. UWORD patnum;
  58. UWORD insnum;
  59. UWORD ordnum;
  60. UWORD unknown6;
  61. UWORD unknown7;
  62. UWORD unknown8;
  63. CHAR  scrm[4];
  64. } STXHEADER;
  65. /* sample information */
  66. typedef struct STXSAMPLE {
  67. UBYTE type;
  68. CHAR  filename[12];
  69. UBYTE memsegh;
  70. UWORD memsegl;
  71. ULONG length;
  72. ULONG loopbeg;
  73. ULONG loopend;
  74. UBYTE volume;
  75. UBYTE dsk;
  76. UBYTE pack;
  77. UBYTE flags;
  78. ULONG c2spd;
  79. UBYTE unused[12];
  80. CHAR  sampname[28];
  81. CHAR  scrs[4];
  82. } STXSAMPLE;
  83. typedef struct STXNOTE {
  84. UBYTE note,ins,vol,cmd,inf;
  85. } STXNOTE;
  86. /*========== Loader variables */
  87. static STXNOTE   *stxbuf  = NULL; /* pointer to a complete STX pattern */
  88. static STXHEADER *mh      = NULL;
  89. static UWORD     *paraptr = NULL; /* parapointer array (see STX docs) */
  90. /*========== Loader code */
  91. static BOOL STX_Test(void)
  92. {
  93. UBYTE id[8];
  94. int t;
  95. _mm_fseek(modreader,0x3C,SEEK_SET);
  96. if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  97. if(memcmp(id,"SCRM",4)) return 0;
  98. _mm_fseek(modreader,0x14,SEEK_SET);
  99. if(!_mm_read_UBYTES(id,8,modreader)) return 0;
  100. for(t=0;t<STM_NTRACKERS;t++)
  101. if(!memcmp(id,STM_Signatures[t],8)) return 1;
  102. return 0;
  103. }
  104. static BOOL STX_Init(void)
  105. {
  106. if(!(stxbuf=(STXNOTE*)_mm_malloc(4*64*sizeof(STXNOTE)))) return 0;
  107. if(!(mh=(STXHEADER*)_mm_malloc(sizeof(STXHEADER)))) return 0;
  108. if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
  109. memset(poslookup,-1,256);
  110. return 1;
  111. }
  112. static void STX_Cleanup(void)
  113. {
  114. _mm_free(stxbuf);
  115. _mm_free(paraptr);
  116. _mm_free(poslookup);
  117. _mm_free(mh);
  118. }
  119. static BOOL STX_ReadPattern(void)
  120. {
  121. int row=0,flag,ch;
  122. STXNOTE *n,dummy;
  123. /* clear pattern data */
  124. memset(stxbuf,255,4*64*sizeof(STXNOTE));
  125. while(row<64) {
  126. flag=_mm_read_UBYTE(modreader);
  127. if(_mm_eof(modreader)) {
  128. _mm_errno = MMERR_LOADING_PATTERN;
  129. return 0;
  130. }
  131. if(flag) {
  132. ch=flag&31;
  133. if((ch>=0)&&(ch<4))
  134. n=&stxbuf[(64U*ch)+row];
  135. else
  136. n=&dummy;
  137. if(flag&32) {
  138. n->note=_mm_read_UBYTE(modreader);
  139. n->ins=_mm_read_UBYTE(modreader);
  140. }
  141. if(flag&64) {
  142. n->vol=_mm_read_UBYTE(modreader);
  143. if(n->vol>64) n->vol=64;
  144. }
  145. if(flag&128) {
  146. n->cmd=_mm_read_UBYTE(modreader);
  147. n->inf=_mm_read_UBYTE(modreader);
  148. }
  149. } else row++;
  150. }
  151. return 1;
  152. }
  153. static UBYTE* STX_ConvertTrack(STXNOTE* tr)
  154. {
  155. int t;
  156. UniReset();
  157. for(t=0;t<64;t++) {
  158. UBYTE note,ins,vol,cmd,inf;
  159. note=tr[t].note;
  160. ins=tr[t].ins;
  161. vol=tr[t].vol;
  162. cmd=tr[t].cmd;
  163. inf=tr[t].inf;
  164. if((ins)&&(ins!=255)) UniInstrument(ins-1);
  165. if((note)&&(note!=255)) {
  166. if(note==254) {
  167. UniPTEffect(0xc,0); /* note cut command */
  168. vol=255;
  169. } else UniNote(24+((note>>4)*OCTAVE)+(note&0xf)); /* normal note */
  170. }
  171. if(vol<255) UniPTEffect(0xc,vol);
  172. if(cmd<255) switch(cmd) {
  173. case 1: /* Axx set speed to xx */
  174. UniPTEffect(0xf,inf>>4);
  175. break;
  176. case 2: /* Bxx position jump */
  177. UniPTEffect(0xb,inf);
  178. break;
  179. case 3: /* Cxx patternbreak to row xx */
  180. UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
  181. break;
  182. case 4: /* Dxy volumeslide */
  183. UniEffect(UNI_S3MEFFECTD,inf);
  184. break;
  185. case 5: /* Exy toneslide down */
  186. UniEffect(UNI_S3MEFFECTE,inf);
  187. break;
  188. case 6: /* Fxy toneslide up */
  189. UniEffect(UNI_S3MEFFECTF,inf);
  190. break;
  191. case 7: /* Gxx Tone portamento,speed xx */
  192. UniPTEffect(0x3,inf);
  193. break;
  194. case 8: /* Hxy vibrato */
  195. UniPTEffect(0x4,inf);
  196. break;
  197. case 9: /* Ixy tremor, ontime x, offtime y */
  198. UniEffect(UNI_S3MEFFECTI,inf);
  199. break;
  200. case 0: /* protracker arpeggio */
  201. if(!inf) break;
  202. /* fall through */
  203. case 0xa: /* Jxy arpeggio */
  204. UniPTEffect(0x0,inf);
  205. break;
  206. case 0xb: /* Kxy Dual command H00 & Dxy */
  207. UniPTEffect(0x4,0);
  208. UniEffect(UNI_S3MEFFECTD,inf);
  209. break;
  210. case 0xc: /* Lxy Dual command G00 & Dxy */
  211. UniPTEffect(0x3,0);
  212. UniEffect(UNI_S3MEFFECTD,inf);
  213. break;
  214. /* Support all these above, since ST2 can LOAD these values but can
  215.    actually only play up to J - and J is only half-way implemented
  216.    in ST2 */
  217. case 0x18: /* Xxx amiga panning command 8xx */
  218. UniPTEffect(0x8,inf);
  219. of.flags |= UF_PANNING;
  220. break;
  221. }
  222. UniNewline();
  223. }
  224. return UniDup();
  225. }
  226. static BOOL STX_Load(BOOL curious)
  227. {
  228. int t,u,track = 0;
  229. int version = 0;
  230. SAMPLE *q;
  231. /* try to read module header */
  232. _mm_read_string(mh->songname,20,modreader);
  233. _mm_read_string(mh->trackername,8,modreader);
  234. mh->patsize     =_mm_read_I_UWORD(modreader);
  235. mh->unknown1    =_mm_read_I_UWORD(modreader);
  236. mh->patptr      =_mm_read_I_UWORD(modreader);
  237. mh->insptr      =_mm_read_I_UWORD(modreader);
  238. mh->chnptr      =_mm_read_I_UWORD(modreader);
  239. mh->unknown2    =_mm_read_I_UWORD(modreader);
  240. mh->unknown3    =_mm_read_I_UWORD(modreader);
  241. mh->mastermult  =_mm_read_UBYTE(modreader);
  242. mh->initspeed   =_mm_read_UBYTE(modreader)>>4;
  243. mh->unknown4    =_mm_read_I_UWORD(modreader);
  244. mh->unknown5    =_mm_read_I_UWORD(modreader);
  245. mh->patnum      =_mm_read_I_UWORD(modreader);
  246. mh->insnum      =_mm_read_I_UWORD(modreader);
  247. mh->ordnum      =_mm_read_I_UWORD(modreader);
  248. mh->unknown6    =_mm_read_I_UWORD(modreader);
  249. mh->unknown7    =_mm_read_I_UWORD(modreader);
  250. mh->unknown8    =_mm_read_I_UWORD(modreader);
  251. _mm_read_string(mh->scrm,4,modreader);
  252. if(_mm_eof(modreader)) {
  253. _mm_errno = MMERR_LOADING_HEADER;
  254. return 0;
  255. }
  256. /* set module variables */
  257. of.songname    = DupStr(mh->songname,20,1);
  258. of.numpat      = mh->patnum;
  259. of.reppos      = 0;
  260. of.numins      = of.numsmp = mh->insnum;
  261. of.initspeed   = mh->initspeed;
  262. of.inittempo   = 125;
  263. of.numchn      = 4;
  264. of.flags      |= UF_S3MSLIDES;
  265. of.bpmlimit    = 32;
  266. if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
  267. return 0;
  268. /* read the instrument+pattern parapointers */
  269. _mm_fseek(modreader,mh->insptr<<4,SEEK_SET);
  270. _mm_read_I_UWORDS(paraptr,of.numins,modreader);
  271. _mm_fseek(modreader,mh->patptr<<4,SEEK_SET);
  272. _mm_read_I_UWORDS(paraptr+of.numins,of.numpat,modreader);
  273. /* check module version */
  274. _mm_fseek(modreader,paraptr[of.numins]<<4,SEEK_SET);
  275. version=_mm_read_I_UWORD(modreader);
  276. if(version==mh->patsize) {
  277. version    = 0x10;
  278. of.modtype = strdup("STMIK 0.2 (STM2STX 1.0)");
  279. } else {
  280. version    = 0x11;
  281. of.modtype = strdup("STMIK 0.2 (STM2STX 1.1)");
  282. }
  283. /* read the order data */
  284. _mm_fseek(modreader,(mh->chnptr<<4)+32,SEEK_SET);
  285. if(!AllocPositions(mh->ordnum)) return 0;
  286. for(t=0;t<mh->ordnum;t++) {
  287. of.positions[t]=_mm_read_UBYTE(modreader);
  288. _mm_fseek(modreader,4,SEEK_CUR);
  289. }
  290. of.numpos=0;poslookupcnt=mh->ordnum;
  291. for(t=0;t<mh->ordnum;t++) {
  292. int order=of.positions[t];
  293. if(order==255) order=LAST_PATTERN;
  294. of.positions[of.numpos]=order;
  295. poslookup[t]=of.numpos; /* bug fix for freaky S3Ms */
  296. if(of.positions[t]<254) of.numpos++;        
  297. else
  298.   /* special end of song pattern */
  299.   if((order==LAST_PATTERN)&&(!curious)) break;
  300. }
  301. if(_mm_eof(modreader)) {
  302. _mm_errno = MMERR_LOADING_HEADER;
  303. return 0;
  304. }
  305. /* load samples */
  306. if(!AllocSamples()) return 0;
  307. for(q=of.samples,t=0;t<of.numins;t++,q++) {
  308. STXSAMPLE s;
  309. /* seek to instrument position */
  310. _mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
  311. /* and load sample info */
  312. s.type      =_mm_read_UBYTE(modreader);
  313. _mm_read_string(s.filename,12,modreader);
  314. s.memsegh   =_mm_read_UBYTE(modreader);
  315. s.memsegl   =_mm_read_I_UWORD(modreader);
  316. s.length    =_mm_read_I_ULONG(modreader);
  317. s.loopbeg   =_mm_read_I_ULONG(modreader);
  318. s.loopend   =_mm_read_I_ULONG(modreader);
  319. s.volume    =_mm_read_UBYTE(modreader);
  320. s.dsk       =_mm_read_UBYTE(modreader);
  321. s.pack      =_mm_read_UBYTE(modreader);
  322. s.flags     =_mm_read_UBYTE(modreader);
  323. s.c2spd     =_mm_read_I_ULONG(modreader);
  324. _mm_read_UBYTES(s.unused,12,modreader);
  325. _mm_read_string(s.sampname,28,modreader);
  326. _mm_read_string(s.scrs,4,modreader);
  327. if(_mm_eof(modreader)) {
  328. _mm_errno = MMERR_LOADING_SAMPLEINFO;
  329. return 0;
  330. }
  331. q->samplename = DupStr(s.sampname,28,1);
  332. q->speed      = (s.c2spd * 8363) / 8448;
  333. q->length     = s.length;
  334. q->loopstart  = s.loopbeg;
  335. q->loopend    = s.loopend;
  336. q->volume     = s.volume;
  337. q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  338. q->flags     |= SF_SIGNED;
  339. if(s.flags&1) q->flags |= SF_LOOP;
  340. if(s.flags&4) q->flags |= SF_16BITS;
  341. }
  342. /* load pattern info */
  343. of.numtrk=of.numpat*of.numchn;
  344. if(!AllocTracks()) return 0;
  345. if(!AllocPatterns()) return 0;
  346. for(t=0;t<of.numpat;t++) {
  347. /* seek to pattern position (+2 skip pattern length) */
  348. _mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+
  349. (version==0x10?2:0),SEEK_SET);
  350. if(!STX_ReadPattern()) return 0;
  351. for(u=0;u<of.numchn;u++)
  352. if(!(of.tracks[track++]=STX_ConvertTrack(&stxbuf[u*64]))) return 0;
  353. }
  354. return 1;
  355. }
  356. static CHAR *STX_LoadTitle(void)
  357. {
  358. CHAR s[28];
  359. _mm_fseek(modreader,0,SEEK_SET);
  360. if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
  361. return(DupStr(s,28,1));
  362. }
  363. /*========== Loader information */
  364. MIKMODAPI MLOADER load_stx={
  365. NULL,
  366. "STX",
  367. "STX (Scream Tracker Music Interface Kit)",
  368. STX_Init,
  369. STX_Test,
  370. STX_Load,
  371. STX_Cleanup,
  372. STX_LoadTitle
  373. };
  374. /* ex:set ts=4: */