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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "mloader.h"
  6. #include "munitrk.h"
  7.  
  8. /*************************************************************************
  9. *************************************************************************/
  10.  
  11.  
  12. typedef struct MSAMPINFO{       // sample header as it appears in a module
  13.     UBYTE samplename[22];
  14.     UWORD length;
  15.     UBYTE finetune;
  16.     UBYTE volume;
  17.     UWORD reppos;
  18.     UWORD replen;
  19. } MSAMPINFO;
  20.  
  21.  
  22. typedef struct MODULEHEADER{                 // verbatim module header
  23.     UBYTE      songname[20];                // the songname..
  24.     MSAMPINFO  samples[15];                         // all sampleinfo
  25.     UBYTE      songlength;                          // number of patterns used
  26.     UBYTE      magic1;                                      // should be 127
  27.     UBYTE      positions[128];                      // which pattern to play at pos
  28. } MODULEHEADER;
  29.  
  30. typedef struct MODNOTE{
  31.     UBYTE a,b,c,d;
  32. } MODNOTE;
  33.  
  34.  
  35. #define rword(p) ((((p)<<8)&0xff00) | (((p)>>8)&0x00ff))
  36. #define cword(p) p=rword(p)
  37.  
  38. /*************************************************************************
  39. *************************************************************************/
  40.  
  41. static MODULEHEADER *mh;        // raw as-is module header
  42. static MODNOTE *patbuf;
  43.  
  44.  
  45. BOOL M15_Test(void)
  46. {
  47.     int t;
  48.     MODULEHEADER mh;
  49.  
  50.     fseek(modfp,0,SEEK_SET);
  51.     if(!fread(&mh,sizeof(MODULEHEADER),1,modfp)) return 0;
  52.  
  53.     for(t=0;t<15;t++){
  54.  
  55.         // all finetunes should be zero
  56.         if(mh.samples[t].finetune!=0) return 0;
  57.  
  58.         // all volumes should be <=64
  59.         if(mh.samples[t].volume>64) return 0;
  60.     }
  61.     if(mh.magic1>127) return 0;    // and magic1 should be <128
  62.  
  63.     return 1;
  64. }
  65.  
  66.  
  67. BOOL M15_Init(void)
  68. {
  69.     patbuf=NULL;
  70.     if(!(mh=(MODULEHEADER *)MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
  71.     return 1;
  72. }
  73.  
  74.  
  75. void M15_Cleanup(void)
  76. {
  77.     if(mh!=NULL) free(mh);
  78.     if(patbuf!=NULL) free(patbuf);
  79. }
  80.  
  81.  
  82. /*
  83.  
  84. Old (amiga) noteinfo:
  85.  
  86.  _____byte 1_____   byte2_    _____byte 3_____   byte4_
  87. /                \ /      \  /                \ /      \
  88. 0000          0000-00000000  0000          0000-00000000
  89.  
  90. Upper four    12 bits for    Lower four    Effect command.
  91. bits of sam-  note period.   bits of sam-
  92. ple number.                  ple number.
  93.  
  94.  
  95. */
  96.  
  97.  
  98. UWORD M15_npertab[60]={
  99.  
  100. // -> Tuning 0
  101.  
  102.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  103.     856,808,762,720,678,640,604,570,538,508,480,453,
  104.     428,404,381,360,339,320,302,285,269,254,240,226,
  105.     214,202,190,180,170,160,151,143,135,127,120,113,
  106.     107,101,95,90,85,80,75,71,67,63,60,56
  107. };
  108.  
  109.  
  110. void M15_ConvertNote(MODNOTE *n)
  111. {
  112.     UBYTE instrument,effect,effdat,note;
  113.     UWORD period;
  114.  
  115.     /* extract the various information from the 4 bytes that
  116.        make up a single note */
  117.  
  118.     instrument=(n->a&0x10)|(n->c>>4);
  119.     period=(((UWORD)n->a&0xf)<<8)+n->b;
  120.     effect=n->c&0xf;
  121.     effdat=n->d;
  122.  
  123.     // Convert the period to a note number
  124.  
  125.     note=0;
  126.     if(period!=0){
  127.         for(note=0;note<60;note++){
  128.             if(period>=M15_npertab[note]) break;
  129.         }
  130.         note++;
  131.         if(note==61) note=0;
  132.     }
  133.  
  134.     if(instrument!=0){
  135.         UniInstrument(instrument-1);
  136.     }
  137.  
  138.     if(note!=0){
  139.         UniNote(note+23);
  140.     }
  141.  
  142.     UniPTEffect(effect,effdat);
  143. }
  144.  
  145.  
  146.  
  147. UBYTE *M15_ConvertTrack(MODNOTE *n)
  148. {
  149.     int t;
  150.  
  151.     UniReset();
  152.     for(t=0;t<64;t++){
  153.         M15_ConvertNote(n);
  154.         UniNewline();
  155.         n+=of.numchn;
  156.     }
  157.     return UniDup();
  158. }
  159.  
  160.  
  161.  
  162. BOOL M15_LoadPatterns(void)
  163. /*
  164.     Loads all patterns of a modfile and converts them into the
  165.     3 byte format.
  166. */
  167. {
  168.     int t,s,tracks=0;
  169.  
  170.     if(!AllocPatterns()) return 0;
  171.     if(!AllocTracks()) return 0;
  172.  
  173.     /* Allocate temporary buffer for loading
  174.        and converting the patterns */
  175.  
  176.     if(!(patbuf=(MODNOTE *)MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  177.  
  178.     for(t=0;t<of.numpat;t++){
  179.  
  180.         /* Load the pattern into the temp buffer
  181.            and convert it into the 3-byte format */
  182.  
  183.         if(fread(patbuf,64U*of.numchn*sizeof(MODNOTE),1,modfp)!=1){
  184.             myerr=ERROR_LOADING_PATTERN;
  185.             return 0;
  186.         }
  187.  
  188.         for(s=0;s<of.numchn;s++){
  189.             if(!(of.tracks[tracks++]=M15_ConvertTrack(patbuf+s))) return 0;
  190.         }
  191.     }
  192.  
  193.     return 1;
  194. }
  195.  
  196.  
  197.  
  198. BOOL M15_Load(void)
  199. {
  200.     int t;
  201.     INSTRUMENT *d;          // new sampleinfo structure
  202.     SAMPLE *q;
  203.     MSAMPINFO *s;           // old module sampleinfo
  204.  
  205.     rewind(modfp);
  206.  
  207.     // try to read module header
  208.  
  209.     if(!fread(mh,sizeof(MODULEHEADER),1,modfp)){
  210.         myerr=ERROR_LOADING_HEADER;
  211.         return 0;
  212.     }
  213.  
  214.     // sample info to intel format
  215.  
  216.     for(t=0;t<15;t++){
  217.         cword(mh->samples[t].length);
  218.         cword(mh->samples[t].reppos);
  219.         cword(mh->samples[t].replen);
  220.     }
  221.  
  222.     /* set module variables */
  223.  
  224.     of.initspeed=6;
  225.     of.inittempo=125;
  226.     of.numchn=4;                                                    // get number of channels
  227.     of.modtype=strdup("15-instrument");             // get ascii type of mod
  228.     of.songname=DupStr(mh->songname,20);        // make a cstr of songname
  229.     of.numpos=mh->songlength;                       // copy the songlength
  230.     memcpy(of.positions,mh->positions,128);     // copy the position array
  231.  
  232.     /* Count the number of patterns */
  233.  
  234.     of.numpat=0;
  235.  
  236.     for(t=0;t<128;t++){             // <-- BUGFIX... have to check ALL positions
  237.         if(of.positions[t] > of.numpat){
  238.             of.numpat=of.positions[t];
  239.         }
  240.     }
  241.     of.numpat++;
  242.     of.numtrk=of.numpat*of.numchn;
  243.  
  244.     // Finally, init the sampleinfo structures
  245.  
  246.     of.numins=15;
  247.     if(!AllocInstruments()) return 0;
  248.  
  249.     s=mh->samples;          // init source pointer
  250.     d=of.instruments;       // init dest pointer
  251.  
  252.     for(t=0;t<of.numins;t++){
  253.  
  254.         d->numsmp=1;
  255.         if(!AllocSamples(d)) return 0;
  256.  
  257.         q=d->samples;
  258.  
  259.         // convert the samplename
  260.  
  261.         d->insname=DupStr(s->samplename,22);
  262.  
  263.         /* init the sampleinfo variables and
  264.            convert the size pointers to longword format */
  265.  
  266.         q->c2spd=finetune[s->finetune&0xf];
  267.         q->volume=s->volume;
  268.         q->loopstart=s->reppos;
  269.         q->loopend=q->loopstart+(s->replen<<1);
  270.         q->length=s->length<<1;
  271.         q->seekpos=0;
  272.  
  273.         q->flags=SF_SIGNED;
  274.         if(s->replen>1) q->flags|=SF_LOOP;
  275.  
  276.         /* fix replen if repend>length */
  277.  
  278.         if(q->loopend>q->length) q->loopend=q->length;
  279.  
  280.         s++;    // point to next source sampleinfo
  281.         d++;    // point to next destiny sampleinfo
  282.     }
  283.  
  284.     if(!M15_LoadPatterns()) return 0;
  285.     return 1;
  286. }
  287.  
  288.  
  289.  
  290. LOADER m15load={
  291.     NULL,
  292.     "15-instrument module",
  293.     "MOD-15 loader v0.1",
  294.     M15_Init,
  295.     M15_Test,
  296.     M15_Load,
  297.     M15_Cleanup
  298. };
  299.