home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / sharewar / mikm202 / source / loaders / modload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-18  |  7.4 KB  |  357 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[31];                         // 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.     UBYTE      magic2[4];                           // string "M.K." or "FLT4" or "FLT8"
  29. } MODULEHEADER;
  30.  
  31.  
  32. typedef struct MODTYPE{                         // struct to identify type of module
  33.     char    id[4];
  34.     UBYTE   channels;
  35.     char    *name;
  36. } MODTYPE;
  37.  
  38.  
  39. typedef struct MODNOTE{
  40.     UBYTE a,b,c,d;
  41. } MODNOTE;
  42.  
  43.  
  44. /*************************************************************************
  45. *************************************************************************/
  46.  
  47.  
  48. char protracker[]="Protracker";
  49. char startracker[]="Startracker";
  50. char fasttracker[]="Fasttracker";
  51. char ins15tracker[]="15-instrument";
  52. char oktalyzer[]="Oktalyzer";
  53. char taketracker[]="TakeTracker";
  54.  
  55.  
  56. MODTYPE modtypes[]={
  57.     "M.K.",4,protracker,    // protracker 4 channel
  58.     "M!K!",4,protracker,    // protracker 4 channel
  59.     "FLT4",4,startracker,   // startracker 4 channel
  60.     "4CHN",4,fasttracker,   // fasttracker 4 channel
  61.     "6CHN",6,fasttracker,   // fasttracker 6 channel
  62.     "8CHN",8,fasttracker,   // fasttracker 8 channel
  63.     "CD81",8,oktalyzer,     // atari oktalyzer 8 channel
  64.     "OKTA",8,oktalyzer,     // atari oktalyzer 8 channel
  65.     "16CN",16,taketracker,  // taketracker 16 channel
  66.     "32CN",32,taketracker,  // taketracker 32 channel
  67.     "    ",4,ins15tracker   // 15-instrument 4 channel
  68. };
  69.  
  70. static MODULEHEADER *mh;        // raw as-is module header
  71. static MODNOTE *patbuf;
  72.  
  73.  
  74. BOOL MOD_Test(void)
  75. {
  76.     int t;
  77.  
  78.     char id[4];
  79.  
  80.     fseek(modfp,sizeof(MODULEHEADER)-4,SEEK_SET);
  81.     if(!fread(id,4,1,modfp)) return 0;
  82.  
  83.     // find out which ID string
  84.  
  85.     for(t=0;t<10;t++){
  86.         if(!memcmp(id,modtypes[t].id,4)) return 1;
  87.     }
  88.  
  89.     return 0;
  90. }
  91.  
  92.  
  93. BOOL MOD_Init(void)
  94. {
  95.     patbuf=NULL;
  96.     if(!(mh=MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
  97.     return 1;
  98. }
  99.  
  100.  
  101. void MOD_Cleanup(void)
  102. {
  103.     if(mh!=NULL) free(mh);
  104.     if(patbuf!=NULL) free(patbuf);
  105. }
  106.  
  107.  
  108. /*
  109.  
  110. Old (amiga) noteinfo:
  111.  
  112.  _____byte 1_____   byte2_    _____byte 3_____   byte4_
  113. /                \ /      \  /                \ /      \
  114. 0000          0000-00000000  0000          0000-00000000
  115.  
  116. Upper four    12 bits for    Lower four    Effect command.
  117. bits of sam-  note period.   bits of sam-
  118. ple number.                  ple number.
  119.  
  120.  
  121. */
  122.  
  123.  
  124. UWORD npertab[60]={
  125.  
  126. // -> Tuning 0
  127.  
  128.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  129.     856,808,762,720,678,640,604,570,538,508,480,453,
  130.     428,404,381,360,339,320,302,285,269,254,240,226,
  131.     214,202,190,180,170,160,151,143,135,127,120,113,
  132.     107,101,95,90,85,80,75,71,67,63,60,56
  133. };
  134.  
  135.  
  136. void ConvertNote(MODNOTE *n)
  137. {
  138.     UBYTE instrument,effect,effdat,note;
  139.     UWORD period;
  140.  
  141.     /* extract the various information from the 4 bytes that
  142.        make up a single note */
  143.  
  144.     instrument=(n->a&0x10)|(n->c>>4);
  145.     period=(((UWORD)n->a&0xf)<<8)+n->b;
  146.     effect=n->c&0xf;
  147.     effdat=n->d;
  148.  
  149.     // Convert the period to a note number
  150.  
  151.     note=0;
  152.     if(period!=0){
  153.         for(note=0;note<60;note++){
  154.             if(period>=npertab[note]) break;
  155.         }
  156.         note++;
  157.         if(note==61) note=0;
  158.     }
  159.  
  160.     if(instrument!=0){
  161.         UniInstrument(instrument-1);
  162.     }
  163.  
  164.     if(note!=0){
  165.         UniNote(note+23);
  166.     }
  167.  
  168.     UniPTEffect(effect,effdat);
  169. }
  170.  
  171.  
  172.  
  173.  
  174. UWORD rword(UWORD p)
  175. /*
  176.     Motorola word -> intel word
  177. */
  178. {
  179.     return( ((p&0x00ff)<<8) | ((p&0xff00)>>8) );
  180. }
  181.  
  182.  
  183.  
  184. void cword(UWORD *p)
  185. {
  186.     *p=rword(*p);
  187. }
  188.  
  189.  
  190.  
  191. UBYTE *ConvertTrack(MODNOTE *n)
  192. {
  193.     int t;
  194.  
  195.     UniReset();
  196.     for(t=0;t<64;t++){
  197.         ConvertNote(n);
  198.         UniNewline();
  199.         n+=of.numchn;
  200.     }
  201.     return UniDup();
  202. }
  203.  
  204.  
  205.  
  206.  
  207. BOOL ML_LoadPatterns(void)
  208. /*
  209.     Loads all patterns of a modfile and converts them into the
  210.     3 byte format.
  211. */
  212. {
  213.     int t,s,tracks=0;
  214.  
  215.     if(!AllocPatterns()) return 0;
  216.     if(!AllocTracks()) return 0;
  217.  
  218.     /* Allocate temporary buffer for loading
  219.        and converting the patterns */
  220.  
  221.     if(!(patbuf=MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  222.  
  223.     for(t=0;t<of.numpat;t++){
  224.  
  225.         /* Load the pattern into the temp buffer
  226.            and convert it into the 3-byte format */
  227.  
  228.         if(fread(patbuf,64U*of.numchn*sizeof(MODNOTE),1,modfp)!=1){
  229.             myerr=ERROR_LOADING_PATTERN;
  230.             return 0;
  231.         }
  232.  
  233.         for(s=0;s<of.numchn;s++){
  234.             if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  235.         }
  236.     }
  237.  
  238.     return 1;
  239. }
  240.  
  241.  
  242. BOOL MOD_Load(void)
  243. {
  244.     int t,modtype=0;
  245.     INSTRUMENT *d;          // new sampleinfo structure
  246.     SAMPLE *q;
  247.     MSAMPINFO *s;           // old module sampleinfo
  248.  
  249.     rewind(modfp);
  250.  
  251.     // try to read module header
  252.  
  253.     if(!fread(mh,sizeof(MODULEHEADER),1,modfp)){
  254.         myerr=ERROR_LOADING_HEADER;
  255.         return 0;
  256.     }
  257.  
  258.     // find out which ID string
  259.  
  260.     for(modtype=0;modtype<10;modtype++){
  261.         if(!memcmp(mh->magic2,modtypes[modtype].id,4)) break;
  262.     }
  263.  
  264.     if(modtype==10){
  265.  
  266.         // unknown modtype
  267.         myerr=ERROR_NOT_A_MODULE;
  268.         return 0;
  269.     }
  270.  
  271.     // sample info to intel format
  272.  
  273.     for(t=0;t<31;t++){
  274.         cword(&mh->samples[t].length);
  275.         cword(&mh->samples[t].reppos);
  276.         cword(&mh->samples[t].replen);
  277.     }
  278.  
  279.     /* set module variables */
  280.  
  281.     of.initspeed=6;
  282.     of.inittempo=125;
  283.     of.numchn=modtypes[modtype].channels;      // get number of channels
  284.     of.modtype=strdup(modtypes[modtype].name);      // get ascii type of mod
  285.     of.songname=DupStr(mh->songname,20);            // make a cstr of songname
  286.     of.numpos=mh->songlength;               // copy the songlength
  287.     memcpy(of.positions,mh->positions,128);         // copy the position array
  288.  
  289.     /* Count the number of patterns */
  290.  
  291.     of.numpat=0;
  292.  
  293.     for(t=0;t<128;t++){             // <-- BUGFIX... have to check ALL positions
  294.         if(of.positions[t] > of.numpat){
  295.             of.numpat=of.positions[t];
  296.         }
  297.     }
  298.     of.numpat++;
  299.     of.numtrk=of.numpat*of.numchn;
  300.  
  301.     // Finally, init the sampleinfo structures
  302.  
  303.     of.numins=31;
  304.  
  305.     if(!AllocInstruments()) return 0;
  306.  
  307.     s=mh->samples;   // init source pointer
  308.     d=of.instruments;  // init dest pointer
  309.  
  310.     for(t=0;t<of.numins;t++){
  311.  
  312.         d->numsmp=1;
  313.         if(!AllocSamples(d)) return 0;
  314.  
  315.         q=d->samples;
  316.  
  317.         // convert the samplename
  318.  
  319.         d->insname=DupStr(s->samplename,22);
  320.  
  321.         /* init the sampleinfo variables and
  322.            convert the size pointers to longword format */
  323.  
  324.         q->c2spd=finetune[s->finetune&0xf];
  325.         q->volume=s->volume;
  326.         q->loopstart=s->reppos<<1;
  327.         q->loopend=q->loopstart+(s->replen<<1);
  328.         q->length=s->length<<1;
  329.         q->seekpos=0;
  330.  
  331.         q->flags=SF_SIGNED;
  332.         if(s->replen>1) q->flags|=SF_LOOP;
  333.  
  334.         /* fix replen if repend>length */
  335.  
  336.         if(q->loopend>q->length) q->loopend=q->length;
  337.  
  338.         s++;    // point to next source sampleinfo
  339.         d++;    // point to next destiny sampleinfo
  340.     }
  341.  
  342.     if(!ML_LoadPatterns()) return 0;
  343.     return 1;
  344. }
  345.  
  346.  
  347.  
  348. LOADER modload={
  349.     NULL,
  350.     "Standard module",
  351.     "MOD loader v0.11",
  352.     MOD_Init,
  353.     MOD_Test,
  354.     MOD_Load,
  355.     MOD_Cleanup
  356. };
  357.