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_669.c next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  7.6 KB  |  340 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_669.c,v 1.19 1998/12/07 06:00:25 miod Exp $
  22.  
  23.   Composer 669 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. /* header */
  38. typedef struct S69HEADER {   
  39.     UBYTE    marker[2];
  40.     CHAR    message[108];
  41.     UBYTE    nos;
  42.     UBYTE    nop;
  43.     UBYTE    looporder;
  44.     UBYTE    orders[0x80];
  45.     UBYTE    tempos[0x80];
  46.     UBYTE    breaks[0x80];
  47. } S69HEADER;
  48.  
  49. /* sample information */
  50. typedef struct S69SAMPLE {
  51.     CHAR    filename[13];
  52.     SLONG    length;
  53.     SLONG    loopbeg;
  54.     SLONG    loopend;
  55. } S69SAMPLE;
  56.  
  57. /* encoded note */
  58. typedef struct S69NOTE {
  59.     UBYTE    a,b,c;
  60. } S69NOTE;
  61.  
  62. /*========== Loader variables */
  63.  
  64. /* current pattern */
  65. static    S69NOTE* s69pat=NULL;
  66. /* Module header */
  67. static    S69HEADER* mh=NULL;
  68.  
  69. /* file type identification */
  70. static    CHAR* S69_Version[]={
  71.     "Composer 669",
  72.     "Extended 669"
  73. };
  74.  
  75. /*========== Loader code */
  76.  
  77. BOOL S69_Test(void)
  78. {
  79.     UBYTE id[2];
  80.  
  81.     if(!_mm_read_UBYTES(id,2,modfp))
  82.         return 0;
  83.     /* look for id */
  84.     if(!memcmp(id,"if",2) || !memcmp(id,"JN",2)) {
  85.         /* skip song message */
  86.         _mm_fseek(modfp,108,SEEK_CUR);
  87.         /* sanity checks */
  88.         if(_mm_read_UBYTE(modfp) > 64) return 0;
  89.         if(_mm_read_UBYTE(modfp) > 128) return 0;
  90.         if(_mm_read_UBYTE(modfp) > 127) return 0;
  91.     } else
  92.         return 0;
  93.  
  94.     return 1;
  95. }
  96.  
  97. BOOL S69_Init(void)
  98. {
  99.     if(!(s69pat=(S69NOTE *)_mm_malloc(64*8*sizeof(S69NOTE)))) return 0;
  100.     if(!(mh=(S69HEADER *)_mm_malloc(sizeof(S69HEADER)))) return 0;
  101.  
  102.     return 1;
  103. }
  104.  
  105. void S69_Cleanup(void)
  106. {
  107.     if(s69pat) free(s69pat);
  108.     if(mh) free(mh);
  109.  
  110.     s69pat=NULL;
  111.     mh=NULL;
  112. }
  113.  
  114. BOOL S69_LoadPatterns(void)
  115. {
  116.     int track,row,channel;
  117.     UBYTE note,inst,vol,effect,lastfx,lastval;
  118.     S69NOTE *cur;
  119.     int tracks=0;
  120.     
  121.     if(!AllocPatterns()) return 0;
  122.     if(!AllocTracks()) return 0;
  123.  
  124.     for(track=0;track<of.numpat;track++) {
  125.         /* set pattern break locations */
  126.         of.pattrows[track]=mh->breaks[track]+1;
  127.  
  128.         /* load the 669 pattern */
  129.         cur=s69pat;
  130.         for(row=0;row<64;row++) {
  131.             for(channel=0;channel<8;channel++,cur++) {
  132.                 cur->a = _mm_read_UBYTE(modfp);
  133.                 cur->b = _mm_read_UBYTE(modfp);
  134.                 cur->c = _mm_read_UBYTE(modfp);
  135.             }
  136.         }
  137.  
  138.         if(feof(modfp)) {
  139.             _mm_errno = MMERR_LOADING_PATTERN;
  140.             return 0;
  141.         }
  142.  
  143.         /* translate the pattern */
  144.         for(channel=0;channel<8;channel++) {
  145.             UniReset();
  146.             /* set pattern tempo */
  147.             UniPTEffect(0xf,78);
  148.             UniPTEffect(0xf,mh->tempos[track]);
  149.  
  150.             lastfx=0xff,lastval=0;
  151.  
  152.             for(row=0;row<=mh->breaks[track];row++) {
  153.                 int a,b,c;
  154.  
  155.                 /* fetch the encoded note */
  156.                 a=s69pat[(row*8)+channel].a;
  157.                 b=s69pat[(row*8)+channel].b;
  158.                 c=s69pat[(row*8)+channel].c;
  159.  
  160.                 /* decode it */
  161.                 note=a>>2;
  162.                 inst=((a&0x3)<<4)|((b&0xf0)>>4);
  163.                 vol=b&0xf;
  164.  
  165.                 if (a<0xff) {
  166.                     if (a<0xfe) {
  167.                         UniInstrument(inst);
  168.                         UniNote(note+2*OCTAVE);
  169.                         lastfx=0xff; /* reset background effect memory */
  170.                     }
  171.                     UniPTEffect(0xc,vol<<2);
  172.                 }
  173.  
  174.                 if ((c!=0xff)||(lastfx!=0xff)) {
  175.                     if(c==0xff)
  176.                         c=lastfx,effect=lastval;
  177.                     else
  178.                         effect=c&0xf;
  179.  
  180.                     switch(c>>4) {
  181.                         case 0: /* porta up */
  182.                             UniPTEffect(0x1,effect);
  183.                             lastfx=c,lastval=effect;
  184.                             break;
  185.                         case 1: /* porta down */
  186.                             UniPTEffect(0x2,effect);
  187.                             lastfx=c,lastval=effect;
  188.                             break;
  189.                         case 2: /* porta to note */
  190.                             UniPTEffect(0x3,effect);
  191.                             lastfx=c,lastval=effect;
  192.                             break;
  193. #ifdef MIKMOD_DEBUG
  194.                         case 3: /* frequency adjust */
  195.                             fprintf(stderr,"\r669: unsupported frequency adjust effect at pat=%d row=%d chan=%d\n",
  196.                                    track,row,channel);
  197.                             break;
  198. #endif
  199.                         case 4: /* vibrato */
  200.                             UniPTEffect(0x4,effect);
  201.                             lastfx=c,lastval=effect;
  202.                             break;
  203.                         case 5: /* set speed */
  204.                             if (effect)
  205.                                 UniPTEffect(0xf,effect);
  206.                             else 
  207.                               if(mh->marker[0]!=0x69) {
  208. #ifdef MIKMOD_DEBUG
  209.                                 fprintf(stderr,"\r669: unsupported super fast tempo at pat=%d row=%d chan=%d\n",
  210.                                        track,row,channel);
  211. #endif
  212.                             }
  213.                             break;
  214.                     }
  215.                 }
  216.                 UniNewline();
  217.             }
  218.             if(!(of.tracks[tracks++]=UniDup())) return 0;
  219.         }
  220.     }
  221.  
  222.     return 1;
  223. }
  224.  
  225. BOOL S69_Load(BOOL curious)
  226. {
  227.     int i;
  228.     SAMPLE *current;
  229.     S69SAMPLE sample;
  230.  
  231.     /* module header */
  232.     _mm_read_UBYTES(mh->marker,2,modfp);
  233.     _mm_read_UBYTES((UBYTE*)mh->message,108,modfp);
  234.     mh->nos=_mm_read_UBYTE(modfp);
  235.     mh->nop=_mm_read_UBYTE(modfp);
  236.     mh->looporder=_mm_read_UBYTE(modfp);
  237.     _mm_read_UBYTES(mh->orders,0x80,modfp);
  238.     for(i=0;i<0x80;i++)
  239.         if ((mh->orders[i]>=0x80)&&(mh->orders[i]!=0xff)) {
  240.             _mm_errno=MMERR_NOT_A_MODULE;
  241.             return 1;
  242.         }
  243.     _mm_read_UBYTES(mh->tempos,0x80,modfp);
  244.     for(i=0;i<0x80;i++)
  245.         if ((!mh->tempos[i])||(mh->tempos[i]>32)) {
  246.             _mm_errno=MMERR_NOT_A_MODULE;
  247.             return 1;
  248.         }
  249.     _mm_read_UBYTES(mh->breaks,0x80,modfp);
  250.     for(i=0;i<0x80;i++)
  251.         if (mh->breaks[i]>0x3f) {
  252.             _mm_errno=MMERR_NOT_A_MODULE;
  253.             return 1;
  254.         }
  255.  
  256.     /* set module variables */
  257.     of.initspeed=4;
  258.     of.inittempo=78;
  259.     of.songname=DupStr(mh->message,36);
  260.     of.modtype=strdup(S69_Version[memcmp(mh->marker,"JN",2)==0]);
  261.     of.numchn=8;
  262.     of.numpat=mh->nop;
  263.     of.numins=of.numsmp=mh->nos;
  264.     of.numtrk=of.numchn*of.numpat;
  265.     of.flags=UF_XMPERIODS|UF_LINEAR;
  266.     if(mh->message) 
  267.         if((of.comment=(CHAR*)_mm_malloc(3*(36+1)+1))) {
  268.             strncpy(of.comment,mh->message,36);
  269.             strcat(of.comment,"\r");
  270.             if (strlen(mh->message)>36) strncat(of.comment,mh->message+36,36);
  271.             strcat(of.comment,"\r");
  272.             if (strlen(mh->message)>72) strncat(of.comment,mh->message+72,36);
  273.             strcat(of.comment,"\r");
  274.             of.comment[3*(36+1)]=0;
  275.         }
  276.  
  277.     if(!AllocPositions(0x80)) return 0;
  278.     for(i=0;i<0x80;i++) {
  279.         if(mh->orders[i]>=mh->nop) break;
  280.         of.positions[i]=mh->orders[i];
  281.     }
  282.     of.numpos=i;
  283.     of.reppos=mh->looporder<of.numpos?mh->looporder:0;
  284.  
  285.     if(!AllocSamples()) return 0;
  286.     current=of.samples;
  287.  
  288.     for(i=0;i<of.numins;i++) {
  289.         /* sample information */
  290.         _mm_read_UBYTES((UBYTE*)sample.filename,13,modfp);
  291.         sample.length=_mm_read_I_SLONG(modfp);
  292.         sample.loopbeg=_mm_read_I_SLONG(modfp);
  293.         sample.loopend=_mm_read_I_SLONG(modfp);
  294.         if (sample.loopend==0xfffff) sample.loopend=0;
  295.  
  296.         if((sample.length<0)||(sample.loopbeg<-1)||(sample.loopend<-1)) {
  297.             _mm_errno = MMERR_LOADING_HEADER;
  298.             return 0;
  299.         }
  300.  
  301.         current->samplename=DupStr(sample.filename,13);
  302.         current->seekpos=0;
  303.         current->speed=0;
  304.         current->length=sample.length;
  305.         current->loopstart=sample.loopbeg;
  306.         current->loopend=(sample.loopend<sample.length)?sample.loopend:sample.length;
  307.         current->flags=(sample.loopbeg<sample.loopend)?SF_LOOP:0;
  308.         current->volume=64;
  309.  
  310.         current++;
  311.     }
  312.  
  313.     if(!S69_LoadPatterns()) return 0;
  314.  
  315.     return 1;
  316. }
  317.  
  318. CHAR *S69_LoadTitle(void)
  319. {
  320.     CHAR s[36];
  321.  
  322.     _mm_fseek(modfp,2,SEEK_SET);
  323.     if(!fread(s,36,1,modfp)) return NULL;
  324.  
  325.     return(DupStr(s,36));
  326. }
  327.  
  328. /*========== Loader information */
  329.  
  330. MLOADER load_669={
  331.     NULL,
  332.     "669",
  333.     "669 loader v1.0",
  334.     S69_Init,
  335.     S69_Test,
  336.     S69_Load,
  337.     S69_Cleanup,
  338.     S69_LoadTitle
  339. };
  340.