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

  1. /*
  2.  
  3. Name:
  4. LOAD_ULT.C
  5.  
  6. Description:
  7. Ultratracker (ULT) 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. #define ULTS_16BITS     4
  20. #define ULTS_LOOP       8
  21. #define ULTS_REVERSE    16
  22.  
  23.  
  24. /* Raw ULT header struct: */
  25.  
  26. typedef struct ULTHEADER{
  27.     char  id[15];
  28.     char  songtitle[32];
  29.     UBYTE reserved;
  30. } ULTHEADER;
  31.  
  32.  
  33. /* Raw ULT sampleinfo struct: */
  34.  
  35. typedef struct ULTSAMPLE{
  36.     char  samplename[32];
  37.     char  dosname[12];
  38.     SLONG  loopstart;
  39.     SLONG  loopend;
  40.     SLONG  sizestart;
  41.     SLONG  sizeend;
  42.     UBYTE volume;
  43.     UBYTE flags;
  44.     SWORD  finetune;
  45. } ULTSAMPLE;
  46.  
  47.  
  48. typedef struct ULTEVENT{
  49.     UBYTE note,sample,eff,dat1,dat2;
  50. } ULTEVENT;
  51.  
  52.  
  53. char *ULT_Version[]={
  54.     "Ultra Tracker V1.3",
  55.     "Ultra Tracker V1.4",
  56.     "Ultra Tracker V1.5",
  57.     "Ultra Tracker V1.6"
  58. };
  59.  
  60.  
  61. BOOL ULT_Test(void)
  62. {
  63.     char id[15];
  64.  
  65.     if(!fread(&id,15,1,modfp)) return 0;
  66.     return(!strncmp(id,"MAS_UTrack_V00",14));
  67. }
  68.  
  69.  
  70. BOOL ULT_Init(void)
  71. {
  72.     return 1;
  73. }
  74.  
  75.  
  76. void ULT_Cleanup(void)
  77. {
  78. }
  79.  
  80. ULTEVENT ev;
  81.  
  82.  
  83.  
  84. int ReadUltEvent(ULTEVENT *event)
  85. {
  86.     UBYTE flag,rep=1;
  87.  
  88.     flag=_mm_read_UBYTE(modfp);
  89.  
  90.     if(flag==0xfc){
  91.         fread(&rep,1,1,modfp);
  92.         event->note    =_mm_read_UBYTE(modfp);
  93.     }
  94.     else{
  95.         event->note=flag;
  96.     }
  97.  
  98.     event->sample    =_mm_read_UBYTE(modfp);
  99.     event->eff        =_mm_read_UBYTE(modfp);
  100.     event->dat1        =_mm_read_UBYTE(modfp);
  101.     event->dat2        =_mm_read_UBYTE(modfp);
  102.  
  103.     return rep;
  104. }
  105.  
  106.  
  107.  
  108.  
  109. BOOL ULT_Load(void)
  110. {
  111.     int t,u,tracks=0;
  112.     INSTRUMENT *d;
  113.     SAMPLE *q;
  114.     ULTSAMPLE s;
  115.     ULTHEADER mh;
  116.     UBYTE nos,noc,nop;
  117.  
  118.     /* try to read module header */
  119.  
  120.     _mm_read_str(mh.id,15,modfp);
  121.     _mm_read_str(mh.songtitle,32,modfp);
  122.     mh.reserved=_mm_read_UBYTE(modfp);
  123.  
  124.     if(feof(modfp)){
  125.         myerr=ERROR_LOADING_HEADER;
  126.         return 0;
  127.     }
  128.  
  129.     if(mh.id[14]<'1' || mh.id[14]>'4'){
  130.         printf("This version is not yet supported\n");
  131.         return 0;
  132.     }
  133.  
  134.     of.modtype=strdup(ULT_Version[mh.id[14]-'1']);
  135.     of.initspeed=6;
  136.     of.inittempo=125;
  137.  
  138.     /* read songtext */
  139.  
  140.     if(!ReadComment((UWORD)mh.reserved*32)) return 0;
  141.  
  142.     nos=_mm_read_UBYTE(modfp);
  143.  
  144.     if(feof(modfp)){
  145.         myerr=ERROR_LOADING_HEADER;
  146.         return 0;
  147.     }
  148.  
  149.     of.songname=DupStr(mh.songtitle,32);
  150.     of.numins=nos;
  151.  
  152.     if(!AllocInstruments()) return 0;
  153.  
  154.     d=of.instruments;
  155.  
  156.     for(t=0;t<nos;t++){
  157.  
  158.         d->numsmp=1;
  159.         if(!AllocSamples(d)) return 0;
  160.         q=d->samples;
  161.  
  162.         /* try to read sample info */
  163.  
  164.         _mm_read_str(s.samplename,32,modfp);
  165.         _mm_read_str(s.dosname,12,modfp);
  166.         s.loopstart    =_mm_read_I_ULONG(modfp);
  167.         s.loopend    =_mm_read_I_ULONG(modfp);
  168.         s.sizestart    =_mm_read_I_ULONG(modfp);
  169.         s.sizeend    =_mm_read_I_ULONG(modfp);
  170.         s.volume    =_mm_read_UBYTE(modfp);
  171.         s.flags        =_mm_read_UBYTE(modfp);
  172.         s.finetune    =_mm_read_I_SWORD(modfp);
  173.  
  174.         if(feof(modfp)){
  175.             myerr=ERROR_LOADING_SAMPLEINFO;
  176.             return 0;
  177.         }
  178.  
  179.         d->insname=DupStr(s.samplename,32);
  180.  
  181.         q->seekpos=0;
  182.  
  183.         q->c2spd=8363;
  184.  
  185.         if(mh.id[14]>='4'){
  186.             _mm_read_I_UWORD(modfp);    /* read 1.6 extra info(??) word */
  187.             q->c2spd=s.finetune;
  188.         }
  189.  
  190.         q->length=s.sizeend-s.sizestart;
  191.         q->volume=s.volume>>2;
  192.         q->loopstart=s.loopstart;
  193.         q->loopend=s.loopend;
  194.  
  195.         q->flags=SF_SIGNED;
  196.  
  197.         if(s.flags&ULTS_LOOP){
  198.             q->flags|=SF_LOOP;
  199.         }
  200.  
  201.         if(s.flags&ULTS_16BITS){
  202.             q->flags|=SF_16BITS;
  203.             q->loopstart>>=1;
  204.             q->loopend>>=1;
  205.         }
  206.  
  207. /*      printf("Sample %d %s length %ld\n",t,d->samplename,d->length); */
  208.         d++;
  209.     }
  210.  
  211.     _mm_read_UBYTES(of.positions,256,modfp);
  212.  
  213.     for(t=0;t<256;t++){
  214.         if(of.positions[t]==255) break;
  215.     }
  216.     of.numpos=t;
  217.  
  218.     noc=_mm_read_UBYTE(modfp);
  219.     nop=_mm_read_UBYTE(modfp);
  220.  
  221.     of.numchn=noc+1;
  222.     of.numpat=nop+1;
  223.     of.numtrk=of.numchn*of.numpat;
  224.  
  225.     if(!AllocTracks()) return 0;
  226.     if(!AllocPatterns()) return 0;
  227.  
  228.     for(u=0;u<of.numchn;u++){
  229.         for(t=0;t<of.numpat;t++){
  230.             of.patterns[(t*of.numchn)+u]=tracks++;
  231.         }
  232.     }
  233.  
  234.     /* read pan position table for v1.5 and higher */
  235.  
  236.     if(mh.id[14]>='3'){
  237.         for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
  238.     }
  239.  
  240.  
  241.     for(t=0;t<of.numtrk;t++){
  242.         int rep,s,done;
  243.  
  244.         UniReset();
  245.         done=0;
  246.  
  247.         while(done<64){
  248.  
  249.             rep=ReadUltEvent(&ev);
  250.  
  251.             if(feof(modfp)){
  252.                 myerr=ERROR_LOADING_TRACK;
  253.                 return 0;
  254.             }
  255.  
  256. /*                      printf("rep %d: n %d i %d e %x d1 %d d2 %d \n",rep,ev.note,ev.sample,ev.eff,ev.dat1,ev.dat2); */
  257.  
  258.  
  259.             for(s=0;s<rep;s++){
  260.                 UBYTE eff;
  261.  
  262.  
  263.                 if(ev.sample){
  264.                     UniInstrument(ev.sample-1);
  265.                 }
  266.  
  267.                 if(ev.note){
  268.                     UniNote(ev.note+23);
  269.                 }
  270.  
  271.                 eff=ev.eff>>4;
  272.  
  273.  
  274.                 /*
  275.                     ULT panning effect fixed by Alexander Kerkhove :
  276.                 */
  277.  
  278.  
  279.                 if(eff==0xc) UniPTEffect(eff,ev.dat2>>2);
  280.                 else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf);
  281.                 else UniPTEffect(eff,ev.dat2);
  282.  
  283.                 eff=ev.eff&0xf;
  284.  
  285.                 if(eff==0xc) UniPTEffect(eff,ev.dat1>>2);
  286.                 else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf);
  287.                 else UniPTEffect(eff,ev.dat1);
  288.  
  289.                 UniNewline();
  290.                 done++;
  291.             }
  292.         }
  293. /*              printf("----------------"); */
  294.  
  295.         if(!(of.tracks[t]=UniDup())) return 0;
  296.     }
  297.  
  298. /*      printf("%d channels %d patterns\n",of.numchn,of.numpat); */
  299. /*      printf("Song %32.32s: There's %d samples\n",mh.songtitle,nos); */
  300.     return 1;
  301. }
  302.  
  303.  
  304.  
  305. LOADER load_ult={
  306.     NULL,
  307.     "ULT",
  308.     "Portable ULT loader v0.1",
  309.     ULT_Init,
  310.     ULT_Test,
  311.     ULT_Load,
  312.     ULT_Cleanup
  313. };
  314.