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

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_dsm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  21.   DSIK internal format (DSM) 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. #define DSM_MAXCHAN (16)
  40. #define DSM_MAXORDERS (128)
  41. typedef struct DSMSONG {
  42. CHAR songname[28];
  43. UWORD version;
  44. UWORD flags;
  45. ULONG reserved2;
  46. UWORD numord;
  47. UWORD numsmp;
  48. UWORD numpat;
  49. UWORD numtrk;
  50. UBYTE globalvol;
  51. UBYTE mastervol;
  52. UBYTE speed;
  53. UBYTE bpm;
  54. UBYTE panpos[DSM_MAXCHAN];
  55. UBYTE orders[DSM_MAXORDERS];
  56. } DSMSONG;
  57. typedef struct DSMINST {
  58. CHAR filename[13];
  59. UWORD flags;
  60. UBYTE volume;
  61. ULONG length;
  62. ULONG loopstart;
  63. ULONG loopend;
  64. ULONG reserved1;
  65. UWORD c2spd;
  66. UWORD period;
  67. CHAR samplename[28];
  68. } DSMINST;
  69. typedef struct DSMNOTE {
  70. UBYTE note,ins,vol,cmd,inf;
  71. } DSMNOTE;
  72. #define DSM_SURROUND (0xa4)
  73. /*========== Loader variables */
  74. static CHAR* SONGID="SONG";
  75. static CHAR* INSTID="INST";
  76. static CHAR* PATTID="PATT";
  77. static UBYTE blockid[4];
  78. static ULONG blockln;
  79. static ULONG blocklp;
  80. static DSMSONG* mh=NULL;
  81. static DSMNOTE* dsmbuf=NULL;
  82. static CHAR DSM_Version[]="DSIK DSM-format";
  83. static unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'};
  84. /*========== Loader code */
  85. BOOL DSM_Test(void)
  86. {
  87. UBYTE id[12];
  88. if(!_mm_read_UBYTES(id,12,modreader)) return 0;
  89. if(!memcmp(id,DSMSIG,4) && !memcmp(id+8,DSMSIG+4,4)) return 1;
  90. return 0;
  91. }
  92. BOOL DSM_Init(void)
  93. {
  94. if(!(dsmbuf=(DSMNOTE *)_mm_malloc(DSM_MAXCHAN*64*sizeof(DSMNOTE)))) return 0;
  95. if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0;
  96. return 1;
  97. }
  98. void DSM_Cleanup(void)
  99. {
  100. _mm_free(dsmbuf);
  101. _mm_free(mh);
  102. }
  103. static BOOL GetBlockHeader(void)
  104. {
  105. /* make sure we're at the right position for reading the
  106.    next riff block, no matter how many bytes read */
  107. _mm_fseek(modreader, blocklp+blockln, SEEK_SET);
  108.    
  109. while(1) {
  110. _mm_read_UBYTES(blockid,4,modreader);
  111. blockln=_mm_read_I_ULONG(modreader);
  112. if(_mm_eof(modreader)) {
  113. _mm_errno = MMERR_LOADING_HEADER;
  114. return 0;
  115. }
  116. if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) &&
  117.    memcmp(blockid,PATTID,4)) {
  118. #ifdef MIKMOD_DEBUG
  119. fprintf(stderr,"rDSM: Skipping unknown block type %4.4sn",blockid);
  120. #endif
  121. _mm_fseek(modreader, blockln, SEEK_CUR);
  122. } else
  123. break;
  124. }
  125. blocklp = _mm_ftell(modreader);
  126. return 1;
  127. }
  128. static BOOL DSM_ReadPattern(void)
  129. {
  130. int flag,row=0;
  131. SWORD length;
  132. DSMNOTE *n;
  133. /* clear pattern data */
  134. memset(dsmbuf,255,DSM_MAXCHAN*64*sizeof(DSMNOTE));
  135. length=_mm_read_I_SWORD(modreader);
  136. while(row<64) {
  137. flag=_mm_read_UBYTE(modreader);
  138. if((_mm_eof(modreader))||(--length<0)) {
  139. _mm_errno = MMERR_LOADING_PATTERN;
  140. return 0;
  141. }
  142. if(flag) {
  143. n=&dsmbuf[((flag&0xf)*64)+row];
  144. if(flag&0x80) n->note=_mm_read_UBYTE(modreader);
  145. if(flag&0x40) n->ins=_mm_read_UBYTE(modreader);
  146. if(flag&0x20) n->vol=_mm_read_UBYTE(modreader);
  147. if(flag&0x10) {
  148. n->cmd=_mm_read_UBYTE(modreader);
  149. n->inf=_mm_read_UBYTE(modreader);
  150. }
  151. } else
  152. row++;
  153. }
  154. return 1;
  155. }
  156. static UBYTE *DSM_ConvertTrack(DSMNOTE *tr)
  157. {
  158. int t;
  159. UBYTE note,ins,vol,cmd,inf;
  160. UniReset();
  161. for(t=0;t<64;t++) {
  162. note=tr[t].note;
  163. ins=tr[t].ins;
  164. vol=tr[t].vol;
  165. cmd=tr[t].cmd;
  166. inf=tr[t].inf;
  167. if(ins!=0 && ins!=255) UniInstrument(ins-1);
  168. if(note!=255) UniNote(note-1); /* normal note */
  169. if(vol<65) UniPTEffect(0xc,vol);
  170. if(cmd!=255) {
  171. if(cmd==0x8) {
  172. if(inf==DSM_SURROUND)
  173. UniEffect(UNI_ITEFFECTS0,0x91);
  174. else
  175.   if(inf<=0x80) {
  176. inf=(inf<0x80)?inf<<1:255;
  177. UniPTEffect(cmd,inf);
  178. }
  179. } else
  180.   if(cmd==0xb) {
  181. if(inf<=0x7f) UniPTEffect(cmd,inf);
  182. } else {
  183. /* Convert pattern jump from Dec to Hex */
  184. if(cmd == 0xd)
  185. inf = (((inf&0xf0)>>4)*10)+(inf&0xf);
  186. UniPTEffect(cmd,inf);
  187. }
  188. }
  189. UniNewline();
  190. }
  191. return UniDup();
  192. }
  193. BOOL DSM_Load(BOOL curious)
  194. {
  195. int t;
  196. DSMINST s;
  197. SAMPLE *q;
  198. int cursmp=0,curpat=0,track=0;
  199. blocklp=0;
  200. blockln=12;
  201. if(!GetBlockHeader()) return 0;
  202. if(memcmp(blockid,SONGID,4)) {
  203. _mm_errno = MMERR_LOADING_HEADER;
  204. return 0;
  205. }
  206. _mm_read_UBYTES(mh->songname,28,modreader);
  207. mh->version=_mm_read_I_UWORD(modreader);
  208. mh->flags=_mm_read_I_UWORD(modreader);
  209. mh->reserved2=_mm_read_I_ULONG(modreader);
  210. mh->numord=_mm_read_I_UWORD(modreader);
  211. mh->numsmp=_mm_read_I_UWORD(modreader);
  212. mh->numpat=_mm_read_I_UWORD(modreader);
  213. mh->numtrk=_mm_read_I_UWORD(modreader);
  214. mh->globalvol=_mm_read_UBYTE(modreader);
  215. mh->mastervol=_mm_read_UBYTE(modreader);
  216. mh->speed=_mm_read_UBYTE(modreader);
  217. mh->bpm=_mm_read_UBYTE(modreader);
  218. _mm_read_UBYTES(mh->panpos,DSM_MAXCHAN,modreader);
  219. _mm_read_UBYTES(mh->orders,DSM_MAXORDERS,modreader);
  220. /* set module variables */
  221. of.initspeed=mh->speed;
  222. of.inittempo=mh->bpm;
  223. of.modtype=strdup(DSM_Version);
  224. of.numchn=mh->numtrk;
  225. of.numpat=mh->numpat;
  226. of.numtrk=of.numchn*of.numpat;
  227. of.songname=DupStr(mh->songname,28,1); /* make a cstr of songname */
  228. of.reppos=0;
  229. of.flags |= UF_PANNING;
  230. /* XXX whenever possible, we should try to determine the original format.
  231.    Here we assume it was S3M-style wrt bpmlimit... */
  232. of.bpmlimit = 32;
  233. for(t=0;t<DSM_MAXCHAN;t++)
  234. of.panning[t]=mh->panpos[t]==DSM_SURROUND?PAN_SURROUND:
  235.               mh->panpos[t]<0x80?(mh->panpos[t]<<1):255;
  236. if(!AllocPositions(mh->numord)) return 0;
  237. of.numpos=0;
  238. for(t=0;t<mh->numord;t++) {
  239. int order=mh->orders[t];
  240. if(order==255) order=LAST_PATTERN;
  241. of.positions[of.numpos]=order;
  242. if(mh->orders[t]<254) of.numpos++;
  243. }
  244. of.numins=of.numsmp=mh->numsmp;
  245. if(!AllocSamples()) return 0;
  246. if(!AllocTracks()) return 0;
  247. if(!AllocPatterns()) return 0;
  248. while(cursmp<of.numins||curpat<of.numpat) {
  249. if(!GetBlockHeader()) return 0;
  250. if(!memcmp(blockid,INSTID,4) && cursmp<of.numins) {
  251. q=&of.samples[cursmp];
  252. /* try to read sample info */
  253. _mm_read_UBYTES(s.filename,13,modreader);
  254. s.flags=_mm_read_I_UWORD(modreader);
  255. s.volume=_mm_read_UBYTE(modreader);
  256. s.length=_mm_read_I_ULONG(modreader);
  257. s.loopstart=_mm_read_I_ULONG(modreader);
  258. s.loopend=_mm_read_I_ULONG(modreader);
  259. s.reserved1=_mm_read_I_ULONG(modreader);
  260. s.c2spd=_mm_read_I_UWORD(modreader);
  261. s.period=_mm_read_I_UWORD(modreader);
  262. _mm_read_UBYTES(s.samplename,28,modreader);
  263. q->samplename=DupStr(s.samplename,28,1);
  264. q->seekpos=_mm_ftell(modreader);
  265. q->speed=s.c2spd;
  266. q->length=s.length;
  267. q->loopstart=s.loopstart;
  268. q->loopend=s.loopend;
  269. q->volume=s.volume;
  270. if(s.flags&1) q->flags|=SF_LOOP;
  271. if(s.flags&2) q->flags|=SF_SIGNED;
  272. /* (s.flags&4) means packed sample,
  273.    but did they really exist in dsm ?*/
  274. cursmp++;
  275. } else
  276.   if(!memcmp(blockid,PATTID,4) && curpat<of.numpat) {
  277. DSM_ReadPattern();
  278. for(t=0;t<of.numchn;t++)
  279. if(!(of.tracks[track++]=DSM_ConvertTrack(&dsmbuf[t*64]))) return 0;
  280. curpat++;
  281. }
  282. }
  283. return 1;
  284. }
  285. CHAR *DSM_LoadTitle(void)
  286. {
  287. CHAR s[28];
  288. _mm_fseek(modreader,12,SEEK_SET);
  289. if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
  290.    
  291. return(DupStr(s,28,1));
  292. }
  293. /*========== Loader information */
  294. MIKMODAPI MLOADER load_dsm={
  295. NULL,
  296. "DSM",
  297. "DSM (DSIK internal format)",
  298. DSM_Init,
  299. DSM_Test,
  300. DSM_Load,
  301. DSM_Cleanup,
  302. DSM_LoadTitle
  303. };
  304. /* ex:set ts=4: */