home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / loaders / load_ult.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  7.0 KB  |  318 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This library is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU Library General Public License as
  6.     published by the Free Software Foundation; either version 2 of
  7.     the License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Library General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Library General Public
  15.     License along with this library; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: load_ult.c,v 1.17 1998/12/07 06:00:22 miod Exp $
  22.  
  23.   Ultratracker (ULT) module loader
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #include <string.h>
  32.  
  33. #include <mikmod_internals.h>
  34.  
  35. /*========== Module structure */
  36.  
  37. /* header */
  38. typedef struct ULTHEADER {
  39.     CHAR  id[16];
  40.     CHAR  songtitle[32];
  41.     UBYTE reserved;
  42. } ULTHEADER;
  43.  
  44. /* sample information */
  45. typedef struct ULTSAMPLE {
  46.     CHAR  samplename[32];
  47.     CHAR  dosname[12];
  48.     SLONG loopstart;
  49.     SLONG loopend;
  50.     SLONG sizestart;
  51.     SLONG sizeend;
  52.     UBYTE volume;
  53.     UBYTE flags;
  54.     UWORD speed;
  55.     SWORD finetune;
  56. } ULTSAMPLE;
  57.  
  58. typedef struct ULTEVENT {
  59.     UBYTE note,sample,eff,dat1,dat2;
  60. } ULTEVENT;
  61.  
  62. /*========== Loader variables */
  63.  
  64. #define ULTS_16BITS     4
  65. #define ULTS_LOOP       8
  66. #define ULTS_REVERSE    16
  67.  
  68. #define ULT_VERSION_LEN 18
  69. static    CHAR ULT_Version[ULT_VERSION_LEN]="Ultra Tracker v1.x";
  70.  
  71. static    ULTEVENT ev;
  72.  
  73. /*========== Loader code */
  74.  
  75. BOOL ULT_Test(void)
  76. {
  77.     CHAR id[16];
  78.  
  79.     if(!_mm_read_string(id,15,modfp)) return 0;
  80.     if(strncmp(id,"MAS_UTrack_V00",14)) return 0;
  81.     if((id[14]<'1')||(id[14]>'4')) return 0;
  82.     return 1;
  83. }
  84.  
  85. BOOL ULT_Init(void)
  86. {
  87.     return 1;
  88. }
  89.  
  90. void ULT_Cleanup(void)
  91. {
  92. }
  93.  
  94. UBYTE ReadUltEvent(ULTEVENT* event)
  95. {
  96.     UBYTE flag,rep=1;
  97.  
  98.     flag = _mm_read_UBYTE(modfp);
  99.     if(flag==0xfc) {
  100.         rep = _mm_read_UBYTE(modfp);
  101.         event->note =_mm_read_UBYTE(modfp);
  102.     } else
  103.         event->note = flag;
  104.  
  105.     event->sample   =_mm_read_UBYTE(modfp);
  106.     event->eff      =_mm_read_UBYTE(modfp);
  107.     event->dat1     =_mm_read_UBYTE(modfp);
  108.     event->dat2     =_mm_read_UBYTE(modfp);
  109.  
  110.     return rep;
  111. }
  112.  
  113. BOOL ULT_Load(BOOL curious)
  114. {
  115.     int t,u,tracks=0;
  116.     SAMPLE *q;
  117.     ULTSAMPLE s;
  118.     ULTHEADER mh;
  119.     UBYTE nos,noc,nop;
  120.  
  121.     /* try to read module header */
  122.     _mm_read_string(mh.id,15,modfp);
  123.     _mm_read_string(mh.songtitle,32,modfp);
  124.     mh.reserved=_mm_read_UBYTE(modfp);
  125.  
  126.     if(feof(modfp)) {
  127.         _mm_errno = MMERR_LOADING_HEADER;
  128.         return 0;
  129.     }
  130.  
  131.     ULT_Version[ULT_VERSION_LEN-1]='3'+(mh.id[14]-'1');
  132.     of.modtype   = DupStr(ULT_Version,ULT_VERSION_LEN);
  133.     of.initspeed = 6;
  134.     of.inittempo = 125;
  135.     of.reppos    = 0;
  136.  
  137.     /* read songtext */
  138.     if ((mh.id[14]>'1')&&(mh.reserved))
  139.         if(!ReadLinedComment(mh.reserved,32)) return 0;
  140.  
  141.     nos=_mm_read_UBYTE(modfp);
  142.     if(feof(modfp)) {
  143.         _mm_errno = MMERR_LOADING_HEADER;
  144.         return 0;
  145.     }
  146.  
  147.     of.songname=DupStr(mh.songtitle,32);
  148.     of.numins=of.numsmp=nos;
  149.  
  150.     if(!AllocSamples()) return 0;
  151.     q = of.samples;
  152.     for(t=0;t<nos;t++) {
  153.         /* try to read sample info */
  154.         _mm_read_string(s.samplename,32,modfp);
  155.         _mm_read_string(s.dosname,12,modfp);
  156.         s.loopstart     =_mm_read_I_ULONG(modfp);
  157.         s.loopend       =_mm_read_I_ULONG(modfp);
  158.         s.sizestart     =_mm_read_I_ULONG(modfp);
  159.         s.sizeend       =_mm_read_I_ULONG(modfp);
  160.         s.volume        =_mm_read_UBYTE(modfp);
  161.         s.flags         =_mm_read_UBYTE(modfp);
  162.         s.speed         =(mh.id[14]>='4')?_mm_read_I_UWORD(modfp):8363;
  163.         s.finetune      =_mm_read_I_SWORD(modfp);
  164.  
  165.         if(feof(modfp)) {
  166.             _mm_errno = MMERR_LOADING_SAMPLEINFO;
  167.             return 0;
  168.         }
  169.  
  170.         q->samplename=DupStr(s.samplename,32);
  171.         /* The correct formula for the coefficient would be
  172.            pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point
  173.            here, we'll use a first order approximation here.
  174.            1/567290 == Ln(2)/OCTAVE/32768 */
  175.         q->speed=s.speed+s.speed*(((SLONG)s.speed*(SLONG)s.finetune)/567290);
  176.         q->length    = s.sizeend-s.sizestart;
  177.         q->volume    = s.volume>>2;
  178.         q->loopstart = s.loopstart;
  179.         q->loopend   = s.loopend;
  180.         q->flags = SF_SIGNED;
  181.         if(s.flags&ULTS_LOOP) q->flags|=SF_LOOP;
  182.         if(s.flags&ULTS_16BITS) {
  183.             s.sizeend+=(s.sizeend-s.sizestart);
  184.             s.sizestart<<=1;
  185.             q->flags|=SF_16BITS;
  186.             q->loopstart>>=1;
  187.             q->loopend>>=1;
  188.         }
  189.         q++;
  190.     }
  191.  
  192.     if(!AllocPositions(256)) return 0;
  193.     for(t=0;t<256;t++)
  194.         of.positions[t]=_mm_read_UBYTE(modfp);
  195.     for(t=0;t<256;t++)
  196.         if(of.positions[t]==255) break;
  197.     of.numpos=t;
  198.  
  199.     noc=_mm_read_UBYTE(modfp);
  200.     nop=_mm_read_UBYTE(modfp);
  201.  
  202.     of.numchn=++noc;
  203.     of.numpat=++nop;
  204.     of.numtrk=of.numchn*of.numpat;
  205.     if(!AllocTracks()) return 0;
  206.     if(!AllocPatterns()) return 0;
  207.     for(u=0;u<of.numchn;u++)
  208.         for(t=0;t<of.numpat;t++)
  209.             of.patterns[(t*of.numchn)+u]=tracks++;
  210.  
  211.     /* read pan position table for v1.5 and higher */
  212.     if(mh.id[14]>='3')
  213.         for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
  214.  
  215.     for(t=0;t<of.numtrk;t++) {
  216.         int rep,row=0;
  217.  
  218.         UniReset();
  219.         while(row<64) {
  220.             rep=ReadUltEvent(&ev);
  221.  
  222.             if(feof(modfp)) {
  223.                 _mm_errno = MMERR_LOADING_TRACK;
  224.                 return 0;
  225.             }
  226.  
  227.             while(rep--) {
  228.                 UBYTE eff;
  229.                 int offset;
  230.  
  231.                 if(ev.sample) UniInstrument(ev.sample-1);
  232.                 if(ev.note)   UniNote(ev.note+2*OCTAVE-1);
  233.  
  234.                 /* first effect - various fixes by Alexander Kerkhove and
  235.                                   Thomas Neumann */
  236.                 eff = ev.eff>>4;
  237.                 switch(eff) {
  238.                     case 0x3: /* tone portamento */
  239.                         UniWrite(UNI_ITEFFECTG);
  240.                         UniWrite(ev.dat2);
  241.                         break;
  242.                     case 0x5:
  243.                         break;
  244.                     case 0x9: /* sample offset */
  245.                         offset=(ev.dat2<<8)|((ev.eff&0xf)==9?ev.dat1:0);
  246.                         UniWrite(UNI_ULTEFFECT9);
  247.                         UniWrite(offset>>8);UniWrite(offset);
  248.                         break;
  249.                     case 0xb: /* panning */
  250.                         UniPTEffect(8,ev.dat2*0xf);
  251.                         break;
  252.                     case 0xc: /* volume */
  253.                         UniPTEffect(eff,ev.dat2>>2);
  254.                         break;
  255.                     default:
  256.                         UniPTEffect(eff,ev.dat2);
  257.                         break;
  258.                 }
  259.  
  260.                 /* second effect */
  261.                 eff=ev.eff&0xf;
  262.                 switch(eff) {
  263.                     case 0x3: /* tone portamento */
  264.                         UniWrite(UNI_ITEFFECTG);
  265.                         UniWrite(ev.dat1);
  266.                         break;
  267.                     case 0x5:
  268.                         break;
  269.                     case 0x9: /* sample offset */
  270.                         if((ev.eff>>4)!=9) {
  271.                             UniWrite(UNI_ULTEFFECT9);
  272.                             UniWrite(ev.dat1);UniWrite(0);
  273.                         }
  274.                         break;
  275.                     case 0xb: /* panning */
  276.                         UniPTEffect(8,ev.dat1*0xf);
  277.                         break;
  278.                     case 0xc: /* volume */
  279.                         UniPTEffect(eff,ev.dat1>>2);
  280.                         break;
  281.                     default:
  282.                         UniPTEffect(eff,ev.dat1);
  283.                         break;
  284.                 }
  285.  
  286.                 UniNewline();
  287.                 row++;
  288.             }
  289.         }
  290.         if(!(of.tracks[t]=UniDup())) return 0;
  291.     }
  292.     return 1;
  293. }
  294.  
  295. CHAR *ULT_LoadTitle(void)
  296. {
  297.     CHAR s[32];
  298.  
  299.     _mm_fseek(modfp,15,SEEK_SET);
  300.     if(!fread(s,32,1,modfp)) return NULL;
  301.  
  302.     return(DupStr(s,32));
  303. }
  304.  
  305. /*========== Loader information */
  306.  
  307. MLOADER load_ult={
  308.     NULL,
  309.     "ULT",
  310.     "ULT loader v1.0",
  311.     ULT_Init,
  312.     ULT_Test,
  313.     ULT_Load,
  314.     ULT_Cleanup,
  315.     ULT_LoadTitle
  316. };
  317.  
  318.