load_m15.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_m15.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   15 instrument MOD loader
  22.   Also supports Ultimate Sound Tracker (old M15 format)
  23. ==============================================================================*/
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #include <ctype.h>
  31. #include <stdio.h>
  32. #ifdef HAVE_MEMORY_H
  33. #include <memory.h>
  34. #endif
  35. #include <string.h>
  36. #include "mikmod_internals.h"
  37. #ifdef SUNOS
  38. extern int fprintf(FILE *, const char *, ...);
  39. #endif
  40. /*========== Module Structure */
  41. typedef struct MSAMPINFO {
  42. CHAR  samplename[23]; /* 22 in module, 23 in memory */
  43. UWORD length;
  44. UBYTE finetune;
  45. UBYTE volume;
  46. UWORD reppos;
  47. UWORD replen;
  48. } MSAMPINFO;
  49. typedef struct MODULEHEADER {
  50. CHAR      songname[21]; /* the songname.., 20 in module, 21 in memory */
  51. MSAMPINFO samples[15]; /* all sampleinfo */
  52. UBYTE     songlength; /* number of patterns used */
  53. UBYTE     magic1;        /* should be 127 */
  54. UBYTE     positions[128]; /* which pattern to play at pos */
  55. } MODULEHEADER;
  56. typedef struct MODNOTE {
  57. UBYTE a,b,c,d;
  58. } MODNOTE;
  59. /*========== Loader variables */
  60. static MODULEHEADER *mh = NULL;
  61. static MODNOTE *patbuf = NULL;
  62. static BOOL ust_loader = 0; /* if TRUE, load as an ust module. */
  63. /* known file formats which can confuse the loader */
  64. #define REJECT 2
  65. static char *signatures[REJECT]={
  66. "CAKEWALK", /* cakewalk midi files */
  67. "SZDD" /* Microsoft compressed files */
  68. };
  69. static int siglen[REJECT]={8,4};
  70. /*========== Loader code */
  71. static BOOL LoadModuleHeader(MODULEHEADER *mh)
  72. {
  73. int t,u;
  74. _mm_read_string(mh->songname,20,modreader);
  75. mh->songname[20]=0; /* just in case */
  76. /* sanity check : title should contain printable characters and a bunch
  77.    of null chars */
  78. for(t=0;t<20;t++)
  79. if((mh->songname[t])&&(mh->songname[t]<32)) return 0;
  80. for(t=0;(mh->songname[t])&&(t<20);t++);
  81. if(t<20) for(;t<20;t++) if(mh->songname[t]) return 0;
  82. for(t=0;t<15;t++) {
  83. MSAMPINFO *s=&mh->samples[t];
  84. _mm_read_string(s->samplename,22,modreader);
  85. s->samplename[22]=0; /* just in case */
  86. s->length   =_mm_read_M_UWORD(modreader);
  87. s->finetune =_mm_read_UBYTE(modreader);
  88. s->volume   =_mm_read_UBYTE(modreader);
  89. s->reppos   =_mm_read_M_UWORD(modreader);
  90. s->replen   =_mm_read_M_UWORD(modreader);
  91. /* sanity check : sample title should contain printable characters and
  92.    a bunch of null chars */
  93. for(u=0;u<20;u++)
  94. if((s->samplename[u])&&(s->samplename[u]</*32*/14)) return 0;
  95. for(u=0;(s->samplename[u])&&(u<20);u++);
  96. if(u<20) for(;u<20;u++) if(s->samplename[u]) return 0;
  97. /* sanity check : finetune values */
  98. if(s->finetune>>4) return 0;
  99. }
  100. mh->songlength  =_mm_read_UBYTE(modreader);
  101. mh->magic1      =_mm_read_UBYTE(modreader); /* should be 127 */
  102. /* sanity check : no more than 128 positions, restart position in range */
  103. if((!mh->songlength)||(mh->songlength>128)) return 0;
  104. /* values encountered so far are 0x6a and 0x78 */
  105. if(((mh->magic1&0xf8)!=0x78)&&(mh->magic1!=0x6a)&&(mh->magic1>mh->songlength)) return 0;
  106. _mm_read_UBYTES(mh->positions,128,modreader);
  107. /* sanity check : pattern range is 0..63 */
  108. for(t=0;t<128;t++)
  109. if(mh->positions[t]>63) return 0;
  110. return(!_mm_eof(modreader));
  111. }
  112. /* Checks the patterns in the modfile for UST / 15-inst indications.
  113.    For example, if an effect 3xx is found, it is assumed that the song 
  114.    is 15-inst.  If a 1xx effect has dat greater than 0x20, it is UST.   
  115.    Returns:  0 indecisive; 1 = UST; 2 = 15-inst                               */
  116. static int CheckPatternType(int numpat)
  117. {
  118. int t;
  119. UBYTE eff, dat;
  120. for(t=0;t<numpat*(64U*4);t++) {
  121. /* Load the pattern into the temp buffer and scan it */
  122. _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);
  123. eff = _mm_read_UBYTE(modreader);
  124. dat = _mm_read_UBYTE(modreader);
  125. switch(eff) {
  126. case 1:
  127. if(dat>0x1f) return 1;
  128. if(dat<0x3)  return 2;
  129. break;
  130. case 2:
  131. if(dat>0x1f) return 1;
  132. return 2;
  133. case 3:
  134. if (dat) return 2;
  135. break;
  136. default:
  137. return 2;
  138. }
  139. }
  140. return 0;
  141. }
  142. static BOOL M15_Test(void)
  143. {
  144. int t, numpat;
  145. MODULEHEADER mh;
  146. ust_loader = 0;
  147. if(!LoadModuleHeader(&mh)) return 0;
  148. /* reject other file types */
  149. for(t=0;t<REJECT;t++)
  150. if(!memcmp(mh.songname,signatures[t],siglen[t])) return 0;
  151. if(mh.magic1>127) return 0;
  152. if((!mh.songlength)||(mh.songlength>mh.magic1)) return 0;
  153. for(t=0;t<15;t++) {
  154. /* all finetunes should be zero */
  155. if(mh.samples[t].finetune) return 0;
  156. /* all volumes should be <= 64 */
  157. if(mh.samples[t].volume>64) return 0;
  158. /* all instrument names should begin with s, st-, or a number */
  159. if((mh.samples[t].samplename[0]=='s')||
  160.    (mh.samples[t].samplename[0]=='S')) {
  161. if((memcmp(mh.samples[t].samplename,"st-",3)) &&
  162.    (memcmp(mh.samples[t].samplename,"ST-",3)) &&
  163.    (*mh.samples[t].samplename))
  164. ust_loader = 1;
  165. } else
  166.   if(!isdigit((int)mh.samples[t].samplename[0]))
  167. ust_loader = 1;
  168. if(mh.samples[t].length>4999||mh.samples[t].reppos>9999) {
  169. ust_loader = 0;
  170. if(mh.samples[t].length>32768) return 0;
  171. }
  172. /* if loop information is incorrect as words, but correct as bytes,
  173.    this is likely to be an ust-style module */
  174. if((mh.samples[t].reppos+mh.samples[t].replen>mh.samples[t].length)&&
  175.    (mh.samples[t].reppos+mh.samples[t].replen<(mh.samples[t].length<<1))){
  176. ust_loader = 1;
  177. return 1;
  178. }
  179. if(!ust_loader) return 1; 
  180. }
  181. for(numpat=0,t=0;t<mh.songlength;t++) 
  182. if(mh.positions[t]>numpat)
  183. numpat = mh.positions[t];
  184. numpat++;
  185. switch(CheckPatternType(numpat)) {
  186. case 0:   /* indecisive, so check more clues... */
  187. break;
  188. case 1:
  189. ust_loader = 1;
  190. break;
  191. case 2:
  192. ust_loader = 0;
  193. break;
  194. }
  195. return 1;
  196. }
  197. static BOOL M15_Init(void)
  198. {
  199. if(!(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
  200. return 1;
  201. }
  202. static void M15_Cleanup(void)
  203. {
  204. _mm_free(mh);
  205. _mm_free(patbuf);
  206. }
  207. /*
  208. Old (amiga) noteinfo:
  209.  _____byte 1_____   byte2_    _____byte 3_____   byte4_
  210. /                 /        /                 /      
  211. 0000          0000-00000000  0000          0000-00000000
  212. Upper four    12 bits for    Lower four    Effect command.
  213. bits of sam-  note period.   bits of sam-
  214. ple number.                  ple number.
  215. */
  216. static UBYTE M15_ConvertNote(MODNOTE* n, UBYTE lasteffect)
  217. {
  218. UBYTE instrument,effect,effdat,note;
  219. UWORD period;
  220. UBYTE lastnote=0;
  221. /* decode the 4 bytes that make up a single note */
  222. instrument = n->c>>4;
  223. period     = (((UWORD)n->a&0xf)<<8)+n->b;
  224. effect     = n->c&0xf;
  225. effdat     = n->d;
  226. /* Convert the period to a note number */
  227. note=0;
  228. if(period) {
  229. for(note=0;note<7*OCTAVE;note++)
  230. if(period>=npertab[note]) break;
  231. if(note==7*OCTAVE) note=0;
  232. else note++;
  233. }
  234. if(instrument) {
  235. /* if instrument does not exist, note cut */
  236. if((instrument>15)||(!mh->samples[instrument-1].length)) {
  237. UniPTEffect(0xc,0);
  238. if(effect==0xc) effect=effdat=0;
  239. } else {
  240. /* if we had a note, then change instrument... */
  241. if(note)
  242. UniInstrument(instrument-1);
  243. /* ...otherwise, only adjust volume... */
  244. else {
  245. /* ...unless an effect was specified, which forces a new note
  246.    to be played */
  247. if(effect||effdat) {
  248. UniInstrument(instrument-1);
  249. note=lastnote;
  250. } else
  251. UniPTEffect(0xc,mh->samples[instrument-1].volume&0x7f);
  252. }
  253. }
  254. }
  255. if(note) {
  256. UniNote(note+2*OCTAVE-1);
  257. lastnote=note;
  258. }
  259. /* Convert pattern jump from Dec to Hex */
  260. if(effect == 0xd)
  261. effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
  262. /* Volume slide, up has priority */
  263. if((effect==0xa)&&(effdat&0xf)&&(effdat&0xf0))
  264. effdat&=0xf0;
  265. /* Handle ``heavy'' volumes correctly */
  266. if ((effect == 0xc) && (effdat > 0x40))
  267. effdat = 0x40;
  268. if(ust_loader) {
  269. switch(effect) {
  270. case 0:
  271. case 3:
  272. break;
  273. case 1:
  274. UniPTEffect(0,effdat);
  275. break;
  276. case 2:  
  277. if(effdat&0xf) UniPTEffect(1,effdat&0xf);
  278. else if(effdat>>2)  UniPTEffect(2,effdat>>2);
  279. break;
  280. default:
  281. UniPTEffect(effect,effdat);
  282. break;
  283. }
  284. } else {
  285. /* An isolated 100, 200 or 300 effect should be ignored (no
  286.    "standalone" porta memory in mod files). However, a sequence
  287.    such as 1XX, 100, 100, 100 is fine. */
  288. if ((!effdat) && ((effect == 1)||(effect == 2)||(effect ==3)) &&
  289. (lasteffect < 0x10) && (effect != lasteffect))
  290. effect = 0;
  291. UniPTEffect(effect,effdat);
  292. }
  293. if (effect == 8)
  294. of.flags |= UF_PANNING;
  295. return effect;
  296. }
  297. static UBYTE *M15_ConvertTrack(MODNOTE* n)
  298. {
  299. int t;
  300. UBYTE lasteffect = 0x10; /* non existant effect */
  301. UniReset();
  302. for(t=0;t<64;t++) {
  303. lasteffect = M15_ConvertNote(n,lasteffect);
  304. UniNewline();
  305. n+=4;
  306. }
  307. return UniDup();
  308. }
  309. /* Loads all patterns of a modfile and converts them into the 3 byte format. */
  310. static BOOL M15_LoadPatterns(void)
  311. {
  312. int t,s,tracks=0;
  313. if(!AllocPatterns()) return 0;
  314. if(!AllocTracks()) return 0;
  315. /* Allocate temporary buffer for loading and converting the patterns */
  316. if(!(patbuf=(MODNOTE*)_mm_calloc(64U*4,sizeof(MODNOTE)))) return 0;
  317. for(t=0;t<of.numpat;t++) {
  318. /* Load the pattern into the temp buffer and convert it */
  319. for(s=0;s<(64U*4);s++) {
  320. patbuf[s].a=_mm_read_UBYTE(modreader);
  321. patbuf[s].b=_mm_read_UBYTE(modreader);
  322. patbuf[s].c=_mm_read_UBYTE(modreader);
  323. patbuf[s].d=_mm_read_UBYTE(modreader);
  324. }
  325. for(s=0;s<4;s++)
  326. if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
  327. }
  328. return 1;
  329. }
  330. static BOOL M15_Load(BOOL curious)
  331. {
  332. int t,scan;
  333. SAMPLE *q;
  334. MSAMPINFO *s;
  335. /* try to read module header */
  336. if(!LoadModuleHeader(mh)) {
  337. _mm_errno = MMERR_LOADING_HEADER;
  338. return 0;
  339. }
  340. if(ust_loader)
  341. of.modtype = strdup("Ultimate Soundtracker");
  342. else
  343. of.modtype = strdup("Soundtracker");
  344. /* set module variables */
  345. of.initspeed = 6;
  346. of.inittempo = 125;
  347. of.numchn    = 4;
  348. of.songname  = DupStr(mh->songname,21,1);
  349. of.numpos    = mh->songlength;
  350. of.reppos    = 0;
  351. /* Count the number of patterns */
  352. of.numpat = 0;
  353. for(t=0;t<of.numpos;t++)
  354. if(mh->positions[t]>of.numpat)
  355. of.numpat=mh->positions[t];
  356. /* since some old modules embed extra patterns, we have to check the
  357.    whole list to get the samples' file offsets right - however we can find
  358.    garbage here, so check carefully */
  359. scan=1;
  360. for(t=of.numpos;t<128;t++)
  361. if(mh->positions[t]>=0x80) scan=0;
  362. if (scan)
  363. for(t=of.numpos;t<128;t++) {
  364. if(mh->positions[t]>of.numpat)
  365. of.numpat=mh->positions[t];
  366. if((curious)&&(mh->positions[t])) of.numpos=t+1;
  367. }
  368. of.numpat++;
  369. of.numtrk = of.numpat*of.numchn;
  370. if(!AllocPositions(of.numpos)) return 0;
  371. for(t=0;t<of.numpos;t++)
  372. of.positions[t]=mh->positions[t];
  373. /* Finally, init the sampleinfo structures */
  374. of.numins=of.numsmp=15;
  375. if(!AllocSamples()) return 0;
  376. s = mh->samples;
  377. q = of.samples;
  378. for(t=0;t<of.numins;t++) {
  379. /* convert the samplename */
  380. q->samplename = DupStr(s->samplename,23,1);
  381. /* init the sampleinfo variables and convert the size pointers */
  382. q->speed     = finetune[s->finetune&0xf];
  383. q->volume    = s->volume;
  384. if(ust_loader)
  385. q->loopstart = s->reppos;
  386. else
  387. q->loopstart = s->reppos<<1;
  388. q->loopend   = q->loopstart+(s->replen<<1);
  389. q->length    = s->length<<1;
  390. q->flags = SF_SIGNED;
  391.     if(ust_loader) q->flags |= SF_UST_LOOP;
  392. if(s->replen>2) q->flags |= SF_LOOP;
  393. s++;
  394. q++;
  395. }
  396. if(!M15_LoadPatterns()) return 0;
  397. ust_loader = 0;
  398. return 1;
  399. }
  400. static CHAR *M15_LoadTitle(void)
  401. {
  402. CHAR s[21];
  403. _mm_fseek(modreader,0,SEEK_SET);
  404. if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
  405. s[20]=0; /* just in case */
  406. return(DupStr(s,21,1));
  407. }
  408. /*========== Loader information */
  409. MIKMODAPI MLOADER load_m15={
  410. NULL,
  411. "15-instrument module",
  412. "MOD (15 instrument)",
  413. M15_Init,
  414. M15_Test,
  415. M15_Load,
  416. M15_Cleanup,
  417. M15_LoadTitle
  418. };
  419. /* ex:set ts=4: */