home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / loaders / load_dsm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  7.6 KB  |  347 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  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., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: load_dsm.c,v 1.18 1998/12/07 06:00:12 miod Exp $
  22.  
  23.   DSIK internal format (DSM) module loader
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #include <string.h>
  32.  
  33. #include <mikmod_internals.h>
  34.  
  35. /*========== Module structure */
  36.  
  37. #define DSM_MAXCHAN (16)
  38. #define DSM_MAXORDERS (128)
  39.  
  40. typedef struct DSMSONG {
  41.     CHAR    songname[28];
  42.     UWORD    version;
  43.     UWORD    flags;
  44.     ULONG    reserved2;
  45.     UWORD    numord;
  46.     UWORD    numsmp;
  47.     UWORD    numpat;
  48.     UWORD    numtrk;
  49.     UBYTE    globalvol;
  50.     UBYTE    mastervol;
  51.     UBYTE    speed;
  52.     UBYTE    bpm;
  53.     UBYTE    panpos[DSM_MAXCHAN];
  54.     UBYTE    orders[DSM_MAXORDERS];
  55. } DSMSONG;
  56.  
  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.  
  70. typedef struct DSMNOTE {
  71.     UBYTE    note,ins,vol,cmd,inf;
  72. } DSMNOTE;
  73.  
  74. #define DSM_SURROUND (0xa4)
  75.  
  76. /*========== Loader variables */
  77.  
  78. static    CHAR* SONGID="SONG";
  79. static    CHAR* INSTID="INST";
  80. static    CHAR* PATTID="PATT";
  81.  
  82. static    UBYTE blockid[4];
  83. static    ULONG blockln;
  84. static    ULONG blocklp;
  85. static    DSMSONG* mh=NULL;
  86. static    DSMNOTE* dsmbuf=NULL;
  87.  
  88. static    CHAR DSM_Version[]="DSIK DSM-format";
  89.  
  90. static    unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'};
  91.  
  92. /*========== Loader code */
  93.  
  94. BOOL DSM_Test(void)
  95. {
  96.     UBYTE id[12];
  97.  
  98.     if(!_mm_read_UBYTES(id,12,modfp)) return 0;
  99.     if(!memcmp(id,DSMSIG,4) && !memcmp(id+8,DSMSIG+4,4)) return 1;
  100.  
  101.     return 0;
  102. }
  103.  
  104. BOOL DSM_Init(void)
  105. {
  106.     if(!(dsmbuf=(DSMNOTE *)_mm_malloc(DSM_MAXCHAN*64*sizeof(DSMNOTE)))) return 0;
  107.     if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0;
  108.     return 1;
  109. }
  110.  
  111. void DSM_Cleanup(void)
  112. {
  113.     if(dsmbuf!=NULL) free(dsmbuf);
  114.     if(mh!=NULL) free(mh);
  115.  
  116.     dsmbuf=NULL;
  117.     mh=NULL;
  118. }
  119.  
  120. BOOL GetBlockHeader(void)
  121. {
  122.     /* make sure we're at the right position for reading the
  123.        next riff block, no matter how many bytes read */
  124.     _mm_fseek(modfp, blocklp+blockln, SEEK_SET);
  125.    
  126.     while(1) {
  127.         _mm_read_UBYTES(blockid,4,modfp);
  128.         blockln=_mm_read_I_ULONG(modfp);
  129.         if(feof(modfp)) {
  130.             _mm_errno = MMERR_LOADING_HEADER;
  131.             return 0;
  132.         }
  133.  
  134.         if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) &&
  135.            memcmp(blockid,PATTID,4)) {
  136. #ifdef MIKMOD_DEBUG
  137.                 fprintf(stderr,"\rDSM: Skipping unknown block type %4.4s\n",blockid);
  138. #endif
  139.                 _mm_fseek(modfp, blockln, SEEK_CUR);
  140.         } else
  141.             break;
  142.     }
  143.  
  144.     blocklp = _mm_ftell(modfp);
  145.  
  146.     return 1;
  147. }
  148.  
  149. BOOL DSM_ReadPattern(void)
  150. {
  151.     int flag,row=0;
  152.     SWORD length;
  153.     DSMNOTE *n;
  154.  
  155.     /* clear pattern data */
  156.     memset(dsmbuf,255,DSM_MAXCHAN*64*sizeof(DSMNOTE));
  157.     length=_mm_read_I_SWORD(modfp);
  158.  
  159.     while(row<64) {
  160.         flag=_mm_read_UBYTE(modfp);
  161.         if((feof(modfp))||(--length<0)) {
  162.             _mm_errno = MMERR_LOADING_PATTERN;
  163.             return 0;
  164.         }
  165.  
  166.         if(flag) {
  167.             n=&dsmbuf[((flag&0xf)*64)+row];
  168.             if(flag&0x80) n->note=_mm_read_UBYTE(modfp);
  169.             if(flag&0x40) n->ins=_mm_read_UBYTE(modfp);
  170.             if(flag&0x20) n->vol=_mm_read_UBYTE(modfp);
  171.             if(flag&0x10) {
  172.                 n->cmd=_mm_read_UBYTE(modfp);
  173.                 n->inf=_mm_read_UBYTE(modfp);
  174.             }
  175.         } else
  176.             row++;
  177.     }
  178.  
  179.     return 1;
  180. }
  181.  
  182. UBYTE *DSM_ConvertTrack(DSMNOTE *tr)
  183. {
  184.     int t;
  185.     UBYTE note,ins,vol,cmd,inf;
  186.  
  187.     UniReset();
  188.     for(t=0;t<64;t++) {
  189.         note=tr[t].note;
  190.         ins=tr[t].ins;
  191.         vol=tr[t].vol;
  192.         cmd=tr[t].cmd;
  193.         inf=tr[t].inf;
  194.  
  195.         if(ins!=0 && ins!=255) UniInstrument(ins-1);
  196.         if(note!=255) UniNote(note-1); /* normal note */
  197.         if(vol<65) UniPTEffect(0xc,vol);
  198.  
  199.         if(cmd!=255) {
  200.             if(cmd==0x8) {
  201.                 if(inf==DSM_SURROUND) {
  202.                     UniWrite(UNI_ITEFFECTS0);
  203.                     UniWrite(0x91);
  204.                 } else
  205.                   if(inf<=0x80) {
  206.                     inf=(inf<0x80)?inf<<1:255;
  207.                     UniPTEffect(cmd,inf);
  208.                 }
  209.             } else
  210.               if(cmd==0xb) {
  211.                 if(inf<=0x7f) UniPTEffect(cmd,inf);
  212.             } else {
  213.                 /* Convert pattern jump from Dec to Hex */
  214.                 if(cmd == 0xd)
  215.                     inf = (((inf&0xf0)>>4)*10)+(inf&0xf);
  216.                 UniPTEffect(cmd,inf);
  217.             }
  218.         }
  219.         UniNewline();
  220.     }
  221.     return UniDup();
  222. }
  223.  
  224. BOOL DSM_Load(BOOL curious)
  225. {
  226.     int t;
  227.     DSMINST s;
  228.     SAMPLE *q;
  229.     int cursmp=0,curpat=0,track=0;
  230.  
  231.     blocklp=0;
  232.     blockln=12;
  233.  
  234.     if(!GetBlockHeader()) return 0;
  235.     if(memcmp(blockid,SONGID,4)) {
  236.         _mm_errno = MMERR_LOADING_HEADER;
  237.         return 0;
  238.     }
  239.  
  240.     _mm_read_UBYTES(mh->songname,28,modfp);
  241.     mh->version=_mm_read_I_UWORD(modfp);
  242.     mh->flags=_mm_read_I_UWORD(modfp);
  243.     mh->reserved2=_mm_read_I_ULONG(modfp);
  244.     mh->numord=_mm_read_I_UWORD(modfp);
  245.     mh->numsmp=_mm_read_I_UWORD(modfp);
  246.     mh->numpat=_mm_read_I_UWORD(modfp);
  247.     mh->numtrk=_mm_read_I_UWORD(modfp);
  248.     mh->globalvol=_mm_read_UBYTE(modfp);
  249.     mh->mastervol=_mm_read_UBYTE(modfp);
  250.     mh->speed=_mm_read_UBYTE(modfp);
  251.     mh->bpm=_mm_read_UBYTE(modfp);
  252.     _mm_read_UBYTES(mh->panpos,DSM_MAXCHAN,modfp);
  253.     _mm_read_UBYTES(mh->orders,DSM_MAXORDERS,modfp);
  254.  
  255.     /* set module variables */
  256.     of.initspeed=mh->speed;
  257.     of.inittempo=mh->bpm;
  258.     of.modtype=strdup(DSM_Version);
  259.     of.numchn=mh->numtrk;
  260.     of.numpat=mh->numpat;
  261.     of.numtrk=of.numchn*of.numpat;
  262.     of.songname=DupStr(mh->songname,28);    /* make a cstr of songname */
  263.     of.reppos=0;
  264.  
  265.     for(t=0;t<DSM_MAXCHAN;t++)
  266.         of.panning[t]=mh->panpos[t]==DSM_SURROUND?PAN_SURROUND:
  267.                       mh->panpos[t]<0x80?(mh->panpos[t]<<1):255;
  268.  
  269.     if(!AllocPositions(mh->numord)) return 0;
  270.     of.numpos=0;
  271.     for(t=0;t<mh->numord;t++) {
  272.         of.positions[of.numpos]=mh->orders[t];
  273.         if(mh->orders[t]<254) of.numpos++;
  274.     }
  275.  
  276.     of.numins=of.numsmp=mh->numsmp;
  277.  
  278.     if(!AllocSamples()) return 0;
  279.     if(!AllocTracks()) return 0;
  280.     if(!AllocPatterns()) return 0;
  281.  
  282.     while(cursmp<of.numins||curpat<of.numpat) {
  283.         if(!GetBlockHeader()) return 0;
  284.         if(!memcmp(blockid,INSTID,4) && cursmp<of.numins) {
  285.             q=&of.samples[cursmp];
  286.  
  287.             /* try to read sample info */
  288.             _mm_read_UBYTES(s.filename,13,modfp);
  289.             s.flags=_mm_read_I_UWORD(modfp);
  290.             s.volume=_mm_read_UBYTE(modfp);
  291.             s.length=_mm_read_I_ULONG(modfp);
  292.             s.loopstart=_mm_read_I_ULONG(modfp);
  293.             s.loopend=_mm_read_I_ULONG(modfp);
  294.             s.reserved1=_mm_read_I_ULONG(modfp);
  295.             s.c2spd=_mm_read_I_UWORD(modfp);
  296.             s.period=_mm_read_I_UWORD(modfp);
  297.             _mm_read_UBYTES(s.samplename,28,modfp);
  298.  
  299.             q->samplename=DupStr(s.samplename,28);
  300.             q->seekpos=_mm_ftell(modfp);
  301.             q->speed=s.c2spd;
  302.             q->length=s.length;
  303.             q->loopstart=s.loopstart;
  304.             q->loopend=s.loopend;
  305.             q->volume=s.volume;
  306.  
  307.             if(s.flags&1) q->flags|=SF_LOOP;
  308.             if(s.flags&2) q->flags|=SF_SIGNED;
  309.             /* (s.flags&4) means packed sample,
  310.                but did they really exist in dsm ?*/
  311.             cursmp++;
  312.         } else
  313.           if(!memcmp(blockid,PATTID,4) && curpat<of.numpat) {
  314.             DSM_ReadPattern();
  315.             for(t=0;t<of.numchn;t++)
  316.                 if(!(of.tracks[track++]=DSM_ConvertTrack(&dsmbuf[t*64]))) return 0;
  317.             curpat++;
  318.         }
  319.     }
  320.  
  321.     return 1;
  322. }
  323.  
  324. CHAR *DSM_LoadTitle(void)
  325. {
  326.     CHAR s[28];
  327.  
  328.     _mm_fseek(modfp,12,SEEK_SET);
  329.     if(!fread(s,28,1,modfp)) return NULL;
  330.    
  331.     return(DupStr(s,28));
  332. }
  333.  
  334. /*========== Loader information */
  335.  
  336. MLOADER load_dsm={
  337.     NULL,
  338.     "DSM",
  339.     "DSM loader v0.1",
  340.     DSM_Init,
  341.     DSM_Test,
  342.     DSM_Load,
  343.     DSM_Cleanup,
  344.     DSM_LoadTitle
  345. };
  346.  
  347.