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

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_ult.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   Ultratracker (ULT) 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 ULTHEADER {
  41. CHAR  id[16];
  42. CHAR  songtitle[32];
  43. UBYTE reserved;
  44. } ULTHEADER;
  45. /* sample information */
  46. typedef struct ULTSAMPLE {
  47. CHAR  samplename[32];
  48. CHAR  dosname[12];
  49. SLONG loopstart;
  50. SLONG loopend;
  51. SLONG sizestart;
  52. SLONG sizeend;
  53. UBYTE volume;
  54. UBYTE flags;
  55. UWORD speed;
  56. SWORD finetune;
  57. } ULTSAMPLE;
  58. typedef struct ULTEVENT {
  59. UBYTE note,sample,eff,dat1,dat2;
  60. } ULTEVENT;
  61. /*========== Loader variables */
  62. #define ULTS_16BITS     4
  63. #define ULTS_LOOP       8
  64. #define ULTS_REVERSE    16
  65. #define ULT_VERSION_LEN 18
  66. static CHAR ULT_Version[ULT_VERSION_LEN]="Ultra Tracker v1.x";
  67. static ULTEVENT ev;
  68. /*========== Loader code */
  69. BOOL ULT_Test(void)
  70. {
  71. CHAR id[16];
  72. if(!_mm_read_string(id,15,modreader)) return 0;
  73. if(strncmp(id,"MAS_UTrack_V00",14)) return 0;
  74. if((id[14]<'1')||(id[14]>'4')) return 0;
  75. return 1;
  76. }
  77. BOOL ULT_Init(void)
  78. {
  79. return 1;
  80. }
  81. void ULT_Cleanup(void)
  82. {
  83. }
  84. static UBYTE ReadUltEvent(ULTEVENT* event)
  85. {
  86. UBYTE flag,rep=1;
  87. flag = _mm_read_UBYTE(modreader);
  88. if(flag==0xfc) {
  89. rep = _mm_read_UBYTE(modreader);
  90. event->note =_mm_read_UBYTE(modreader);
  91. } else
  92. event->note = flag;
  93. event->sample   =_mm_read_UBYTE(modreader);
  94. event->eff      =_mm_read_UBYTE(modreader);
  95. event->dat1     =_mm_read_UBYTE(modreader);
  96. event->dat2     =_mm_read_UBYTE(modreader);
  97. return rep;
  98. }
  99. BOOL ULT_Load(BOOL curious)
  100. {
  101. int t,u,tracks=0;
  102. SAMPLE *q;
  103. ULTSAMPLE s;
  104. ULTHEADER mh;
  105. UBYTE nos,noc,nop;
  106. /* try to read module header */
  107. _mm_read_string(mh.id,15,modreader);
  108. _mm_read_string(mh.songtitle,32,modreader);
  109. mh.reserved=_mm_read_UBYTE(modreader);
  110. if(_mm_eof(modreader)) {
  111. _mm_errno = MMERR_LOADING_HEADER;
  112. return 0;
  113. }
  114. ULT_Version[ULT_VERSION_LEN-1]='3'+(mh.id[14]-'1');
  115. of.modtype   = DupStr(ULT_Version,ULT_VERSION_LEN,1);
  116. of.initspeed = 6;
  117. of.inittempo = 125;
  118. of.reppos    = 0;
  119. /* read songtext */
  120. if ((mh.id[14]>'1')&&(mh.reserved))
  121. if(!ReadLinedComment(mh.reserved * 32, 32)) return 0;
  122. nos=_mm_read_UBYTE(modreader);
  123. if(_mm_eof(modreader)) {
  124. _mm_errno = MMERR_LOADING_HEADER;
  125. return 0;
  126. }
  127. of.songname=DupStr(mh.songtitle,32,1);
  128. of.numins=of.numsmp=nos;
  129. if(!AllocSamples()) return 0;
  130. q = of.samples;
  131. for(t=0;t<nos;t++) {
  132. /* try to read sample info */
  133. _mm_read_string(s.samplename,32,modreader);
  134. _mm_read_string(s.dosname,12,modreader);
  135. s.loopstart     =_mm_read_I_ULONG(modreader);
  136. s.loopend       =_mm_read_I_ULONG(modreader);
  137. s.sizestart     =_mm_read_I_ULONG(modreader);
  138. s.sizeend       =_mm_read_I_ULONG(modreader);
  139. s.volume        =_mm_read_UBYTE(modreader);
  140. s.flags         =_mm_read_UBYTE(modreader);
  141. s.speed         =(mh.id[14]>='4')?_mm_read_I_UWORD(modreader):8363;
  142. s.finetune      =_mm_read_I_SWORD(modreader);
  143. if(_mm_eof(modreader)) {
  144. _mm_errno = MMERR_LOADING_SAMPLEINFO;
  145. return 0;
  146. }
  147. q->samplename=DupStr(s.samplename,32,1);
  148. /* The correct formula for the coefficient would be
  149.    pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point
  150.    here, we'll use a first order approximation here.
  151.    1/567290 == Ln(2)/OCTAVE/32768 */
  152. q->speed=s.speed+s.speed*(((SLONG)s.speed*(SLONG)s.finetune)/567290);
  153. q->length    = s.sizeend-s.sizestart;
  154. q->volume    = s.volume>>2;
  155. q->loopstart = s.loopstart;
  156. q->loopend   = s.loopend;
  157. q->flags = SF_SIGNED;
  158. if(s.flags&ULTS_LOOP) q->flags|=SF_LOOP;
  159. if(s.flags&ULTS_16BITS) {
  160. s.sizeend+=(s.sizeend-s.sizestart);
  161. s.sizestart<<=1;
  162. q->flags|=SF_16BITS;
  163. q->loopstart>>=1;
  164. q->loopend>>=1;
  165. }
  166. q++;
  167. }
  168. if(!AllocPositions(256)) return 0;
  169. for(t=0;t<256;t++)
  170. of.positions[t]=_mm_read_UBYTE(modreader);
  171. for(t=0;t<256;t++)
  172. if(of.positions[t]==255) {
  173. of.positions[t]=LAST_PATTERN;
  174. break;
  175. }
  176. of.numpos=t;
  177. noc=_mm_read_UBYTE(modreader);
  178. nop=_mm_read_UBYTE(modreader);
  179. of.numchn=++noc;
  180. of.numpat=++nop;
  181. of.numtrk=of.numchn*of.numpat;
  182. if(!AllocTracks()) return 0;
  183. if(!AllocPatterns()) return 0;
  184. for(u=0;u<of.numchn;u++)
  185. for(t=0;t<of.numpat;t++)
  186. of.patterns[(t*of.numchn)+u]=tracks++;
  187. /* read pan position table for v1.5 and higher */
  188. if(mh.id[14]>='3') {
  189. for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modreader)<<4;
  190. of.flags |= UF_PANNING;
  191. }
  192. for(t=0;t<of.numtrk;t++) {
  193. int rep,row=0;
  194. UniReset();
  195. while(row<64) {
  196. rep=ReadUltEvent(&ev);
  197. if(_mm_eof(modreader)) {
  198. _mm_errno = MMERR_LOADING_TRACK;
  199. return 0;
  200. }
  201. while(rep--) {
  202. UBYTE eff;
  203. int offset;
  204. if(ev.sample) UniInstrument(ev.sample-1);
  205. if(ev.note)   UniNote(ev.note+2*OCTAVE-1);
  206. /* first effect - various fixes by Alexander Kerkhove and
  207.                   Thomas Neumann */
  208. eff = ev.eff>>4;
  209. switch(eff) {
  210. case 0x3: /* tone portamento */
  211. UniEffect(UNI_ITEFFECTG,ev.dat2);
  212. break;
  213. case 0x5:
  214. break;
  215. case 0x9: /* sample offset */
  216. offset=(ev.dat2<<8)|((ev.eff&0xf)==9?ev.dat1:0);
  217. UniEffect(UNI_ULTEFFECT9,offset);
  218. break;
  219. case 0xb: /* panning */
  220. UniPTEffect(8,ev.dat2*0xf);
  221. of.flags |= UF_PANNING;
  222. break;
  223. case 0xc: /* volume */
  224. UniPTEffect(eff,ev.dat2>>2);
  225. break;
  226. default:
  227. UniPTEffect(eff,ev.dat2);
  228. break;
  229. }
  230. /* second effect */
  231. eff=ev.eff&0xf;
  232. switch(eff) {
  233. case 0x3: /* tone portamento */
  234. UniEffect(UNI_ITEFFECTG,ev.dat1);
  235. break;
  236. case 0x5:
  237. break;
  238. case 0x9: /* sample offset */
  239. if((ev.eff>>4)!=9)
  240. UniEffect(UNI_ULTEFFECT9,((UWORD)ev.dat1)<<8);
  241. break;
  242. case 0xb: /* panning */
  243. UniPTEffect(8,ev.dat1*0xf);
  244. of.flags |= UF_PANNING;
  245. break;
  246. case 0xc: /* volume */
  247. UniPTEffect(eff,ev.dat1>>2);
  248. break;
  249. default:
  250. UniPTEffect(eff,ev.dat1);
  251. break;
  252. }
  253. UniNewline();
  254. row++;
  255. }
  256. }
  257. if(!(of.tracks[t]=UniDup())) return 0;
  258. }
  259. return 1;
  260. }
  261. CHAR *ULT_LoadTitle(void)
  262. {
  263. CHAR s[32];
  264. _mm_fseek(modreader,15,SEEK_SET);
  265. if(!_mm_read_UBYTES(s,32,modreader)) return NULL;
  266. return(DupStr(s,32,1));
  267. }
  268. /*========== Loader information */
  269. MIKMODAPI MLOADER load_ult={
  270. NULL,
  271. "ULT",
  272. "ULT (UltraTracker)",
  273. ULT_Init,
  274. ULT_Test,
  275. ULT_Load,
  276. ULT_Cleanup,
  277. ULT_LoadTitle
  278. };
  279. /* ex:set ts=4: */