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