home *** CD-ROM | disk | FTP | other *** search
/ The Games Machine 25 / GNOME_DEMO.iso / amiga / music / mikmod.lzx / mikmod / load_s3m.c < prev    next >
C/C++ Source or Header  |  2000-01-05  |  11KB  |  571 lines

  1. /*
  2.  
  3. Name:
  4. LOAD_S3M.C
  5.  
  6. Description:
  7. Screamtracker (S3M) module loader
  8.  
  9. Portability:
  10. All systems - all compilers (hopefully)
  11.  
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include "mikmod.h"
  18.  
  19. /**************************************************************************
  20. **************************************************************************/
  21.  
  22. typedef struct S3MNOTE{
  23.     UBYTE note,ins,vol,cmd,inf;
  24. } S3MNOTE;
  25.  
  26. typedef S3MNOTE S3MTRACK[64];
  27.  
  28.  
  29. /* Raw S3M header struct: */
  30.  
  31. typedef struct S3MHEADER{
  32.     char  songname[28];
  33.     char  t1a;
  34.     char  type;
  35.     char  unused1[2];
  36.     UWORD ordnum;
  37.     UWORD insnum;
  38.     UWORD patnum;
  39.     UWORD flags;
  40.     UWORD tracker;
  41.     UWORD fileformat;
  42.     char  scrm[4];
  43.     UBYTE mastervol;
  44.     UBYTE initspeed;
  45.     UBYTE inittempo;
  46.     UBYTE mastermult;
  47.     UBYTE ultraclick;
  48.     UBYTE pantable;
  49.     char  unused2[8];
  50.     UWORD special;
  51.     UBYTE channels[32];
  52. } S3MHEADER;
  53.  
  54.  
  55. /* Raw S3M sampleinfo struct: */
  56.  
  57. typedef struct S3MSAMPLE{
  58.     UBYTE type;
  59.     char  filename[12];
  60.     UBYTE memsegh;
  61.     UWORD memsegl;
  62.     ULONG length;
  63.     ULONG loopbeg;
  64.     ULONG loopend;
  65.     UBYTE volume;
  66.     UBYTE dsk;
  67.     UBYTE pack;
  68.     UBYTE flags;
  69.     ULONG c2spd;
  70.     char  unused[12];
  71.     char  sampname[28];
  72.     char  scrs[4];
  73. } S3MSAMPLE;
  74.  
  75.  
  76. /**************************************************************************
  77. **************************************************************************/
  78.  
  79.  
  80.  
  81. S3MNOTE *s3mbuf;        /* pointer to a complete S3M pattern */
  82. UWORD *paraptr;         /* parapointer array (see S3M docs) */
  83. static S3MHEADER *mh;
  84. UBYTE remap[32];
  85.  
  86.  
  87. char S3M_Version[]="Screamtracker 3.xx";
  88.  
  89.  
  90.  
  91. BOOL S3M_Test(void)
  92. {
  93.     char id[4];
  94.     _mm_fseek(modfp,0x2c,SEEK_SET);
  95.     if(!fread(id,4,1,modfp)) return 0;
  96.     if(!memcmp(id,"SCRM",4)) return 1;
  97.     return 0;
  98. }
  99.  
  100. BOOL S3M_Init(void)
  101. {
  102.     s3mbuf=NULL;
  103.     paraptr=NULL;
  104.  
  105.     if(!(s3mbuf=MyMalloc(16*64*sizeof(S3MNOTE)))) return 0;
  106.     if(!(mh=MyCalloc(1,sizeof(S3MHEADER)))) return 0;
  107.  
  108.     return 1;
  109. }
  110.  
  111. void S3M_Cleanup(void)
  112. {
  113.     if(s3mbuf!=NULL) free(s3mbuf);
  114.     if(paraptr!=NULL) free(paraptr);
  115.     if(mh!=NULL) free(mh);
  116. }
  117.  
  118.  
  119.  
  120.  
  121. BOOL S3M_ReadPattern(void)
  122. {
  123.     int row=0,flag,ch;
  124.     S3MNOTE *n;
  125.     S3MNOTE dummy;
  126.  
  127.     /* clear pattern data */
  128.  
  129.     memset(s3mbuf,255,16*64*sizeof(S3MNOTE));
  130.  
  131.     while(row<64){
  132.  
  133.         flag=fgetc(modfp);
  134.  
  135.         if(flag==EOF){
  136.             myerr="Error loading pattern";
  137.             return 0;
  138.         }
  139.  
  140.         if(flag){
  141.  
  142.             ch=flag&31;
  143.  
  144.             if(mh->channels[ch]<16){
  145.                 n=&s3mbuf[(64U*remap[ch])+row];
  146.             }
  147.             else{
  148.                 n=&dummy;
  149.             }
  150.  
  151.             if(flag&32){
  152.                 n->note=fgetc(modfp);
  153.                 n->ins=fgetc(modfp);
  154.             }
  155.  
  156.             if(flag&64){
  157.                 n->vol=fgetc(modfp);
  158.             }
  159.  
  160.             if(flag&128){
  161.                 n->cmd=fgetc(modfp);
  162.                 n->inf=fgetc(modfp);
  163.             }
  164.         }
  165.         else row++;
  166.     }
  167.     return 1;
  168. }
  169.  
  170.  
  171.  
  172. UBYTE *S3M_ConvertTrack(S3MNOTE *tr)
  173. {
  174.     int t;
  175.  
  176.     UBYTE note,ins,vol,cmd,inf,lo,hi;
  177.  
  178.     UniReset();
  179.     for(t=0;t<64;t++){
  180.  
  181.         note=tr[t].note;
  182.         ins=tr[t].ins;
  183.         vol=tr[t].vol;
  184.         cmd=tr[t].cmd;
  185.         inf=tr[t].inf;
  186.         lo=inf&0xf;
  187.         hi=inf>>4;
  188.  
  189.  
  190.         if(ins!=0 && ins!=255){
  191.             UniInstrument(ins-1);
  192.         }
  193.  
  194.         if(note!=255){
  195.             if(note==254) UniPTEffect(0xc,0);                       /* <- note off command */
  196.             else UniNote(((note>>4)*12)+(note&0xf));        /* <- normal note */
  197.         }
  198.  
  199.         if(vol<255){
  200.             UniPTEffect(0xc,vol);
  201. /*            UniWrite(UNI_S3MVOLUME); */
  202. /*            UniWrite(vol); */
  203.         }
  204.  
  205.         if(cmd!=255){
  206.             switch(cmd){
  207.  
  208.                 case 1:                 /* Axx set speed to xx */
  209.                     UniWrite(UNI_S3MEFFECTA);
  210.                     UniWrite(inf);
  211.                     break;
  212.  
  213.                 case 2:                 /* Bxx position jump */
  214.                     UniPTEffect(0xb,inf);
  215.                     break;
  216.  
  217.                 case 3:                 /* Cxx patternbreak to row xx */
  218.                     UniPTEffect(0xd,inf);
  219.                     break;
  220.  
  221.                 case 4:                 /* Dxy volumeslide */
  222.                     UniWrite(UNI_S3MEFFECTD);
  223.                     UniWrite(inf);
  224.                     break;
  225.  
  226.                 case 5:                 /* Exy toneslide down */
  227.                     UniWrite(UNI_S3MEFFECTE);
  228.                     UniWrite(inf);
  229.                     break;
  230.  
  231.                 case 6:                 /* Fxy toneslide up */
  232.                     UniWrite(UNI_S3MEFFECTF);
  233.                     UniWrite(inf);
  234.                     break;
  235.  
  236.                 case 7:                 /* Gxx Tone portamento,speed xx */
  237.                     UniPTEffect(0x3,inf);
  238.                     break;
  239.  
  240.                 case 8:                 /* Hxy vibrato */
  241.                     UniPTEffect(0x4,inf);
  242.                     break;
  243.  
  244.                 case 9:                 /* Ixy tremor, ontime x, offtime y */
  245.                     UniWrite(UNI_S3MEFFECTI);
  246.                     UniWrite(inf);
  247.                     break;
  248.  
  249.                 case 0xa:               /* Jxy arpeggio */
  250.                     UniPTEffect(0x0,inf);
  251.                     break;
  252.  
  253.                 case 0xb:               /* Kxy Dual command H00 & Dxy */
  254.                     UniPTEffect(0x4,0);
  255.                     UniWrite(UNI_S3MEFFECTD);
  256.                     UniWrite(inf);
  257.                     break;
  258.  
  259.                 case 0xc:               /* Lxy Dual command G00 & Dxy */
  260.                     UniPTEffect(0x3,0);
  261.                     UniWrite(UNI_S3MEFFECTD);
  262.                     UniWrite(inf);
  263.                     break;
  264.  
  265.                 case 0xf:               /* Oxx set sampleoffset xx00h */
  266.                     UniPTEffect(0x9,inf);
  267.                     break;
  268.  
  269.                 case 0x11:              /* Qxy Retrig (+volumeslide) */
  270.                     UniWrite(UNI_S3MEFFECTQ);
  271.                     UniWrite(inf);
  272.                     break;
  273.  
  274.                 case 0x12:              /* Rxy tremolo speed x, depth y */
  275.                     UniPTEffect(0x6,inf);
  276.                     break;
  277.  
  278.                 case 0x13:              /* Sxx special commands */
  279.                     switch(hi){
  280.  
  281.                         case 0: /* S0x set filter */
  282.                             UniPTEffect(0xe,0x00|lo);
  283.                             break;
  284.  
  285.                         case 1: /* S1x set glissando control */
  286.                             UniPTEffect(0xe,0x30|lo);
  287.                             break;
  288.  
  289.                         case 2: /* S2x set finetune */
  290.                             UniPTEffect(0xe,0x50|lo);
  291.                             break;
  292.  
  293.                         case 3: /* S3x set vibrato waveform */
  294.                             UniPTEffect(0xe,0x40|lo);
  295.                             break;
  296.  
  297.                         case 4: /* S4x set tremolo waveform */
  298.                             UniPTEffect(0xe,0x70|lo);
  299.                             break;
  300.  
  301.                         case 8: /* S8x set panning position */
  302.                             UniPTEffect(0xe,0x80|lo);
  303.                             break;
  304.  
  305.                         case 0xb:       /* SBx pattern loop */
  306.                             UniPTEffect(0xe,0x60|lo);
  307.                             break;
  308.  
  309.                         case 0xc:       /* SCx notecut */
  310.                             UniPTEffect(0xe,0xC0|lo);
  311.                             break;
  312.  
  313.                         case 0xd:       /* SDx notedelay */
  314.                             UniPTEffect(0xe,0xD0|lo);
  315.                             break;
  316.  
  317.                         case 0xe:       /* SDx patterndelay */
  318.                             UniPTEffect(0xe,0xE0|lo);
  319.                             break;
  320.                     }
  321.                     break;
  322.  
  323.                 case 0x14:      /* Txx tempo */
  324.                     if(inf>0x20){
  325.                         UniWrite(UNI_S3MEFFECTT);
  326.                         UniWrite(inf);
  327.                     }
  328.                     break;
  329.  
  330.                 case 0x18:      /* Xxx amiga command 8xx */
  331.                     UniPTEffect(0x8,inf);
  332.                     break;
  333.             }
  334.         }
  335.  
  336.         UniNewline();
  337.     }
  338.     return UniDup();
  339. }
  340.  
  341.  
  342.  
  343.  
  344. BOOL S3M_Load(void)
  345. {
  346.     int t,u,track=0;
  347.     INSTRUMENT *d;
  348.     SAMPLE *q;
  349.     UBYTE isused[16];
  350.     UBYTE pan[32];
  351.  
  352.     /* try to read module header */
  353.  
  354.     _mm_read_str(mh->songname,28,modfp);
  355.     mh->t1a            =_mm_read_UBYTE(modfp);
  356.     mh->type        =_mm_read_UBYTE(modfp);
  357.     _mm_read_UBYTES(mh->unused1,2,modfp);
  358.     mh->ordnum        =_mm_read_I_UWORD(modfp);
  359.     mh->insnum        =_mm_read_I_UWORD(modfp);
  360.     mh->patnum        =_mm_read_I_UWORD(modfp);
  361.     mh->flags        =_mm_read_I_UWORD(modfp);
  362.     mh->tracker        =_mm_read_I_UWORD(modfp);
  363.     mh->fileformat    =_mm_read_I_UWORD(modfp);
  364.     _mm_read_str(mh->scrm,4,modfp);
  365.  
  366.     mh->mastervol    =_mm_read_UBYTE(modfp);
  367.     mh->initspeed    =_mm_read_UBYTE(modfp);
  368.     mh->inittempo    =_mm_read_UBYTE(modfp);
  369.     mh->mastermult    =_mm_read_UBYTE(modfp);
  370.     mh->ultraclick    =_mm_read_UBYTE(modfp);
  371.     mh->pantable    =_mm_read_UBYTE(modfp);
  372.     _mm_read_UBYTES(mh->unused2,8,modfp);
  373.     mh->special        =_mm_read_I_UWORD(modfp);
  374.     _mm_read_UBYTES(mh->channels,32,modfp);
  375.  
  376.     if(feof(modfp)){
  377.         myerr="Error loading header";
  378.         return 0;
  379.     }
  380.  
  381.     /* set module variables */
  382.  
  383.     of.modtype=strdup(S3M_Version);
  384.     of.songname=DupStr(mh->songname,28);    /* make a cstr of songname */
  385.     of.numpat=mh->patnum;
  386.     of.numins=mh->insnum;
  387.     of.initspeed=mh->initspeed;
  388.     of.inittempo=mh->inittempo;
  389.  
  390.     /* count the number of channels used */
  391.  
  392.     of.numchn=0;
  393.  
  394.     for(t=0;t<32;t++) printf("%2.2x ",mh->channels[t]);
  395.  
  396.     for(t=0;t<32;t++) remap[t]=0;
  397.     for(t=0;t<16;t++) isused[t]=0;
  398.  
  399.     /* set a flag for each channel (1 out of of 16) thats being used: */
  400.  
  401.     for(t=0;t<32;t++){
  402.         if(mh->channels[t]<16){
  403.             isused[mh->channels[t]]=1;
  404.         }
  405.     }
  406.  
  407.     /* give each of them a different number */
  408.  
  409.     for(t=0;t<16;t++){
  410.         if(isused[t]){
  411.             isused[t]=of.numchn;
  412.             of.numchn++;
  413.         }
  414.     }
  415.  
  416.     /* build the remap array */
  417.  
  418.     for(t=0;t<32;t++){
  419.         if(mh->channels[t]<16){
  420.             remap[t]=isused[mh->channels[t]];
  421.         }
  422.     }
  423.  
  424.     /* set panning positions */
  425.  
  426.     for(t=0;t<32;t++){
  427.         if(mh->channels[t]<16){
  428.             if(mh->channels[t]<8){
  429.                 of.panning[remap[t]]=0x30;
  430.             }
  431.             else{
  432.                 of.panning[remap[t]]=0xc0;
  433.             }
  434.         }
  435.     }
  436.  
  437.     of.numtrk=of.numpat*of.numchn;
  438.  
  439.     printf("Uses %d channels\n",of.numchn);
  440.  
  441.     /* read the order data */
  442.  
  443.     _mm_read_UBYTES(of.positions,mh->ordnum,modfp);
  444.  
  445.     of.numpos=0;
  446.     for(t=0;t<mh->ordnum;t++){
  447.         of.positions[of.numpos]=of.positions[t];
  448.         if(of.positions[t]<254) of.numpos++;
  449.     }
  450.  
  451.     if((paraptr=MyMalloc((of.numins+of.numpat)*sizeof(UWORD)))==NULL) return 0;
  452.  
  453.     /* read the instrument+pattern parapointers */
  454.  
  455.     _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modfp);
  456.  
  457.     printf("pantab %d\n",mh->pantable);
  458.  
  459.     if(mh->pantable==252){
  460.  
  461.         /* read the panning table */
  462.  
  463.         _mm_read_UBYTES(pan,32,modfp);
  464.  
  465.         /* set panning positions according to panning table (new for st3.2) */
  466.  
  467.         for(t=0;t<32;t++){
  468.             if((pan[t]&0x20) && mh->channels[t]<16){
  469.                 of.panning[remap[t]]=(pan[t]&0xf)<<4;
  470.             }
  471.         }
  472.     }
  473.  
  474.     /* now is a good time to check if the header was too short :) */
  475.  
  476.     if(feof(modfp)){
  477.         myerr="Error loading header";
  478.         return 0;
  479.     }
  480.  
  481.     if(!AllocInstruments()) return 0;
  482.  
  483.     d=of.instruments;
  484.  
  485.     for(t=0;t<of.numins;t++){
  486.         S3MSAMPLE s;
  487.  
  488.         d->numsmp=1;
  489.         if(!AllocSamples(d)) return 0;
  490.         q=d->samples;
  491.  
  492.         /* seek to instrument position */
  493.  
  494.         _mm_fseek(modfp,((long)paraptr[t])<<4,SEEK_SET);
  495.  
  496.         /* and load sample info */
  497.  
  498.         s.type        =_mm_read_UBYTE(modfp);
  499.         _mm_read_str(s.filename,12,modfp);
  500.         s.memsegh    =_mm_read_UBYTE(modfp);
  501.         s.memsegl    =_mm_read_I_UWORD(modfp);
  502.         s.length    =_mm_read_I_ULONG(modfp);
  503.         s.loopbeg    =_mm_read_I_ULONG(modfp);
  504.         s.loopend    =_mm_read_I_ULONG(modfp);
  505.         s.volume    =_mm_read_UBYTE(modfp);
  506.         s.dsk         =_mm_read_UBYTE(modfp);
  507.         s.pack        =_mm_read_UBYTE(modfp);
  508.         s.flags        =_mm_read_UBYTE(modfp);
  509.         s.c2spd        =_mm_read_I_ULONG(modfp);
  510.         _mm_read_UBYTES(s.unused,12,modfp);
  511.         _mm_read_str(s.sampname,28,modfp);
  512.         _mm_read_str(s.scrs,4,modfp);
  513.  
  514.         if(feof(modfp)){
  515.             myerr=ERROR_LOADING_HEADER;
  516.             return 0;
  517.         }
  518.  
  519.         d->insname=DupStr(s.sampname,28);
  520.         q->c2spd=s.c2spd;
  521.         q->length=s.length;
  522.         q->loopstart=s.loopbeg;
  523.         q->loopend=s.loopend;
  524.         q->volume=s.volume;
  525.         q->seekpos=(((long)s.memsegh)<<16|s.memsegl)<<4;
  526.  
  527.         q->flags=0;
  528.  
  529.         if(s.flags&1) q->flags|=SF_LOOP;
  530.         if(s.flags&4) q->flags|=SF_16BITS;
  531.         if(mh->fileformat==1) q->flags|=SF_SIGNED;
  532.  
  533.         /* DON'T load sample if it doesn't have the SCRS tag */
  534.  
  535.         if(memcmp(s.scrs,"SCRS",4)!=0) q->length=0;
  536.  
  537.                 printf("%s\n",d->insname);
  538.  
  539.         d++;
  540.     }
  541.  
  542.     if(!AllocTracks()) return 0;
  543.     if(!AllocPatterns()) return 0;
  544.  
  545.     for(t=0;t<of.numpat;t++){
  546.  
  547.         /* seek to pattern position ( + 2 skip pattern length ) */
  548.  
  549.         _mm_fseek(modfp,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  550.  
  551.         if(!S3M_ReadPattern()) return 0;
  552.  
  553.         for(u=0;u<of.numchn;u++){
  554.             if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  555.         }
  556.     }
  557.  
  558.     return 1;
  559. }
  560.  
  561.  
  562. LOADER load_s3m={
  563.     NULL,
  564.     "S3M",
  565.     "Portable S3M loader v0.2",
  566.     S3M_Init,
  567.     S3M_Test,
  568.     S3M_Load,
  569.     S3M_Cleanup
  570. };
  571.