home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / sharewar / mikm202 / source / loaders / xmload.c < prev   
Encoding:
C/C++ Source or Header  |  1995-09-18  |  13.0 KB  |  542 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <malloc.h>
  6. #include "mloader.h"
  7. #include "munitrk.h"
  8.  
  9. /**************************************************************************
  10. **************************************************************************/
  11.  
  12.  
  13. typedef struct XMHEADER{
  14.     char  id[17];                   // ID text: 'Extended module: '
  15.     char  songname[21];             // Module name, padded with zeroes and 0x1a at the end
  16.     char  trackername[20];  // Tracker name
  17.     UWORD version;                  // (word) Version number, hi-byte major and low-byte minor
  18.     ULONG headersize;               // Header size
  19.     UWORD songlength;               // (word) Song length (in patten order table)
  20.     UWORD restart;                  // (word) Restart position
  21.     UWORD numchn;                   // (word) Number of channels (2,4,6,8,10,...,32)
  22.     UWORD numpat;                   // (word) Number of patterns (max 256)
  23.     UWORD numins;                   // (word) Number of instruments (max 128)
  24.     UWORD flags;                    // (word) Flags: bit 0: 0 = Amiga frequency table (see below) 1 = Linear frequency table
  25.     UWORD tempo;                    // (word) Default tempo
  26.     UWORD bpm;                              // (word) Default BPM
  27.     UBYTE orders[256];              // (byte) Pattern order table
  28. } XMHEADER;
  29.  
  30.  
  31. typedef struct XMINSTHEADER{
  32.     ULONG size;                             // (dword) Instrument size
  33.     char  name[22];                 // (char) Instrument name
  34.     UBYTE type;                             // (byte) Instrument type (always 0)
  35.     UWORD numsmp;                   // (word) Number of samples in instrument
  36.     ULONG ssize;                    //
  37. } XMINSTHEADER;
  38.  
  39.  
  40. typedef struct XMPATCHHEADER{
  41.     UBYTE what[96];         // (byte) Sample number for all notes
  42.     UBYTE volenv[48];       // (byte) Points for volume envelope
  43.     UBYTE panenv[48];       // (byte) Points for panning envelope
  44.     UBYTE volpts;           // (byte) Number of volume points
  45.     UBYTE panpts;           // (byte) Number of panning points
  46.     UBYTE volsus;           // (byte) Volume sustain point
  47.     UBYTE volbeg;           // (byte) Volume loop start point
  48.     UBYTE volend;           // (byte) Volume loop end point
  49.     UBYTE pansus;           // (byte) Panning sustain point
  50.     UBYTE panbeg;           // (byte) Panning loop start point
  51.     UBYTE panend;           // (byte) Panning loop end point
  52.     UBYTE volflg;           // (byte) Volume type: bit 0: On; 1: Sustain; 2: Loop
  53.     UBYTE panflg;           // (byte) Panning type: bit 0: On; 1: Sustain; 2: Loop
  54.     UBYTE vibflg;           // (byte) Vibrato type
  55.     UBYTE vibsweep;         // (byte) Vibrato sweep
  56.     UBYTE vibdepth;         // (byte) Vibrato depth
  57.     UBYTE vibrate;          // (byte) Vibrato rate
  58.     UWORD volfade;          // (word) Volume fadeout
  59.     UWORD reserved[11];     // (word) Reserved
  60. } XMPATCHHEADER;
  61.  
  62.  
  63. typedef struct XMWAVHEADER{
  64.     ULONG length;           // (dword) Sample length
  65.     ULONG loopstart;        // (dword) Sample loop start
  66.     ULONG looplength;       // (dword) Sample loop length
  67.     UBYTE volume;           // (byte) Volume
  68.     BYTE finetune;          // (byte) Finetune (signed byte -128..+127)
  69.     UBYTE type;                     // (byte) Type: Bit 0-1: 0 = No loop, 1 = Forward loop,
  70. //                                        2 = Ping-pong loop;
  71. //                                        4: 16-bit sampledata
  72.     UBYTE panning;          // (byte) Panning (0-255)
  73.     BYTE  relnote;          // (byte) Relative note number (signed byte)
  74.     UBYTE reserved;         // (byte) Reserved
  75.     char  samplename[22];   // (char) Sample name
  76. } XMWAVHEADER;
  77.  
  78.  
  79. typedef struct XMPATHEADER{
  80.     ULONG size;                             // (dword) Pattern header length
  81.     UBYTE packing;                  // (byte) Packing type (always 0)
  82.     UWORD numrows;                  // (word) Number of rows in pattern (1..256)
  83.     UWORD packsize;                 // (word) Packed patterndata size
  84. } XMPATHEADER;
  85.  
  86. typedef struct MTMNOTE{
  87.     UBYTE a,b,c;
  88. } MTMNOTE;
  89.  
  90.  
  91. typedef struct XMNOTE{
  92.     UBYTE note,ins,vol,eff,dat;
  93. }XMNOTE;
  94.  
  95. XMNOTE *xmpat;
  96.  
  97. /**************************************************************************
  98. **************************************************************************/
  99.  
  100.  
  101.  
  102. static XMHEADER *mh;
  103.  
  104. char XM_Version[]="XM";
  105.  
  106.  
  107.  
  108. BOOL XM_Test(void)
  109. {
  110.     char id[17];
  111.     rewind(modfp);
  112.     if(!fread(id,17,1,modfp)) return 0;
  113.     if(!memcmp(id,"Extended Module: ",17)) return 1;
  114.     return 0;
  115. }
  116.  
  117.  
  118. BOOL XM_Init(void)
  119. {
  120.     mh=NULL;
  121.     if(!(mh=MyCalloc(1,sizeof(XMHEADER)))) return 0;
  122.     return 1;
  123. }
  124.  
  125.  
  126. void XM_Cleanup(void)
  127. {
  128.     if(mh!=NULL) free(mh);
  129. }
  130.  
  131.  
  132. void XM_ReadNote(XMNOTE *n)
  133. {
  134.     UBYTE cmp;
  135.     memset(n,0,sizeof(XMNOTE));
  136.  
  137.     cmp=fgetc(modfp);
  138.  
  139.     if(cmp&0x80){
  140.         if(cmp&1) n->note=fgetc(modfp);
  141.         if(cmp&2) n->ins=fgetc(modfp);
  142.         if(cmp&4) n->vol=fgetc(modfp);
  143.         if(cmp&8) n->eff=fgetc(modfp);
  144.         if(cmp&16) n->dat=fgetc(modfp);
  145.     }
  146.     else{
  147.         n->note=cmp;
  148.         n->ins=fgetc(modfp);
  149.         n->vol=fgetc(modfp);
  150.         n->eff=fgetc(modfp);
  151.         n->dat=fgetc(modfp);
  152.     }
  153. }
  154.  
  155.  
  156. UBYTE *XM_Convert(XMNOTE *xmtrack,UWORD rows)
  157. {
  158.     int t;
  159.     UBYTE note,ins,vol,eff,dat;
  160.  
  161.     UniReset();
  162.  
  163.     for(t=0;t<rows;t++){
  164.  
  165.         note=xmtrack->note;
  166.         ins=xmtrack->ins;
  167.         vol=xmtrack->vol;
  168.         eff=xmtrack->eff;
  169.         dat=xmtrack->dat;
  170.  
  171.         if(note!=0){
  172.             UniNote(note-1);
  173.         }
  174.  
  175.         if(ins!=0){
  176.             UniInstrument(ins-1);
  177.         }
  178.  
  179. //              printf("Vol:%d\n",vol);
  180.  
  181.         switch(vol>>4){
  182.  
  183.             case 0x6:                    // volslide down
  184.                 if(vol&0xf){
  185.                     UniWrite(UNI_XMEFFECTA);
  186.                     UniWrite(vol&0xf);
  187.                 }
  188.                 break;
  189.  
  190.             case 0x7:                    // volslide up
  191.                 if(vol&0xf){
  192.                     UniWrite(UNI_XMEFFECTA);
  193.                     UniWrite(vol<<4);
  194.                 }
  195.                 break;
  196.  
  197.             /* volume-row fine volume slide is compatible with protracker
  198.                EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
  199.                opposed to 'take the last sliding value'.
  200.             */
  201.  
  202.             case 0x8:                        // finevol down
  203.                 UniPTEffect(0xe,0xb0 | (vol&0xf));
  204.                 break;
  205.  
  206.             case 0x9:                       // finevol up
  207.                 UniPTEffect(0xe,0xa0 | (vol&0xf));
  208.                 break;
  209.  
  210.             case 0xa:                       // set vibrato speed
  211.                 UniPTEffect(0x4,vol<<4);
  212.                 break;
  213.  
  214.             case 0xb:                       // vibrato
  215.                 UniPTEffect(0x4,vol&0xf);
  216.                 break;
  217.  
  218.             case 0xc:                       // set panning
  219.                 UniPTEffect(0x8,vol<<4);
  220.                 break;
  221.  
  222.             case 0xd:                       // panning slide left
  223.                 // only slide when data nibble not zero:
  224.  
  225.                 if(vol&0xf){
  226.                     UniWrite(UNI_XMEFFECTP);
  227.                     UniWrite(vol&0xf);
  228.                 }
  229.                 break;
  230.  
  231.             case 0xe:                       // panning slide right
  232.                 // only slide when data nibble not zero:
  233.  
  234.                 if(vol&0xf){
  235.                     UniWrite(UNI_XMEFFECTP);
  236.                     UniWrite(vol<<4);
  237.                 }
  238.                 break;
  239.  
  240.             case 0xf:                       // tone porta
  241.                 UniPTEffect(0x3,vol<<4);
  242.                 break;
  243.  
  244.             default:
  245.                 if(vol>=0x10 && vol<=0x50){
  246.                     UniPTEffect(0xc,vol-0x10);
  247.                 }
  248.         }
  249.  
  250. //              if(eff>0xf) printf("Effect %d",eff);
  251.  
  252.         switch(eff){
  253.  
  254.             case 'G'-55:                    // G - set global volume
  255.                 break;
  256.  
  257.             case 'H'-55:                    // H - global volume slide
  258.                 break;
  259.  
  260.             case 'K'-55:                    // K - keyoff
  261.                 UniNote(96);
  262.                 break;
  263.  
  264.             case 'L'-55:                    // L - set envelope position
  265.                 break;
  266.  
  267.             case 'P'-55:                    // P - panning slide
  268.                 UniWrite(UNI_XMEFFECTP);
  269.                 UniWrite(dat);
  270.                 break;
  271.  
  272.             case 'R'-55:                    // R - multi retrig note
  273.                 UniWrite(UNI_S3MEFFECTQ);
  274.                 UniWrite(dat);
  275.                 break;
  276.  
  277.             case 'T'-55:
  278.                 UniPTEffect(0x6,dat);
  279.                 break;
  280.  
  281.             case 'X'-55:
  282.                 if((dat>>4)==1){                // X1 extra fine porta up
  283.  
  284.  
  285.                 }
  286.                 else{                                   // X2 extra fine porta down
  287.  
  288.                 }
  289.                 break;
  290.  
  291.             default:
  292.                 if(eff==0xa){
  293.                     UniWrite(UNI_XMEFFECTA);
  294.                     UniWrite(dat);
  295.                 }
  296.                 else if(eff<=0xf) UniPTEffect(eff,dat);
  297.                 break;
  298.         }
  299.  
  300.         UniNewline();
  301.         xmtrack++;
  302.     }
  303.     return UniDup();
  304. }
  305.  
  306.  
  307.  
  308. BOOL XM_Load(void)
  309. {
  310.     INSTRUMENT *d;
  311.     SAMPLE *q;
  312.     int t,u,v,p,numtrk;
  313.     long next;
  314.  
  315.     rewind(modfp);
  316.  
  317.     // try to read module header
  318.  
  319.     if(!fread(mh,sizeof(XMHEADER),1,modfp)){
  320.         myerr=ERROR_LOADING_HEADER;
  321.         return 0;
  322.     }
  323.  
  324.     /* set module variables */
  325.  
  326.     of.initspeed=mh->tempo;
  327.     of.inittempo=mh->bpm;
  328.     of.modtype=DupStr(mh->trackername,20);
  329.     of.numchn=mh->numchn;
  330.     of.numpat=mh->numpat;
  331.     of.numtrk=(UWORD)of.numpat*of.numchn;   // get number of channels
  332.     of.songname=DupStr(mh->songname,20);    // make a cstr of songname
  333.     of.numpos=mh->songlength;                       // copy the songlength
  334.     of.numins=mh->numins;
  335.     of.flags|=UF_XMPERIODS;
  336.     if(mh->flags&1) of.flags|=UF_LINEAR;
  337.  
  338.     memcpy(of.positions,mh->orders,256);
  339.  
  340.     of.numpat=0;
  341.     for(t=0;t<of.numpos;t++){
  342.         if(of.positions[t]>of.numpat) of.numpat=of.positions[t];
  343.     }
  344.     of.numpat++;
  345.  
  346. /*    printf("Modtype :%s\n",of.modtype);
  347.     printf("Version :%x\n",mh->version);
  348.     printf("Song    :%s\n",of.songname);
  349.     printf("Speed   :%d,%d\n",of.initspeed,of.inittempo);
  350.     printf("Channels:%d\n",of.numchn);
  351.     printf("Numins  :%d\n",mh->numins);
  352. */
  353.     if(!AllocTracks()) return 0;
  354.     if(!AllocPatterns()) return 0;
  355.  
  356.     numtrk=0;
  357.     for(t=0;t<mh->numpat;t++){
  358.         XMPATHEADER ph;
  359.  
  360. //        printf("Reading pattern %d\n",t);
  361.  
  362.         fread(&ph,sizeof(XMPATHEADER),1,modfp);
  363.  
  364.  
  365. //        printf("headln:  %ld\n",ph.size);
  366. //        printf("numrows: %d\n",ph.numrows);
  367. //        printf("packsize:%d\n",ph.packsize);
  368.  
  369.         of.pattrows[t]=ph.numrows;
  370.  
  371.         /*
  372.             Gr8.. when packsize is 0, don't try to load a pattern.. it's empty.
  373.             This bug was discovered thanks to Khyron's module..
  374.         */
  375.  
  376.         if(!(xmpat=MyCalloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0;
  377.  
  378.         if(ph.packsize>0){
  379.             for(u=0;u<ph.numrows;u++){
  380.                 for(v=0;v<of.numchn;v++){
  381.                     XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  382.                 }
  383.             }
  384.         }
  385.  
  386.         for(v=0;v<of.numchn;v++){
  387.             of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  388.         }
  389.  
  390.         free(xmpat);
  391.     }
  392.  
  393.     if(!AllocInstruments()) return 0;
  394.  
  395.     d=of.instruments;
  396.  
  397.     for(t=0;t<of.numins;t++){
  398.         XMINSTHEADER ih;
  399.  
  400. //              printf("Reading instrument %d\n",t);
  401.  
  402.         fread(&ih,sizeof(XMINSTHEADER),1,modfp);
  403.  
  404. /*              printf("Size: %ld\n",ih.size);
  405.         printf("Name:     %22.22s\n",ih.name);
  406.         printf("Samples:%d\n",ih.numsmp);
  407.         printf("sampleheadersize:%ld\n",ih.ssize);
  408. */
  409.         d->insname=DupStr(ih.name,22);
  410.         d->numsmp=ih.numsmp;
  411.  
  412.         if(!AllocSamples(d)) return 0;
  413.  
  414.         if(ih.numsmp>0){
  415.             XMPATCHHEADER pth;
  416.             XMWAVHEADER wh;
  417.  
  418.             fread(&pth,sizeof(XMPATCHHEADER),1,modfp);
  419.  
  420.             memcpy(d->samplenumber,pth.what,96);
  421.  
  422.             d->volfade=pth.volfade;
  423.  
  424. //            printf("Volfade %x\n",d->volfade);
  425.  
  426.             memcpy(d->volenv,pth.volenv,48);
  427.             d->volflg=pth.volflg;
  428.             d->volsus=pth.volsus;
  429.             d->volbeg=pth.volbeg;
  430.             d->volend=pth.volend;
  431.             d->volpts=pth.volpts;
  432.  
  433. /*            printf("volume points    : %d\n"
  434.                    "volflg            : %d\n"
  435.                    "volbeg            : %d\n"
  436.                    "volend            : %d\n"
  437.                    "volsus            : %d\n",
  438.                    d->volpts,
  439.                    d->volflg,
  440.                    d->volbeg,
  441.                    d->volend,
  442.                    d->volsus);
  443. */
  444.             // scale volume envelope:
  445.  
  446.             for(p=0;p<d->volpts;p++){
  447.                 d->volenv[p].val<<=2;
  448. //                printf("%d,%d,",d->volenv[p].pos,d->volenv[p].val);
  449.             }
  450.  
  451.             memcpy(d->panenv,pth.panenv,48);
  452.             d->panflg=pth.panflg;
  453.             d->pansus=pth.pansus;
  454.             d->panbeg=pth.panbeg;
  455.             d->panend=pth.panend;
  456.             d->panpts=pth.panpts;
  457.  
  458. /*                      printf("Panning points    : %d\n"
  459.                    "panflg            : %d\n"
  460.                    "panbeg            : %d\n"
  461.                    "panend            : %d\n"
  462.                    "pansus            : %d\n",
  463.                    d->panpts,
  464.                    d->panflg,
  465.                    d->panbeg,
  466.                    d->panend,
  467.                    d->pansus);
  468. */
  469.             // scale panning envelope:
  470.  
  471.             for(p=0;p<d->panpts;p++){
  472.                 d->panenv[p].val<<=2;
  473. //                printf("%d,%d,",d->panenv[p].pos,d->panenv[p].val);
  474.             }
  475.  
  476. //                      for(u=0;u<256;u++){
  477. //                              printf("%2.2x ",fgetc(modfp));
  478. //                      }
  479.  
  480.             next=0;
  481.  
  482.             for(u=0;u<ih.numsmp;u++){
  483.                 q=&d->samples[u];
  484.  
  485.                 fread(&wh,sizeof(XMWAVHEADER),1,modfp);
  486. //                              printf("wav %d:%22.22s\n",u,wh.samplename);
  487.  
  488.                 q->samplename   =DupStr(wh.samplename,22);
  489.                 q->length       =wh.length;
  490.                 q->loopstart    =wh.loopstart;
  491.                 q->loopend      =wh.loopstart+wh.looplength;
  492.                 q->volume       =wh.volume;
  493.                 q->c2spd        =wh.finetune+128;
  494.                 q->transpose    =wh.relnote;
  495.                 q->panning      =wh.panning;
  496.                 q->seekpos        =next;
  497.  
  498.                 if(wh.type&0x10){
  499.                     q->length>>=1;
  500.                     q->loopstart>>=1;
  501.                     q->loopend>>=1;
  502.                 }
  503.  
  504.                 next+=wh.length;
  505.  
  506. //                              printf("Type %u\n",wh.type);
  507. //                printf("Trans %d\n",wh.relnote);
  508.  
  509.                 q->flags|=SF_OWNPAN;
  510.                 if(wh.type&0x3) q->flags|=SF_LOOP;
  511.                 if(wh.type&0x2) q->flags|=SF_BIDI;
  512.  
  513.                 if(wh.type&0x10) q->flags|=SF_16BITS;
  514.                 q->flags|=SF_DELTA;
  515.                 q->flags|=SF_SIGNED;
  516.             }
  517.  
  518.             for(u=0;u<ih.numsmp;u++) d->samples[u].seekpos+=ftell(modfp);
  519.  
  520.             fseek(modfp,next,SEEK_CUR);
  521.         }
  522.  
  523.         d++;
  524.     }
  525.  
  526.  
  527.     return 1;
  528. }
  529.  
  530.  
  531.  
  532. LOADER xmload={
  533.     NULL,
  534.     "XM",
  535.     "XM loader v0.3 - for your ears only / MikMak",
  536.     XM_Init,
  537.     XM_Test,
  538.     XM_Load,
  539.     XM_Cleanup
  540. };
  541.  
  542.