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

Windows CE

开发平台:

C/C++

  1. /* MikMod sound library
  2. (c) 2004, Raphael Assenat and others - see file AUTHORS for
  3. 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_asy.c,v 1.3 2004/01/28 01:18:22 raph Exp $
  21.   ASYLUM Music Format v1.0 (.amf) loader
  22.   adapted from load_mod.c by Raphael Assenat <raph@raphnet.net>,
  23.   with the help of the AMF2MOD utility sourcecode,
  24.   written to convert crusader's amf files into 8
  25.   channels mod file in 1995 by Mr. P / Powersource
  26.   mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca 
  27.   
  28. ==============================================================================*/
  29. #ifdef HAVE_CONFIG_H
  30. #include "config.h"
  31. #endif
  32. #ifdef HAVE_UNISTD_H
  33. #include <unistd.h>
  34. #endif
  35. #include <ctype.h>
  36. #include <string.h>
  37. #include "mikmod_internals.h"
  38. /*========== Module structure */
  39. typedef struct MSAMPINFO {
  40. CHAR samplename[24];
  41. UBYTE finetune;
  42. UBYTE volume;
  43. ULONG length;
  44. ULONG reppos;
  45. ULONG replen;
  46. } MSAMPINFO;
  47. typedef struct MODULEHEADER {
  48. CHAR songname[21];
  49. UBYTE num_patterns; /* number of patterns used */
  50. UBYTE num_orders;
  51. UBYTE positions[256]; /* which pattern to play at pos */
  52. MSAMPINFO samples[64]; /* all sampleinfo */
  53. } MODULEHEADER;
  54. typedef struct MODTYPE {
  55. CHAR id[5];
  56. UBYTE channels;
  57. CHAR *name;
  58. } MODTYPE;
  59. typedef struct MODNOTE {
  60. UBYTE a, b, c, d;
  61. } MODNOTE;
  62. /* This table is taken from AMF2MOD.C
  63.  * written in 1995 by Mr. P / Powersource
  64.  * mrp@fish.share.net, ac054@sfn.saskatoon.sk.ca */ 
  65. UWORD periodtable[]={6848,6464,6096,5760,5424,5120,4832,4560,4304,
  66. 4064,3840,3628,3424,3232,3048,2880,2712,2560,
  67. 2416,2280,2152,2032,1920,1814,1712,1616,1524,
  68. 1440,1356,1280,1208,1140,1076,1016, 960, 907,
  69. 856, 808, 762, 720, 678, 640, 604, 570, 538,
  70. 508, 480, 453, 428, 404, 381, 360, 339, 320,
  71. 302, 285, 269, 254, 240, 226, 214, 202, 190,
  72. 180, 170, 160, 151, 143, 135, 127, 120, 113,
  73. 107, 101,  95,  90,  85,  80,  75,  71,  67,
  74. 63,  60,  56,  53,  50,  47,  45,  42,  40,
  75. 37,  35,  33,  31,  30,  28};
  76. /*========== Loader variables */
  77. static CHAR asylum[] = "Asylum 1.0";
  78. static MODULEHEADER *mh = NULL;
  79. static MODNOTE *patbuf = NULL;
  80. static int modtype = 0;
  81. /*========== Loader code */
  82. static BOOL ASY_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
  83. {
  84. if (!memcmp(id, "ASYLUM Music Format V1.0", 24))
  85. {
  86. *descr = asylum;
  87. *numchn = 8;
  88. modtype = 1;
  89. return 1;
  90. }
  91. return 0;
  92. }
  93. static BOOL ASY_Test(void)
  94. {
  95. UBYTE namestring[24], numchn;
  96. CHAR *descr;
  97. /* Read the magic string */
  98. _mm_fseek(modreader, 0, SEEK_SET);
  99. if (!_mm_read_UBYTES(namestring, 24, modreader))
  100. return 0;
  101. /* Test if the string is what we expect */
  102. if (ASY_CheckType(namestring, &numchn, &descr))
  103. return 1;
  104. return 0;
  105. }
  106. static BOOL ASY_Init(void)
  107. {
  108. if (!(mh = (MODULEHEADER *)_mm_malloc(sizeof(MODULEHEADER))))
  109. return 0;
  110. return 1;
  111. }
  112. static void ASY_Cleanup(void)
  113. {
  114. _mm_free(mh);
  115. _mm_free(patbuf);
  116. }
  117. static void ConvertNote(MODNOTE *n)
  118. {
  119. UBYTE instrument, effect, effdat, note;
  120. UWORD period;
  121. UBYTE lastnote = 0;
  122. instrument = n->b&0x1f;
  123. effect = n->c;
  124. effdat = n->d;
  125. /* convert amf note to mod period */
  126. if (n->a) {
  127. period = periodtable[n->a];
  128. } else {
  129. period = 0;
  130. }
  131. /* Convert the period to a note number */
  132. note = 0;
  133. if (period) 
  134. {
  135. for (note = 0; note < 7 * OCTAVE; note++)
  136. if (period >= npertab[note])
  137. break;
  138. if (note == 7 * OCTAVE)
  139. note = 0;
  140. else
  141. note++;
  142. }
  143. if (instrument) {
  144. /* if instrument does not exist, note cut */
  145. if ((instrument > 31) || (!mh->samples[instrument - 1].length)) {
  146. UniPTEffect(0xc, 0);
  147. if (effect == 0xc)
  148. effect = effdat = 0;
  149. } else {
  150. /* Protracker handling */
  151. if (!modtype) {
  152. /* if we had a note, then change instrument...*/
  153. if (note)
  154. UniInstrument(instrument - 1);
  155. /* ...otherwise, only adjust volume... */
  156. else {
  157. /* ...unless an effect was specified, 
  158.  * which forces a new note to be 
  159.  * played */
  160. if (effect || effdat) {
  161. UniInstrument(instrument - 1);
  162. note = lastnote;
  163. } else
  164. UniPTEffect(0xc,
  165. mh->samples[instrument -
  166. 1].volume & 0x7f);
  167. }
  168. } else {
  169. /* Fasttracker handling */
  170. UniInstrument(instrument - 1);
  171. if (!note)
  172. note = lastnote;
  173. }
  174. }
  175. }
  176. if (note) {
  177. UniNote(note + 2 * OCTAVE - 1);
  178. lastnote = note;
  179. }
  180. /* Convert pattern jump from Dec to Hex */
  181. if (effect == 0xd)
  182. effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf);
  183. /* Volume slide, up has priority */
  184. if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
  185. effdat &= 0xf0;
  186. UniPTEffect(effect, effdat);
  187. }
  188. static UBYTE *ConvertTrack(MODNOTE *n)
  189. {
  190. int t;
  191. UniReset();
  192. for (t = 0; t < 64; t++) {
  193. ConvertNote(n);
  194. UniNewline();
  195. n += of.numchn;
  196. }
  197. return UniDup();
  198. }
  199. /* Loads all patterns of a modfile and converts them into the 3 byte format. */
  200. static BOOL ML_LoadPatterns(void)
  201. {
  202. int t, s, tracks = 0;
  203. if (!AllocPatterns()) {
  204. return 0;
  205. }
  206. if (!AllocTracks()) {
  207. return 0;
  208. }
  209. /* Allocate temporary buffer for loading and converting the patterns */
  210. if (!(patbuf = (MODNOTE *)_mm_calloc(64U * of.numchn, sizeof(MODNOTE))))
  211. return 0;
  212. /* patterns start here */
  213. _mm_fseek(modreader, 0xA66, SEEK_SET);
  214. for (t = 0; t < of.numpat; t++) {
  215. /* Load the pattern into the temp buffer and convert it */
  216. for (s = 0; s < (64U * of.numchn); s++) {
  217. patbuf[s].a = _mm_read_UBYTE(modreader);
  218. patbuf[s].b = _mm_read_UBYTE(modreader);
  219. patbuf[s].c = _mm_read_UBYTE(modreader);
  220. patbuf[s].d = _mm_read_UBYTE(modreader);
  221. }
  222. for (s = 0; s < of.numchn; s++) {
  223. if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s))) {
  224. return 0;
  225. }
  226. }
  227. }
  228. return 1;
  229. }
  230. static BOOL ASY_Load(BOOL curious)
  231. {
  232. int t;
  233. SAMPLE *q;
  234. MSAMPINFO *s;
  235. CHAR *descr=asylum;
  236. ULONG seekpos;
  237. // no title in asylum amf files :(
  238. strcpy(mh->songname, "");
  239. _mm_fseek(modreader, 0x23, SEEK_SET);
  240. mh->num_patterns = _mm_read_UBYTE(modreader);
  241. mh->num_orders = _mm_read_UBYTE(modreader);
  242. // skip unknown byte
  243. _mm_read_UBYTE(modreader);
  244. _mm_read_UBYTES(mh->positions, 256, modreader);
  245. /* read samples headers*/
  246. for (t = 0; t < 64; t++) {
  247. s = &mh->samples[t];
  248. _mm_fseek(modreader, 0x126 + (t*37), SEEK_SET);
  249. _mm_read_string(s->samplename, 22, modreader);
  250. s->samplename[21] = 0; /* just in case */
  251. s->finetune = _mm_read_UBYTE(modreader);
  252. s->volume = _mm_read_UBYTE(modreader);
  253. _mm_read_UBYTE(modreader); // skip unknown byte
  254. s->length = _mm_read_I_ULONG(modreader);
  255. s->reppos = _mm_read_I_ULONG(modreader);
  256. s->replen = _mm_read_I_ULONG(modreader);
  257. }
  258. if (_mm_eof(modreader)) {
  259. _mm_errno = MMERR_LOADING_HEADER;
  260. return 0;
  261. }
  262. /* set module variables */
  263. of.initspeed = 6;
  264. of.inittempo = 125;
  265. of.numchn = 8;
  266. modtype = 0;
  267. of.songname = DupStr(mh->songname, 21, 1);
  268. of.numpos = mh->num_orders;
  269. of.reppos = 0;
  270. of.numpat = mh->num_patterns;
  271. of.numtrk = of.numpat * of.numchn;
  272. /* Copy positions (orders) */
  273. if (!AllocPositions(of.numpos))
  274. return 0;
  275. for (t = 0; t < of.numpos; t++) {
  276. of.positions[t] = mh->positions[t];
  277. }
  278. /* Finally, init the sampleinfo structures  */
  279. of.numins = 31;
  280. of.numsmp = 31;
  281. if (!AllocSamples())
  282. return 0;
  283. s = mh->samples;
  284. q = of.samples;
  285. seekpos = 2662+(2048*(of.numpat));
  286. for (t = 0; t < of.numins; t++) {
  287. /* convert the samplename */
  288. q->samplename = DupStr(s->samplename, 23, 1);
  289. /* init the sampleinfo variables */
  290. q->speed = finetune[s->finetune & 0xf];
  291. q->volume = s->volume & 0x7f;
  292. q->loopstart = (ULONG)s->reppos;
  293. q->loopend = (ULONG)q->loopstart + (s->replen);
  294. q->length = (ULONG)s->length;
  295. q->flags = SF_SIGNED;
  296. q->seekpos = seekpos;
  297. seekpos += q->length;
  298. if ((s->replen) > 2) {
  299. q->flags |= SF_LOOP;
  300. }
  301. /* fix replen if repend > length */
  302. if (q->loopend > q->length)
  303. q->loopend = q->length;
  304. s++;
  305. q++;
  306. }
  307. of.modtype = strdup(descr);
  308. if (!ML_LoadPatterns())
  309. return 0;
  310. return 1;
  311. }
  312. static CHAR *ASY_LoadTitle(void)
  313. {
  314. CHAR *s = ""; // no titles
  315. return (DupStr(s, 21, 1));
  316. }
  317. /*========== Loader information */
  318. MLOADER load_asy = {
  319. NULL,
  320. "AMF",
  321. "AMF (ASYLUM Music Format V1.0)",
  322. ASY_Init,
  323. ASY_Test,
  324. ASY_Load,
  325. ASY_Cleanup,
  326. ASY_LoadTitle
  327. };
  328. /* ex:set ts=4: */