home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / prg / omega060 / omega.cpp < prev    next >
C/C++ Source or Header  |  1995-06-13  |  57KB  |  1,839 lines

  1. /***********************************************/
  2. /* Omega AWE32 module player v0.6               */
  3. /* This file is written by Cygnus X-1          */
  4. /*                                               */
  5. /* You can use this file in any way you want!! */
  6. /***********************************************/
  7.  
  8. /************/
  9. /* Includes */
  10. /************/
  11. #include <iostream.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <dos.h>
  15. #include <conio.h>
  16. #include <math.h>
  17. #include <graph.h>
  18. #include <string.h>
  19. #include <time.h>
  20.                   
  21. /**************/
  22. /* Structures */
  23. /**************/
  24. struct ChannelInfo
  25.     {
  26.     long StartAddr;
  27.     long LoopStart;
  28.     long LoopEnd;
  29.     long Offset;
  30.     int Pitch;
  31.     int Period;
  32.     char Finetune;
  33.     char Volume;
  34.     char VolumeSlide;
  35.     int PitchSlide;
  36.     int PortamentoSpeed;
  37.     unsigned char Reverb;
  38.     unsigned char Chorus;
  39.     unsigned char Pan;
  40.     char AWE32Chan;
  41.     char Status;
  42.     char FirstNote;
  43.     unsigned char Env2Decay;
  44.     unsigned char Env2Sustain;
  45.     int MaxSlide;
  46.     int MinSlide;
  47.     unsigned char VibSpeed;                                    // Vibrato speed
  48.     unsigned char VibDepth;                                 // Vibrato depth
  49.     unsigned char TremSpeed;                                // Tremolo speed
  50.     unsigned char TremDepth;                                // Tremolo depth
  51.     unsigned int ArpeggioD[3];
  52.     unsigned int ArpeggioP;
  53.     };
  54. struct SampleInfo
  55.     {
  56.     char SampleName[22];                                    // padded with null bytes
  57.     unsigned int SampleLen;                                      // sample length in words
  58.     char Finetune;                                      
  59.     char Volume;                                            // 0-64
  60.     unsigned int LoopStart;                                 // loop start point in words
  61.     unsigned int LoopLen;                                    // loop length in words
  62.     };          
  63. struct SampleInfoE
  64.     { 
  65.     unsigned long StartAddr;
  66.     unsigned long LoopStart;
  67.     unsigned long LoopEnd;
  68.     };
  69. struct SongInfo
  70.     {
  71.     char SongName[20];                                      // song name
  72.     SampleInfo SampleA[31];                                     // 31 sample attributes
  73.     unsigned char SongLength;                               // length of song
  74.     char Unused;                                     
  75.     unsigned char PattSeq[128];                                   // points to pattern sequence
  76.     char FileID[4];                                            // "M.K." for 31 sample modfiles
  77.     };
  78. struct ChanI
  79.     { 
  80.     char Sample;
  81.     unsigned int Period;
  82.     char Effect;
  83.     };
  84. struct RowI
  85.     {
  86.     ChanI Chan[4];
  87.     };
  88. struct Pattern
  89.     {
  90.     RowI Row[64];
  91.     };
  92.         
  93. /********************/
  94. /* Global song data */
  95. /********************/
  96. unsigned int AWE32Base = 0x620;
  97. ChannelInfo* Channel = new ChannelInfo[4];
  98. char CR = 0;                                                // Current row
  99. int DRAMSize;
  100. unsigned char* EnvTimeTable = new unsigned char[32];
  101. SongInfo* Header = new SongInfo;
  102. unsigned int* LogTable = new unsigned int[2000];            // AWE32 log rate table
  103. unsigned char NumberOfPatterns = 0;
  104. void (_interrupt _far *OldIRQ0)(void);
  105. Pattern* Patt[128];                                            // 128 pointers to patterns
  106. SampleInfoE* SampleAE = new SampleInfoE[31];                // Extended sample attributes
  107. unsigned char SongPos = 0;                                  // Sequnce pattern position
  108. char SongSpeed = 6;                                         // Song speed(6 default)
  109. FILE *Soundfile;
  110. char TrackTick = SongSpeed;                                    // Counter for Beat interrupt handler    
  111. unsigned char* VolTable = new unsigned char[65];
  112. unsigned char Reverb = 64;                                  // Reverb effect, 0-255
  113. unsigned char Chorus = 64;                                  // Chorus effect, 0-255
  114.  
  115. unsigned char MainVolumeL,MainVolumeR;
  116. unsigned char SynthVolumeL,SynthVolumeR;
  117. unsigned char BassL,BassR;
  118. unsigned char TrebleL,TrebleR;
  119.  
  120. /****************************/
  121. /* Various constant defines */
  122. /****************************/
  123. #define     IRQ0            8
  124. #define        Left            255
  125. #define        Center          127
  126. #define        Right            0
  127.  
  128. #define        Room1            0
  129. #define        Room2            1
  130. #define        Room3            2
  131. #define        Hall1            3
  132. #define        Hall2            4
  133. #define        Plate            5
  134. #define        Delay            6
  135. #define        PanningDelay    7
  136.  
  137. #define        Chorus1            0
  138. #define        Chorus2            1
  139. #define        Chorus3            2
  140. #define        Chorus4            3
  141. #define        FeedbackChorus    4
  142. #define        Flanger            5
  143. #define        ShortDelay        6
  144. #define        Shortdelay        7
  145.    
  146. /****************/
  147. /* Effect list  */
  148. /****************/  
  149. #define        Arpeggio        0x0
  150. #define        SlideUp            0x1
  151. #define        SlideDown        0x2
  152. #define        SlideToNote        0x3
  153. #define        Vibrato            0x4
  154. #define        Tremolo            0x7
  155. #define        SampleOffset    0x9
  156. #define        VolumeSlideUD   0xA
  157. #define        PositionJump    0xB
  158. #define        SetVolume        0xC
  159. #define        PatternBreak    0xD
  160. #define        SetSpeed        0xF
  161.                      
  162. unsigned int EffectData[] = { 0x3FF,0x30,0x7FF,0x130,0xBFF,0x230,0xFFF,0x330,
  163.                             0x13FF,0x430,0x17FF,0x530,0x1BFF,0x630,0x1FFF,0x730,
  164.                             0x23FF,0x830,0x27FF,0x930,0x2BFF,0xA30,0x2FFF,0xB30,
  165.                             0x33FF,0xC30,0x37FF,0xD30,0x3BFF,0xE30,0x3FFF,0xF30,
  166.                             0x43FF,0x030,0x47FF,0x130,0x4BFF,0x230,0x4FFF,0x330,
  167.                             0x53FF,0x430,0x57FF,0x530,0x5BFF,0x630,0x5FFF,0x730,
  168.                             0x63FF,0x830,0x67FF,0x930,0x6BFF,0xA30,0x6FFF,0xB30,
  169.                             0x73FF,0xC30,0x77FF,0xD30,0x7BFF,0xE30,0x7FFF,0xF30,
  170.  
  171.                             0x83FF,0x030,0x87FF,0x130,0x8BFF,0x230,0x8FFF,0x330,
  172.                             0x93FF,0x430,0x97FF,0x530,0x9BFF,0x630,0x9FFF,0x730,
  173.                             0xA3FF,0x830,0xA7FF,0x930,0xABFF,0xA30,0xAFFF,0xB30,
  174.                             0xB3FF,0xC30,0xB7FF,0xD30,0xBBFF,0xE30,0xBFFF,0xF30,
  175.                             0xC3FF,0x030,0xC7FF,0x130,0xCBFF,0x230,0xCFFF,0x330,
  176.                             0xD3FF,0x430,0xD7FF,0x530,0xDBFF,0x630,0xDFFF,0x730,
  177.                             0xE3FF,0x830,0xE7FF,0x930,0xEBFF,0xA30,0xEFFF,0xB30,
  178.                             0xF3FF,0xC30,0xF7FF,0xD30,0xFBFF,0xE30,0xFFFF,0xF30 };
  179.                         
  180. unsigned int EffectData2[] = { 0xC10,0x8470,0x14FE,0xB488,0x167F,0xA470,0x18E7,0x84B5,
  181.                              0x1B6E,0x842A,0x1F1D,0x852A,0xDA3,0xF7C,0x167E,0x7254,
  182.                              0x0000,0x842A,1,0x852A,0x18E6,0xBAA,0x1B6D,0x7234,
  183.                              0x229F,0x8429,0x2746,0x8529,0x1F1C,0x6E7,0x229E,0x7224,
  184.                               0xDA4,0x8429,0x2C29,0x8529,0x2745,0x7F6,0x2C28,0x7254,
  185.                              0x383B,0x8428,0x320F,0x8528,0x320E,0xF02,0x1341,0x7264,
  186.                              0x3EB6,0x8428,0x3EB9,0x8528,0x383A,0xFA9,0x3EB5,0x7294,
  187.                              0x3EB7,0x8474,0x3EBA,0x8575,0x3EB8,0x44C3,0x3EBB,0x45C3,
  188.  
  189.                              0x0000,0xA404,1,0xA504,0x141F,0x671,0x14FD,0x287,
  190.                              0x3EBC,0xE610,0x3EC8,0xC7B,0x31A,0x7E6,0x3EC8,0x86F7,
  191.                              0x3EC0,0x821E,0x3EBE,0xD280,0x3EBD,0x21F,0x3ECA,0x386,
  192.                              0x3EC1,0xC03,0x3EC9,0x31E,0x3ECA,0x8C4C,0x3EBF,0xC55,
  193.                              0x3EC9,0xC280,0x3EC4,0xBC84,0x3EC8,0xEAD,0x3EC8,0xD380,
  194.                              0x3EC2,0x8F7E,0x3ECB,0x219,0x3ECB,0xD2E6,0x3EC5,0x31F,
  195.                              0x3EC6,0xC380,0x3EC3,0x327F,0x3EC9,0x265,0x3EC9,0x8319,
  196.                              0x1342,0xD3E6,0x3EC7,0x337F,0x0000,0x8365,0x1420,0x9570 };
  197.                              
  198. unsigned int EffectCommand[] = { 0x40,0xA20,0x40,0xA22,0x60,0xA20,0x60,0xA22 };  
  199.  
  200. unsigned int ChorusEffects[] = {0xE600,0x3F6,0xBC2C,0xE608,0x31A,0xBC6E,0xE610,0x31A,0xBC84,
  201.                                 0xE620,0x269,0xBC6E,0xE680,0x4D3,0xBCA6,0xE6E0,0x44E,0xBC37,
  202.                                 0xE600,0xB06,0xBC00,0xE6C0,0xB06,0xBC00 };
  203.  
  204. unsigned long ChorusEffects2[] = {  0,0x6D,0x8000,0,0,0x17C,0x8000,0,0,0x83,0x8000,0,
  205.                                     0,0x17C,0x8000,0,0,0x5B,0x8000,0,0,0x26,0x8000,0,
  206.                                     0x6E000,0x83,0x8000,0,0x6E000,0x83,0x8000,0 };
  207.  
  208. unsigned int ChorusCommand[] = {0x69,0xA20,0x6C,0xA20,0x63,0xA22,0x29,0xA20,0x2A,0xA20,0x2D,0xA20,0x2E,0xA20 };
  209.  
  210. unsigned int ReverbEffects[] = {0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,0x72A4,
  211.                                 0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,0xA490,0xA590,
  212.                                 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  213.                                 0x8428,0x8528,0x8428,0x8528, 
  214.                                 0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  215.                                 0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
  216.                                 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  217.                                 0x8428,0x8528,0x8428,0x8528,
  218.                                 0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  219.                                 0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,0xA490,0xA590,
  220.                                 0x842C,0x852C,0x842C,0x852C,0x842B,0x852B,0x842B,0x852B,
  221.                                 0x842A,0x852A,0x842A,0x852A,
  222.                                 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,0x7254,
  223.                                 0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,0xA440,0xA540,
  224.                                 0x842B,0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
  225.                                 0x8429,0x8529,0x8429,0x8529,
  226.                                 0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,0x7234,
  227.                                 0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,0xA404,0xA504,
  228.                                 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  229.                                 0x8428,0x8528,0x8428,0x8528, 
  230.                                 0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,0x7234,
  231.                                 0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,0xA440,0xA540,
  232.                                 0x842A,0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
  233.                                 0x8428,0x8528,0x8428,0x8528,
  234.                                 0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,0x7204,
  235.                                 0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
  236.                                 0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
  237.                                 0x8420,0x8520,0x8420,0x8520,
  238.                                 0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,0x7204,
  239.                                 0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,0xA4FF,0xA5FF,
  240.                                 0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
  241.                                 0x8420,0x8520,0x8420,0x8520 };
  242.                                 
  243. unsigned int ReverbCommand[] = {0x43,0xA20,0x45,0xA20,0x7F,0xA22,0x47,0xA20,
  244.                                 0x54,0xA22,0x56,0xA22,0x4F,0xA20,0x57,0xA20,
  245.                                 0x5F,0xA20,0x47,0xA22,0x4F,0xA22,0x57,0xA22,
  246.                                 0x5D,0xA22,0x5F,0xA22,0x61,0xA20,0x63,0xA20,
  247.                                 0x49,0xA20,0x4B,0xA20,0x51,0xA20,0x53,0xA20,
  248.                                 0x59,0xA20,0x5B,0xA20,0x41,0xA22,0x43,0xA22,
  249.                                 0x49,0xA22,0x4B,0xA22,0x51,0xA22,0x53,0xA22 };
  250.  
  251. void ExitWithError(char* ErrorMessage)
  252.     {
  253.     cout << ErrorMessage << "\n";
  254.     exit(1);
  255.     }           
  256.     
  257. void AWE32RegW(int Command,int DataPort,unsigned int Data)
  258.     {
  259.     _disable();
  260.     _outpw((AWE32Base+0x802),Command);
  261.     _outpw((AWE32Base-0x620+DataPort),Data);
  262.     _enable();        
  263.     }
  264.     
  265. void AWE32RegDW(int Command,int DataPort,unsigned long Data)
  266.     {
  267.     _disable();
  268.     _outpw((AWE32Base+0x802),Command);
  269.     _outpw((AWE32Base-0x620+DataPort),Data);
  270.     _outpw((AWE32Base-0x620+DataPort+2),Data>>16);
  271.     _enable();
  272.     }
  273.     
  274. unsigned int AWE32RegR(int Command,int DataPort)
  275.     {
  276.     _disable();
  277.     _outpw((AWE32Base+0x802),Command);
  278.     unsigned int k = _inpw(AWE32Base-0x620+DataPort);
  279.     _enable();
  280.     return k;
  281.     } 
  282.     
  283. unsigned long AWE32RegDR(int Command,int DataPort)
  284.     {
  285.     _disable();
  286.     _outpw((AWE32Base+0x802),Command);
  287.     unsigned long k = _inpw(AWE32Base-0x620+DataPort);
  288.     unsigned long Temp = _inpw(AWE32Base-0x620+DataPort+2);
  289.     k |= Temp << 16;
  290.     _enable();
  291.     return k;
  292.     }
  293.  
  294. int AWE32Detect()                                       // autodetect AWE32 at 620h,640h,660h or 680h
  295.     {
  296.     for(int AWE32Base=0x620;AWE32Base<=0x680;AWE32Base +=0x20)
  297.         {
  298.         if(AWE32RegR(0xE0,0xE20)&0xC != 0xC)
  299.             continue;
  300.         if(AWE32RegR(0x3D,0xA20)&0x58 != 0x58)
  301.             continue;
  302.         if(AWE32RegR(0x3E,0xA20)&3 != 3)
  303.             continue;
  304.         return 0;
  305.         }
  306.     return 1;    
  307.     }        
  308.     
  309. void InitEffect(unsigned int* Data)
  310.     { 
  311.     for(int k=0;k<4;++k)
  312.         for(int i=0;i<32;++i)
  313.             AWE32RegW(EffectCommand[k*2]+i,EffectCommand[k*2+1],Data[k*32+i]);
  314.     }
  315. void InitEffect2(unsigned int* Data)
  316.     {
  317.     for(int k=0;k<4;++k)
  318.         for(int i=0;i<32;++i)       
  319.             {
  320.             unsigned int TempData = Data[k*32+i];
  321.             AWE32RegW(EffectCommand[k*2]+i,EffectCommand[k*2+1],TempData | (i&1)<<15);
  322.             }
  323.     }                         
  324.     
  325. /*********************************************/  
  326. /* Wait Delay number of AWE32 44100Hz clocks */
  327. /*********************************************/
  328. void AWE32Wait(unsigned int Clocks)
  329.     {
  330.     unsigned int k = AWE32RegR(0x3B,0xA22);                 // 44100Hz clock
  331.     unsigned Time = k;
  332.     while(Clocks > (Time-k))
  333.         Time = AWE32RegR(0x3B,0xA22);
  334.     }
  335.     
  336. /****************************************/
  337. /* Initialization of the AWE32 hardware */
  338. /****************************************/
  339. void AWE32Init()
  340.     {
  341.     for(int k=0;k<32;++k)                                    // init envelope engine 
  342.         {  
  343.         AWE32RegW(0xA0+k,0xA20,0x80);                        // envelope 2 sustain & decay
  344.         AWE32RegW(0xC0+k,0xA22,0);                            // envelope 1 hold & attack
  345.         AWE32RegW(0xE0+k,0xA20,0);                            // envelope 1 sustain & decay
  346.         AWE32RegW(0x00+k,0xE20,0xE000);                        // pitch
  347.         AWE32RegW(0x20+k,0xE20,0xFF00);                        // filter cutoff & volume
  348.         AWE32RegW(0x40+k,0xE20,0);                            // envelope 1 to pitch & filter
  349.         AWE32RegW(0x60+k,0xE20,0);                            // LFO1 to pitch & filter
  350.         AWE32RegW(0x80+k,0xE20,0x18);                        // LFO1 frequnecy & LFO1 to volume
  351.         AWE32RegW(0xA0+k,0xE20,0x18);                        // LFO2 frequency & LFO2 to pitch
  352.         AWE32RegW(0xC0+k,0xE20,0);                            // ???
  353.         AWE32RegW(0xE0+k,0xA22,0);                            // LFO2 delay
  354.         AWE32RegW(0xA0+k,0xA22,0);                            // LFO1 delay
  355.         AWE32RegW(0x80+k,0xA22,0);                            // envelope 2 hold & attack
  356.         AWE32RegW(0x80+k,0xA20,0);                            // envelope 2 delay
  357.         AWE32RegW(0xC0+k,0xA20,0);                            // envelope 1 delay
  358.         }           
  359.         
  360.     AWE32Wait(2);     
  361.          
  362.     for(k=0;k<32;++k)                                        // init sound engine
  363.         {
  364.         AWE32RegDW(0x20+k,0x620,0);
  365.         AWE32RegDW(0x60+k,0x620,0xFFFF);
  366.         AWE32RegDW(0xC0+k,0x620,0);                            // pan & loop start
  367.         AWE32RegDW(0xE0+k,0x620,0);                            // chorus & loop end
  368.         AWE32RegDW(0x00+k,0x620,0);
  369.         AWE32RegDW(0x40+k,0x620,0xFFFF);
  370.         AWE32RegDW(0x00+k,0xA20,0);                            // filter coeff. & start address
  371.         AWE32RegDW(0xA0+k,0x620,0);
  372.         AWE32RegDW(0x80+k,0x620,0);
  373.         AWE32RegW(0xA0+k,0xA20,0x807F);
  374.         }  
  375.         
  376.     AWE32RegW(0x34,0xA20,0);                                // init effects engine
  377.     AWE32RegW(0x35,0xA20,0);
  378.     AWE32RegW(0x36,0xA20,0);
  379.     AWE32RegW(0x35,0xA20,0);
  380.     
  381.     InitEffect(EffectData);
  382.     AWE32Wait(0x400);
  383.     InitEffect2(EffectData);
  384.     for(k=0;k<0x14;++k)
  385.         AWE32RegDW(0x20+k,0xA20,0);
  386.     InitEffect2(EffectData2);
  387.     
  388.     AWE32RegDW(0x29,0xA20,0);
  389.     AWE32RegDW(0x2A,0xA20,0x83);
  390.     AWE32RegDW(0x2D,0xA20,0x8000);
  391.     AWE32RegDW(0x2E,0xA20,0);
  392.     
  393.     InitEffect(EffectData2);     
  394.  
  395.     AWE32RegW(0xBE,0xA20,0x80);                                // init DRAM refresh
  396.     AWE32RegDW(0xDE,0x620,0xFFFFFFE0);
  397.     AWE32RegDW(0xFE,0x620,0xFFFFE8);
  398.     AWE32RegDW(0x3E,0x620,0);
  399.     AWE32RegDW(0x1E,0x620,0);
  400.     AWE32RegDW(0x1E,0xA20,0xFFFFE3);
  401.     
  402.     AWE32RegW(0xBF,0xA20,0x80);
  403.     AWE32RegDW(0xDF,0x620,0xFFFFF0);
  404.     AWE32RegDW(0xFF,0x620,0xFFFFF8);
  405.     AWE32RegDW(0x3F,0x620,0xFF);
  406.     AWE32RegDW(0x1F,0x620,0x8000);
  407.     AWE32RegDW(0x1F,0xA20,0xFFFFF3);
  408.      
  409.     _disable();
  410.     _outpw(AWE32Base+0x802,0x3E);
  411.     _outpw(AWE32Base,0);
  412.     while(k==0)
  413.         k = _inpw(AWE32Base+0x802) & 0x10;
  414.     while(k==0x10)
  415.         k = _inpw(AWE32Base+0x802) & 0x10;
  416.     _enable();
  417.     _outpw(AWE32Base+2,0x4828);
  418.     _outpw(AWE32Base+0x802,0x3C);
  419.     _outpw(AWE32Base+0x400,0);
  420.     _enable();
  421.     
  422.     AWE32RegDW(0x7E,0x620,0xFFFFFFFF);
  423.     AWE32RegDW(0x7F,0x620,0xFFFFFFFF);
  424.     }
  425.    
  426. void SetReverbEffect(char Effect)
  427.     {
  428.     for(int k=0; k<28; k++)
  429.         AWE32RegW(ReverbCommand[k*2],ReverbCommand[k*2+1],ReverbEffects[k+Effect*28]);
  430.     }                               
  431. void SetChorusEffect(char Effect)
  432.     {              
  433.     for(int k=0; k<3; k++)
  434.         AWE32RegW(ChorusCommand[k*2],ChorusCommand[k*2+1],ChorusEffects[k+Effect*3]);
  435.     for(k=0; k<4; k++)
  436.         AWE32RegDW(ChorusCommand[6+k*2],ChorusCommand[6+k*2+1],ChorusEffects2[k+Effect*4]);
  437.     }
  438. /*********************************************/
  439. /* Convert an Motorola word to an Intel word */
  440. /*********************************************/                                              
  441. unsigned int cword(unsigned int BigEndian)
  442.     {
  443.     return ((BigEndian&0xFF)<<8) | ((BigEndian&0xFF00)>>8);
  444.     }
  445.     
  446. /****************************/
  447. /* Enable AWE32 DRAM access */
  448. /****************************/
  449. void EnableDRAM()
  450.     {
  451.     unsigned long Scratch;
  452.  
  453.     AWE32RegW(0x3E,0xA20,0x20);                             // enable DRAM access
  454.     for(int k=0;k<30;k++)
  455.         {
  456.         AWE32RegW(0xA0+k,0xA20,0x80);
  457.         AWE32RegDW(0x60+k,0x620,0);
  458.         AWE32RegDW(0x40+k,0x620,0);
  459.         AWE32RegDW(0xC0+k,0x620,0);
  460.         AWE32RegDW(0xE0+k,0x620,0);
  461.         AWE32RegDW(0x20+k,0x620,0x40000000);
  462.         AWE32RegDW(0+k,0x620,0x40000000);
  463.         Scratch = (((k&1)<<9)+0x400);
  464.         Scratch = Scratch <<16;
  465.         AWE32RegDW(0+k,0xA20,Scratch);
  466.         }
  467.     }
  468.     
  469. /*****************************/
  470. /* Disable AWE32 DRAM access */
  471. /*****************************/
  472. void DisableDRAM()
  473.     {
  474.     for(int k=0;k<30;k++)                                        // disable DRAM access
  475.         {
  476.         AWE32RegDW(k,0xA20,0);
  477.         AWE32RegW(0xA0+k,0xA20,0x807F);
  478.         }
  479.     }
  480.     
  481. /**************/
  482. /* Check DRAM */
  483. /**************/
  484. void CheckDRAM()
  485.     { 
  486.     EnableDRAM();
  487.         
  488.     AWE32RegDW(0x36,0xA20,0x200000);                        // Address for writing
  489.     AWE32RegW(0x3A,0xA20,0x1234);
  490.     AWE32RegW(0x3A,0xA20,0x7777);    
  491.     
  492.     while(DRAMSize < 28*1024)                                // 28 MB is max onboard memory
  493.         {
  494.         AWE32Wait(2);
  495.         AWE32RegDW(0x34,0xA20,0x200000);                    // Address for reading
  496.         AWE32RegR(0x3A,0xA20);                                // Skip first word
  497.         if(AWE32RegR(0x3A,0xA20) != 0x1234)
  498.             break;
  499.         if(AWE32RegR(0x3A,0xA20) != 0x7777)
  500.             break;                                
  501.         DRAMSize += 32;
  502.            AWE32RegDW(0x36,0xA20,0x200000+DRAMSize*512L);        // Address for writing
  503.         AWE32RegW(0x3A,0xA20,0xFFFF);
  504.         }
  505.     
  506.     DisableDRAM();
  507.     }
  508.  
  509. /******************************************/
  510. /* Load & upload instruments to the AWE32 */
  511. /******************************************/
  512. void LoadInstruments()
  513.     {
  514.     long AWE32FreeMem = DRAMSize * 1024L;
  515.     long BufferSize = 32768;
  516.     long SampleLen,LoopStart,LoopLen,LoopEnd;
  517.     long CurrentAddr = 0x200000;
  518.     long Samples;
  519.     long CurrentSample;
  520.     char* SampleBuffer = new char[BufferSize];
  521.     char LoopSample1,LoopSample2; 
  522.              
  523.     cout << "Uploading instruments to AWE32 DRAM:" << endl;
  524.     EnableDRAM();
  525.     AWE32RegDW(0x36,0xA20,CurrentAddr);                            // write start address
  526.     
  527.     for(int Instr=0; Instr<31; Instr++)                            // Load 31 samples
  528.         {
  529.         SampleLen = cword(Header->SampleA[Instr].SampleLen)*2L;
  530.         SampleAE[Instr].StartAddr = 0;                            // Start address 0 will not play sample
  531.         if(SampleLen == 0)                                         // Is this a sample?
  532.             continue;
  533.         
  534.         for(int m=0; m<22; m++)
  535.             {
  536.             if(Header->SampleA[Instr].SampleName[m] < 32)
  537.                 {
  538.                 Header->SampleA[Instr].SampleName[m] = 0;
  539.                 break;
  540.                 }
  541.             if(m == 21)
  542.                 Header->SampleA[Instr].SampleName[m] = 0;
  543.             }
  544.             
  545.         cout << Header->SampleA[Instr].SampleName;
  546.         for(int k=0; k<(25-strlen(Header->SampleA[Instr].SampleName)); k++)
  547.             cout << " ";
  548.         
  549.         if(AWE32FreeMem < (SampleLen+8))
  550.             {
  551.             fseek(Soundfile,SampleLen,SEEK_CUR);        
  552.             cout << "ERROR: Not enough AWE32 memory!" << endl;
  553.             continue;
  554.             }
  555.         
  556.         LoopStart = cword(Header->SampleA[Instr].LoopStart)*2L;
  557.         LoopLen = cword(Header->SampleA[Instr].LoopLen)*2L;
  558.         LoopEnd = LoopStart+LoopLen;
  559.         if((Header->SampleA[Instr].Finetune &8) != 0)           // Expand finetune signed nibble to signed char
  560.             Header->SampleA[Instr].Finetune |= 0xF0;
  561.         
  562.         CurrentSample = 0;
  563.         
  564.         if(LoopLen < 4)
  565.             {
  566.             LoopStart = SampleLen+1;                            // Never find loopstart
  567.             LoopSample1 = 0;                                    // Smooth end to 0
  568.             LoopEnd = SampleLen;
  569.             }
  570.             
  571.         do
  572.             {
  573.             if((CurrentSample+BufferSize) >= SampleLen)
  574.                 Samples = SampleLen-CurrentSample;
  575.             else
  576.                 Samples = BufferSize;
  577.             
  578.             fread(SampleBuffer,1,Samples,Soundfile);            // read sample data from file
  579.             
  580.             if(LoopStart < (CurrentSample + Samples))            // Find first sample in loop
  581.                 {
  582.                 if(LoopStart > CurrentSample)
  583.                     LoopSample1 = SampleBuffer[LoopStart-CurrentSample];
  584.                 }                         
  585.                 
  586.             if(LoopEnd <= (CurrentSample + Samples))             // Find last sample in loop
  587.                 {
  588.                 if(LoopEnd >= CurrentSample)
  589.                     {
  590.                     LoopSample2 = SampleBuffer[LoopEnd-CurrentSample-9];
  591.                     for(int i=0; i<8; i++)
  592.                         SampleBuffer[LoopEnd-CurrentSample-8+i] = LoopSample2+(i+1)*(LoopSample1-LoopSample2)/8;
  593.                     }
  594.                 }
  595.                 
  596.             for(long i=0; i<Samples; i++)
  597.                 {
  598.                 AWE32RegW(0x3A,0xA20,SampleBuffer[i]<<8);        // upload data to AWE32 DRAM
  599.                 if((CurrentSample + i) == LoopStart)
  600.                     LoopSample1 = SampleBuffer[i];
  601.                 }
  602.                 
  603.             CurrentSample += Samples;
  604.             }    
  605.         while(CurrentSample != SampleLen);
  606.          
  607.         SampleAE[Instr].StartAddr = CurrentAddr;
  608.         if(LoopLen < 4)
  609.             {
  610.             for(int i=0; i<8; i++)                                // Anticlick samples
  611.                 AWE32RegW(0x3A,0xA20,0);
  612.             SampleAE[Instr].LoopStart = SampleLen+CurrentAddr;
  613.             SampleAE[Instr].LoopEnd = SampleLen+5+CurrentAddr;
  614.             CurrentAddr += SampleLen + 8;
  615.             AWE32FreeMem -= SampleLen + 8;
  616.             }
  617.         else
  618.             {
  619.             SampleAE[Instr].LoopStart = LoopStart+CurrentAddr;
  620.             SampleAE[Instr].LoopEnd = LoopStart+LoopLen+CurrentAddr-3;
  621.             CurrentAddr += SampleLen;
  622.             AWE32FreeMem -= SampleLen + 8;
  623.             }
  624.         cout << "OK!" << endl;
  625.         }         
  626.                       
  627.     delete SampleBuffer;
  628.     DisableDRAM();
  629.     }    
  630.  
  631. /******************************************/
  632. /* Play a note with settings from Chan[i] */
  633. /******************************************/       
  634. void PlayNote(ChannelInfo* Chan, int i)
  635.     {       
  636.     char GChan = Chan[i].AWE32Chan;
  637.     AWE32RegW(0xA0+GChan,0xA20,0x807F);                        // envelope 2 sustain & decay
  638.     AWE32RegW(0x00+GChan,0xE20,0xE000);                           // pitch
  639.     
  640.     AWE32RegW(0xA0+GChan,0xA20,0x80);                         // envelope 2 sustain & decay
  641.     AWE32RegDW(0x60+GChan,0x620,0xFFFF);
  642.                                                             
  643.     AWE32RegW(0x80+GChan,0xA20,0x8000);                        // envelope 2 delay
  644.     AWE32RegW(0x80+GChan,0xA22,0x7F7F);                        // envelope 2 hold & attack
  645.     AWE32RegW(0xC0+GChan,0xA20,0x8000);                       // envelope 1 delay
  646.     AWE32RegW(0xC0+GChan,0xA22,0x7F7F);                       // envelope 1 hold & attack
  647.     AWE32RegW(0xE0+GChan,0xA20,0x7F);                         // envelope 2 sustain & decay
  648.         
  649.     AWE32RegW(0x00+GChan,0xE20,Chan[i].Pitch);                // pitch
  650.     unsigned char AWE32Vol = VolTable[Chan[i].Volume];
  651.     AWE32RegW(0x20+GChan,0xE20,0xFF00 | AWE32Vol);            // filter cutoff & volume
  652.     AWE32RegW(0xA0+GChan,0xA22,0x8000);                       // LFO1 delay
  653.     AWE32RegW(0xE0+GChan,0xA22,0x8000);                       // LFO2 delay
  654.     AWE32RegW(0x40+GChan,0xE20,0);                            // envelope 2 to pitch & filter
  655.     AWE32RegW(0x60+GChan,0xE20,0);                            // LFO1 to pitch & filter
  656. //    AWE32RegW(0x80+GChan,0xE20,0x7F);                         // LFO1 frequency & to volume
  657.     AWE32RegW(0x80+GChan,0xE20,(Chan[i].TremDepth << 8) | Chan[i].TremSpeed);
  658.     AWE32RegW(0xA0+GChan,0xE20,(Chan[i].VibDepth << 8) | Chan[i].VibSpeed);
  659.     AWE32RegDW(0x20+GChan,0x620,(Chan[i].Reverb<<8) | (AWE32RegDR(0x20+GChan,0x620)&0xFFFF0000));
  660.     long TempPan = Chan[i].Pan;
  661.     TempPan <<= 24L;
  662.     AWE32RegDW(0xC0+GChan,0x620,TempPan | Chan[i].LoopStart);
  663.     TempPan = Chan[i].Chorus;
  664.     TempPan <<= 24L;
  665.     AWE32RegDW(0xE0+GChan,0x620,TempPan | Chan[i].LoopEnd);    
  666.     AWE32RegDW(0x00+GChan,0xA20,Chan[i].StartAddr+Chan[i].Offset);
  667.     AWE32RegW(0xA0+GChan,0xA20,Chan[i].Env2Sustain<<8 | Chan[i].Env2Decay);
  668.     }         
  669.       
  670. void NoteOff(char Channel)
  671.     {
  672.     AWE32RegW(0xA0+Channel,0xA20,0x807F);
  673.     AWE32RegW(0xE0+Channel,0xA20,0x807F);
  674.     }
  675.  
  676. /**********************************************/
  677. /* Calculate the AWE32 logarithmic rate table */
  678. /**********************************************/    
  679. void CalcLogTable()
  680.     {               
  681.     long Frequency;
  682.     for(int k=75;k<2000;k++)
  683.         {
  684.         Frequency = 8363L*428L/k;
  685.         LogTable[k] = int(log(Frequency)*5909.27-5850.98);
  686.         }          
  687.  
  688.     VolTable[0] = 127;
  689.     for(k=1; k<65; k++)
  690.         VolTable[k] = char(127 - log(k)*26.6899);
  691.         
  692.     }               
  693.                 
  694. /**********************************************/
  695. /* DecodePatterns functions flips a couple of */
  696. /* bytes in the pattern so that it would be   */
  697. /* easier to use the data when playing          */
  698. /**********************************************/
  699. void DecodePatterns()
  700.     {   
  701.     char b;
  702.     int w;
  703.     
  704.     for(int k=0; k<NumberOfPatterns; k++)
  705.         for(int n=0; n<64; n++)
  706.             for(int i=0; i<4; i++)
  707.                 {       
  708.                 b = Patt[k]->Row[n].Chan[i].Period >> 12;
  709.                 b &= 0xF;
  710.                 b |= Patt[k]->Row[n].Chan[i].Sample & 0xF0;
  711.                 w = Patt[k]->Row[n].Chan[i].Period << 4;
  712.                 w &= 0xF000;
  713.                 w |= (Patt[k]->Row[n].Chan[i].Sample << 8L)&0xFFF;
  714.                 w |= Patt[k]->Row[n].Chan[i].Period & 0xFF;
  715.                 
  716.                 Patt[k]->Row[n].Chan[i].Sample = b;
  717.                 Patt[k]->Row[n].Chan[i].Period = w;
  718.                 }
  719.     }
  720. /**********************/
  721. /* Beat function data */
  722. /**********************/
  723.     char CP;                                                // Current pattern
  724.     char Effect;                                            // Effect type
  725.     unsigned char EffectD;                                    // Effect data                                    
  726.     int Finetune;                
  727.     char i;                                                    // Channel number in loop
  728.     char l;
  729.     char s;                                                    // Sample to play
  730.     int Period;                                             // Note to play
  731.     int    StackSeg;
  732.     int    StackPtr;
  733.     int    StackData[1024];
  734.     unsigned char NewSongPos = 255;
  735.     char NewCR = 0;
  736.     char TempSTR[8];    
  737.     unsigned int TempTimer;
  738.     
  739. /******************************************************/
  740. /* IRQ0 Timer interrupt handler                       */
  741. /* This function is called 50 times a second(125 BPM) */
  742. /*                                                       */
  743. /* Counts TrackTick down to 0 and then plays a row    */
  744. /******************************************************/
  745. void interrupt Beat()                                 
  746.     {
  747.     _asm
  748.         {
  749.         mov    ax,ss                                            // Switch to our stack
  750.         mov    StackSeg,ax
  751.         mov    StackPtr,sp
  752.         mov    ax,ds
  753.         mov    ss,ax           
  754.         mov    sp,StackData+1024
  755.         }        
  756.         
  757.     if( SongPos == 255)
  758.         goto EXIT_INT;                                        // The song has finished
  759.         
  760.     TrackTick -= 1;                                            // TrackTick is a counter based on the song speed
  761.     if(TrackTick != 0)
  762.         {
  763.         for(i=0; i<4; i++)
  764.             {
  765.             if(Channel[i].VolumeSlide != 0)
  766.                 {
  767.                 Channel[i].Volume += Channel[i].VolumeSlide;
  768.                 if(Channel[i].Volume > 64)
  769.                     Channel[i].Volume = 64;                    // Don't slide higher than 64
  770.                 if(Channel[i].Volume < 0)                   // Don't slide less than 0
  771.                     Channel[i].Volume = 0;                    
  772.                 AWE32RegW(0x20+Channel[i].AWE32Chan,0xE20,0xFF00 | VolTable[Channel[i].Volume]);
  773.                 }
  774.             if(Channel[i].PitchSlide != 0)
  775.                 {
  776.                 Channel[i].Period += Channel[i].PitchSlide;
  777.                 if(Channel[i].Period > Channel[i].MinSlide)
  778.                     Channel[i].Period = Channel[i].MinSlide;
  779.                 if(Channel[i].Period < Channel[i].MaxSlide)
  780.                     Channel[i].Period = Channel[i].MaxSlide;
  781.                 AWE32RegW(Channel[i].AWE32Chan,0xE20,LogTable[Channel[i].Period + Channel[i].Finetune]);
  782.                 }
  783.             if(Channel[i].ArpeggioD[0] != 0)
  784.                 {
  785.                 AWE32RegW(Channel[i].AWE32Chan,0xE20,LogTable[Channel[i].ArpeggioD[Channel[i].ArpeggioP] + Channel[i].Finetune]);
  786.                 if(Channel[i].ArpeggioP == 2)
  787.                     Channel[i].ArpeggioP = 0;
  788.                 else
  789.                     Channel[i].ArpeggioP++;
  790.                 }
  791.             }
  792.         goto EXIT_INT;                                      // Don't play new row yet
  793.         }
  794.      
  795.     CP = Header->PattSeq[SongPos];                            // Fetch current pattern from pattern sequence    
  796.     for(i=0; i<4; i++)
  797.         {
  798.         if(Channel[i].VibSpeed != 0)
  799.             AWE32RegW(0xA0+Channel[i].AWE32Chan,0xE20,0);    // stop vibrating
  800.         if(Channel[i].TremSpeed != 0)
  801.             AWE32RegW(0x80+Channel[i].AWE32Chan,0xE20,0);    // stop tremolo 
  802.         if(Channel[i].ArpeggioD[0] != 0)
  803.             AWE32RegW(Channel[i].AWE32Chan,0xE20,LogTable[Channel[i].Period + Channel[i].Finetune]);
  804.         Channel[i].ArpeggioD[0] = 0;
  805.             
  806.         s = Patt[CP]->Row[CR].Chan[i].Sample;
  807.         Period = Patt[CP]->Row[CR].Chan[i].Period;
  808.         Effect = (Period >> 12) & 0xF;                      // Effect type is the top 4 bits of Period
  809.         EffectD = Patt[CP]->Row[CR].Chan[i].Effect;            // Fetch effect data
  810.         Period &= 0xFFF;                                    // Throw away the effect type
  811.         
  812.         if(Period == 0)
  813.             s = 0;
  814.             
  815.         if(s != 0)
  816.             {
  817.             Channel[i].Status = 1;
  818.             s -= 1;
  819.             Channel[i].Volume = Header->SampleA[s].Volume;
  820.             Channel[i].StartAddr = SampleAE[s].StartAddr;
  821.             Channel[i].LoopStart = SampleAE[s].LoopStart;
  822.             Channel[i].LoopEnd = SampleAE[s].LoopEnd;
  823.             Channel[i].Env2Decay = 0x7F;                    // Decay time set to zero
  824.             Channel[i].Env2Sustain = 0x7F;                  // Max sustain
  825.             Finetune = Header->SampleA[s].Finetune;
  826.             Channel[i].Pitch = LogTable[Period+Finetune];        // AWE32 logarithmic rate
  827.             Channel[i].Period = Period;
  828.             Channel[i].Finetune = Finetune;
  829.             Channel[i].VibSpeed = 0;
  830.             Channel[i].TremSpeed = 0;
  831.             Channel[i].Offset = 0;
  832.             }
  833.             
  834.         if(Period == 0)
  835.             Channel[i].Status = 0;    
  836.             
  837.         if(Finetune && 8)                                    // Finetune is a 4-bit signed value
  838.             Finetune |= 0xFFF0;                             // Expand sign to 16-bit
  839.         
  840.         Channel[i].Reverb = Reverb;
  841.         Channel[i].Chorus = Chorus;
  842.         Channel[i].VolumeSlide = 0;
  843.         Channel[i].PitchSlide = 0;
  844.  
  845.         switch(Effect)                                    // Find out which effect we have
  846.             {
  847.             case Arpeggio:
  848.                 if(EffectD != 0)
  849.                     {                     
  850.                     Channel[i].ArpeggioP = 1;
  851.                     Channel[i].ArpeggioD[0] = Channel[i].Period;
  852.                     Channel[i].ArpeggioD[1] = Channel[i].Period;
  853.                     Channel[i].ArpeggioD[2] = Channel[i].Period;
  854.                     for(l=0; l<((EffectD>>4)&0xF); l++)
  855.                         Channel[i].ArpeggioD[1] -= Channel[i].ArpeggioD[1]>>4;
  856.                     for(l=0; l<(EffectD&0xF); l++)
  857.                         Channel[i].ArpeggioD[2] -= Channel[i].ArpeggioD[2]>>4;
  858.                     }
  859.                 break;
  860.             case SlideUp:
  861.                 Channel[i].PitchSlide = - EffectD;
  862.                 Channel[i].MaxSlide = 113;
  863.                 Channel[i].MinSlide = 856;
  864.                 break;
  865.             case SlideDown:
  866.                 Channel[i].PitchSlide = EffectD;
  867.                 Channel[i].MaxSlide = 113;
  868.                 Channel[i].MinSlide = 856;
  869.                 break;
  870.             case SlideToNote:
  871.                 if(EffectD == 0)
  872.                     {
  873.                     Channel[i].PitchSlide = Channel[i].PortamentoSpeed;
  874.                     break;
  875.                     }   
  876.                 if(Period != 0)
  877.                     {
  878.                     if(Channel[i].Period > Period)
  879.                         {
  880.                         if(Period != 0)
  881.                             Channel[i].MaxSlide = Period;
  882.                         Channel[i].PitchSlide = - EffectD;
  883.                         }
  884.                     else
  885.                         {   
  886.                         if(Period != 0)
  887.                             Channel[i].MinSlide = Period;
  888.                         Channel[i].PitchSlide = EffectD;
  889.                         }
  890.                     }
  891.                 else
  892.                     {
  893.                     if(Channel[i].PortamentoSpeed > 0)
  894.                         Channel[i].PitchSlide = EffectD;
  895.                     else
  896.                         Channel[i].PitchSlide = - EffectD;
  897.                     }
  898.                 Channel[i].PortamentoSpeed = Channel[i].PitchSlide;
  899.                 break;
  900.             case Vibrato:
  901.                 if(EffectD & 0xF != 0)
  902.                     Channel[i].VibSpeed = (EffectD >> 4)*16+7;
  903.                 if(EffectD & 0xF0 != 0)
  904.                     Channel[i].VibDepth = EffectD & 0xF;
  905.                 if(Channel[i].Status == 0)
  906.                     AWE32RegW(0xA0+Channel[i].AWE32Chan,0xE20,(Channel[i].VibDepth << 8) | Channel[i].VibSpeed);
  907.                 break;         
  908.             case Tremolo:
  909.                 if(EffectD & 0xF != 0)
  910.                     Channel[i].TremSpeed = (EffectD >> 4)*16+7;
  911.                 if(EffectD & 0xF0 != 0)
  912.                     Channel[i].TremDepth = EffectD & 0xF;
  913.                 if(Channel[i].Status == 0)
  914.                     AWE32RegW(0x80+Channel[i].AWE32Chan,0xE20,(Channel[i].TremDepth << 8) | Channel[i].TremSpeed);
  915.                 break;
  916.             case SampleOffset:
  917.                 Channel[i].Offset = EffectD << 8L;
  918.                 break;
  919.             case VolumeSlideUD:
  920.                 if((EffectD & 0xF0) == 0)
  921.                     Channel[i].VolumeSlide = - EffectD;
  922.                 if((EffectD & 0xF) == 0)
  923.                     Channel[i].VolumeSlide = EffectD>>4;
  924.                 break;
  925.             case PositionJump:
  926.                 NewSongPos = EffectD;     
  927.                 break;
  928.             case SetVolume:
  929.                 Channel[i].Volume = EffectD;
  930.                 if(Channel[i].Status == 0)
  931.                     AWE32RegW(0x20+Channel[i].AWE32Chan,0xE20,0xFF00 | VolTable[EffectD]);
  932.                 break;
  933.             case PatternBreak:
  934.                 NewCR = EffectD;
  935.                 NewSongPos = SongPos + 1;
  936.                 break;
  937.             case SetSpeed:
  938.                 if(EffectD < 32)
  939.                     SongSpeed = EffectD;
  940.                 else 
  941.                     {
  942.                     TempTimer = 1193181L/((EffectD*50L)/125);
  943.                     _outp(0x40,TempTimer&0xFF);                                        
  944.                     _outp(0x40,(TempTimer>>8)&0xFF);
  945.                     }
  946.                    break;
  947.             }      
  948.         }
  949.     
  950.     l = 0;                   
  951.     for(i=0; i<4; i++)
  952.         {
  953.         while( l != 30 )
  954.             {
  955.             if((AWE32RegR(0xA0+l,0xA20) >> 15) == 1)
  956.                 if((AWE32RegDR(0x60+l,0x620) >> 16) == 0)
  957.                     break;
  958.             l++;
  959.             }
  960.         if(l == 30)
  961.             break;
  962.         if(Channel[i].Status == 1)
  963.             {
  964.             if(Channel[i].FirstNote != 1)
  965.                 NoteOff(Channel[i].AWE32Chan);
  966.             else
  967.                 Channel[i].FirstNote = 0;
  968.                 
  969.             Channel[i].AWE32Chan = l;
  970.             if(Channel[i].StartAddr != 0)
  971.                 PlayNote(Channel, i);
  972.             Channel[i].Status = 0;
  973.             l++;
  974.             }
  975.         }
  976.     
  977.     TempSTR[0] = SongPos/10+48;
  978.     TempSTR[1] = (SongPos - (SongPos/10)*10)+48;
  979.     TempSTR[2] = 0;
  980.     _settextposition(4,44);
  981.     _outtext(TempSTR);
  982.     
  983.     TempSTR[0] = CR/10+48;
  984.     TempSTR[1] = (CR - (CR/10)*10)+48;
  985.     TempSTR[2] = 0;
  986.     _settextposition(4,60);
  987.     _outtext(TempSTR);
  988.         
  989.     CR++;                                                    // Increase current row
  990.         if(CR == 64)                                            // If end of pattern, reset
  991.             {                                                   // current row & increase song pos
  992.             CR = 0;
  993.             SongPos++;
  994.             Header->SongLength -= 1;
  995.             if(Header->SongLength == 0)    
  996.                 SongPos = 255;
  997.             }
  998.     if(NewSongPos != 255)
  999.         {
  1000.         Header->SongLength += SongPos - NewSongPos;
  1001.         SongPos = NewSongPos;
  1002.         CR = NewCR;
  1003.         NewSongPos = 255;
  1004.         NewCR = 0;
  1005.         }
  1006.             
  1007.     TrackTick = SongSpeed;    
  1008.     EXIT_INT:;
  1009.     _disable();
  1010.     _outp(0x20,0x20);                                        // send end of interrupt to int controller 
  1011.     _asm
  1012.         {
  1013.         mov    ss,StackSeg                                        // Restore stack
  1014.         mov    sp,StackPtr
  1015.         }        
  1016.     }                
  1017.     
  1018. /*******************/    
  1019. /* Mouse functions */
  1020. /*******************/
  1021. union REGS regs;
  1022.  
  1023. void ShowMouseCursor()
  1024.     {
  1025.     regs.x.ax = 1;
  1026.     int86(0x33,®s,®s);
  1027.     }
  1028.     
  1029. void HideMouseCursor()
  1030.     {
  1031.     regs.x.ax = 2;
  1032.     int86(0x33,®s,®s);
  1033.     }
  1034.       
  1035. void InitMouse()
  1036.     {
  1037.     regs.x.ax = 0;
  1038.     int86(0x33,®s,®s);
  1039.     }
  1040.  
  1041. int GetMousePos(unsigned int* MouseX,unsigned int* MouseY)
  1042.     {
  1043.     regs.x.ax = 3;
  1044.     int86(0x33,®s,®s);
  1045.     *MouseX = regs.x.cx;
  1046.     *MouseY = regs.x.dx;
  1047.     return regs.x.bx;
  1048.     }  
  1049.       
  1050. int GetMouseButtonStat()
  1051.     {
  1052.     regs.x.ax = 5;
  1053.     regs.x.bx = 0;
  1054.     int86(0x33,®s,®s);
  1055.     return regs.x.ax;
  1056.     }                
  1057.     
  1058. int MouseMov(unsigned int* MouseX,unsigned int* MouseY)
  1059.     {
  1060.     regs.x.ax = 3;
  1061.     int86(0x33,®s,®s);
  1062.     if(*MouseX != regs.x.cx || *MouseY != regs.x.dx)
  1063.         {
  1064.         *MouseX = regs.x.cx;
  1065.         *MouseY = regs.x.dx;
  1066.         return 1;
  1067.         }
  1068.     return 0;
  1069.     }
  1070.     
  1071. void SetMousePos(int MouseX,int MouseY)
  1072.     {
  1073.     regs.x.ax = 4;
  1074.     regs.x.cx = MouseX;
  1075.     regs.x.dx = MouseY;
  1076.     int86(0x33,®s,®s);
  1077.     }
  1078.  
  1079. void SetMouseYLimits(int yMin,int yMax)
  1080.     {                                  
  1081.     regs.x.ax = 8;
  1082.     regs.x.cx = yMin;
  1083.     regs.x.dx = yMax;
  1084.     int86(0x33,®s,®s);
  1085.     } 
  1086.  
  1087. void SetMouseXLimits(int xMin,int xMax)
  1088.     {
  1089.     regs.x.ax = 7;
  1090.     regs.x.cx = xMin;
  1091.     regs.x.dx = xMax;
  1092.     int86(0x33,®s,®s);
  1093.     } 
  1094.     
  1095. void WaitRetrace()
  1096.     {
  1097.     _asm
  1098.         {
  1099.         mov    dx,0x3DA
  1100.         WR1:
  1101.         in    al,dx
  1102.         test al,8
  1103.         jz    WR1  
  1104.         WR2:
  1105.         in    al,dx
  1106.         test al,8
  1107.         jnz WR2
  1108.         }
  1109.     }
  1110.     
  1111. /***********************************/
  1112. /* Objects and classes for buttons */
  1113. /***********************************/
  1114. class Base
  1115.     {
  1116.     public:
  1117.         virtual void ButtonFunction(int Data) = 0;
  1118.     };
  1119.  
  1120. class Chan0Pan : public Base
  1121.     { 
  1122.     public:
  1123.         void ButtonFunction(int Data)    
  1124.             {
  1125.             Channel[0].Pan = 255-Data;
  1126.             long TempPan = Channel[0].Pan;
  1127.             TempPan <<= 24L;
  1128.             if(Channel[0].FirstNote == 0)
  1129.                 AWE32RegDW(0xC0+Channel[0].AWE32Chan,0x620,TempPan | Channel[0].LoopStart);
  1130.             }
  1131.     };                   
  1132. class Chan1Pan : public Base
  1133.     { 
  1134.     public:
  1135.         void ButtonFunction(int Data)    
  1136.             {
  1137.             Channel[1].Pan = 255-Data;
  1138.             long TempPan = Channel[1].Pan;
  1139.             TempPan <<= 24L;
  1140.             if(Channel[1].FirstNote == 0)
  1141.                 AWE32RegDW(0xC0+Channel[1].AWE32Chan,0x620,TempPan | Channel[1].LoopStart);
  1142.             }
  1143.     };                   
  1144. class Chan2Pan : public Base
  1145.     { 
  1146.     public:
  1147.         void ButtonFunction(int Data)    
  1148.             {
  1149.             Channel[2].Pan = 255-Data;
  1150.             long TempPan = Channel[2].Pan;
  1151.             TempPan <<= 24L;
  1152.             if(Channel[2].FirstNote == 0)
  1153.                 AWE32RegDW(0xC0+Channel[2].AWE32Chan,0x620,TempPan | Channel[2].LoopStart);
  1154.             }
  1155.     };                   
  1156. class Chan3Pan : public Base
  1157.     { 
  1158.     public:
  1159.         void ButtonFunction(int Data)    
  1160.             {
  1161.             Channel[3].Pan = 255-Data;
  1162.             long TempPan = Channel[3].Pan;
  1163.             TempPan <<= 24L;
  1164.             if(Channel[3].FirstNote == 0)
  1165.                 AWE32RegDW(0xC0+Channel[3].AWE32Chan,0x620,TempPan | Channel[3].LoopStart);
  1166.             }
  1167.     };    
  1168. class AWE32MVolume : public Base
  1169.     {
  1170.     public:
  1171.         void ButtonFunction(int Data)
  1172.             {                            
  1173.             int Volume = (Data/2)*8;
  1174.             _outp(AWE32Base-0x400+4,0x30);
  1175.             _outp(AWE32Base-0x400+5,Volume);
  1176.             _outp(AWE32Base-0x400+4,0x31);
  1177.             _outp(AWE32Base-0x400+5,Volume);
  1178.             }
  1179.     };
  1180. class AWE32Volume : public Base
  1181.     {
  1182.     public:
  1183.         void ButtonFunction(int Data)
  1184.             {                            
  1185.             int Volume = (Data/2)*8;
  1186.             _outp(AWE32Base-0x400+4,0x34);
  1187.             _outp(AWE32Base-0x400+5,Volume);
  1188.             _outp(AWE32Base-0x400+4,0x35);
  1189.             _outp(AWE32Base-0x400+5,Volume);
  1190.             }
  1191.     };
  1192. class AWE32Bass : public Base
  1193.     {
  1194.     public:
  1195.         void ButtonFunction(int Data)
  1196.             {                            
  1197.             int Volume = (Data/2)*8;
  1198.             _outp(AWE32Base-0x400+4,0x46);
  1199.             _outp(AWE32Base-0x400+5,Volume);
  1200.             _outp(AWE32Base-0x400+4,0x47);
  1201.             _outp(AWE32Base-0x400+5,Volume);
  1202.             }
  1203.     };
  1204. class AWE32Treble : public Base
  1205.     {
  1206.     public:
  1207.         void ButtonFunction(int Data)
  1208.             {                            
  1209.             int Volume = (Data/2)*8;
  1210.             _outp(AWE32Base-0x400+4,0x44);
  1211.             _outp(AWE32Base-0x400+5,Volume);
  1212.             _outp(AWE32Base-0x400+4,0x45);
  1213.             _outp(AWE32Base-0x400+5,Volume);
  1214.             }
  1215.     };
  1216. class AWE32Reverb : public Base
  1217.     {
  1218.     public:
  1219.         void ButtonFunction(int Data)
  1220.             {
  1221.             Reverb = Data*4;
  1222.             }
  1223.     };
  1224. class AWE32Chorus : public Base
  1225.     {
  1226.     public:
  1227.         void ButtonFunction(int Data)
  1228.             {                            
  1229.             Chorus = Data*4;
  1230.             }
  1231.     };
  1232.     
  1233. class Button
  1234.     {
  1235.     public:
  1236.         Base* FunctionPTR;
  1237.         virtual void ButtonDown(int MouseX,int MouseY) = 0;
  1238.         virtual void ButtonUp() = 0;
  1239.         virtual void ButtonMov(int MouseX,int MouseY) = 0;
  1240.         virtual int CheckButton(int MouseX,int MouseY) = 0;
  1241.         virtual void DrawButton(int Status) = 0;
  1242.     };
  1243.  
  1244. class BigButton : public Button
  1245.     {
  1246.     private:
  1247.         int xLoc,yLoc;
  1248.         int SlideLen;
  1249.         int Height,Width;
  1250.         int SlidePos;
  1251.         int xDown,yDown;
  1252.     public:  
  1253.         BigButton(int x,int y,int l)
  1254.             {
  1255.             xLoc = x;
  1256.             yLoc = y;
  1257.             SlideLen = l;
  1258.             Height = 19;
  1259.             Width = SlideLen + 12;
  1260.             }
  1261.         void ButtonDown(int MouseX,int MouseY)
  1262.             {
  1263.             SetMouseXLimits(MouseX,MouseX);
  1264.             SetMouseYLimits(MouseY,MouseY);
  1265.             }
  1266.         void ButtonUp()
  1267.             {
  1268.             SetMouseYLimits(0,479);
  1269.             SetMouseXLimits(0,639);
  1270.             }
  1271.         int CheckButton(int MouseX,int MouseY)
  1272.             {
  1273.             if(MouseX > (xLoc*8))
  1274.                 if(MouseX < (xLoc*8+128))
  1275.                     if(MouseY > (yLoc*16))
  1276.                         if(MouseY < (yLoc*16+128))
  1277.                             return 1;
  1278.             return 0;
  1279.             }
  1280.         void DrawButton(int Status)
  1281.             {
  1282.             
  1283.             }
  1284.     };
  1285.     
  1286. class VSlideButton : public Button
  1287.     {
  1288.     private:
  1289.         int xLoc,yLoc;
  1290.         int SlideLen;
  1291.         int Height,Width;
  1292.         int SlidePos;
  1293.         int xDown,yDown;
  1294.     public:
  1295.         VSlideButton(int x,int y,int l)                                    // Constructor
  1296.             {               
  1297.             xLoc = x;
  1298.             yLoc = y;
  1299.             SlideLen = l;
  1300.             Height = 19;
  1301.             Width = SlideLen + 12;
  1302.             }       
  1303.         void ButtonDown(int MouseX,int MouseY)
  1304.             {
  1305.             xDown = MouseX;
  1306.             yDown = MouseY;
  1307.             HideMouseCursor();
  1308.             SetMouseYLimits(MouseY-SlideLen+SlidePos,MouseY+SlidePos);
  1309.             SetMouseXLimits(MouseX,MouseX);
  1310.             }       
  1311.         void ButtonUp()
  1312.             {
  1313.             ShowMouseCursor();
  1314.             SetMouseYLimits(0,479);
  1315.             SetMouseXLimits(0,639);
  1316.             }
  1317.         void ButtonMov(int MouseX,int MouseY)
  1318.             {
  1319.             int Status = SlideLen-SlidePos;
  1320.             WaitRetrace();
  1321.             
  1322.             _setcolor(7);
  1323.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+Status+1,xLoc+7,yLoc+Status+10);
  1324.             _rectangle_w(_GFILLINTERIOR,xLoc+12,yLoc+Status+1,xLoc+17,yLoc+Status+10);
  1325.             _setcolor(0);
  1326.             _rectangle_w(_GFILLINTERIOR,xLoc+9,yLoc+Status+1,xLoc+10,yLoc+Status+10);
  1327.             _setcolor(15);
  1328.             _rectangle_w(_GFILLINTERIOR,xLoc+11,yLoc+Status+1,xLoc+11,yLoc+Status+10);
  1329.             if(Status == SlideLen)
  1330.                 _rectangle_w(_GFILLINTERIOR,xLoc+8,yLoc+Status+10,xLoc+10,yLoc+Status+10);
  1331.             _setcolor(10);
  1332.             _rectangle_w(_GFILLINTERIOR,xLoc+8,yLoc+Status+1,xLoc+8,yLoc+Status+10);
  1333.             if(Status == 0)
  1334.                 _rectangle_w(_GFILLINTERIOR,xLoc+9,yLoc+1,xLoc+11,yLoc+1);    
  1335.             
  1336.             SlidePos += yDown - MouseY;
  1337.             Status = SlideLen-SlidePos;
  1338.             
  1339.             _setcolor(0);
  1340.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+1+Status,xLoc+2,yLoc+Status+10);
  1341.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+1+Status,xLoc+17,yLoc+Status+1);
  1342.             _rectangle_w(_GFILLINTERIOR,xLoc+17,yLoc+1+Status,xLoc+17,yLoc+Status+10);
  1343.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+Status+10,xLoc+17,yLoc+Status+10);
  1344.                 
  1345.             _setcolor(7);
  1346.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+4,xLoc+14,yLoc+Status+7);
  1347.                 
  1348.             _setcolor(15);
  1349.             _rectangle_w(_GFILLINTERIOR,xLoc+3,yLoc+Status+2,xLoc+4,yLoc+Status+9);
  1350.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+2,xLoc+16,yLoc+Status+3);
  1351.                 
  1352.             _setcolor(10);
  1353.             _rectangle_w(_GFILLINTERIOR,xLoc+16,yLoc+Status+2,xLoc+16,yLoc+Status+9);
  1354.             _rectangle_w(_GFILLINTERIOR,xLoc+15,yLoc+Status+3,xLoc+15,yLoc+Status+9);
  1355.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+8,xLoc+14,yLoc+Status+8);
  1356.             _rectangle_w(_GFILLINTERIOR,xLoc+4,yLoc+Status+9,xLoc+14,yLoc+Status+9);
  1357.             
  1358.             yDown = MouseY;
  1359.             
  1360.             FunctionPTR->ButtonFunction(SlidePos);
  1361.             }
  1362.             
  1363.         int CheckButton(int MouseX,int MouseY)
  1364.             {
  1365.             if(MouseX >= (xLoc+2))
  1366.                 if(MouseX <= (xLoc+17))
  1367.                     if(MouseY >= (yLoc+1+SlideLen-SlidePos))
  1368.                         if(MouseY <= (yLoc+10+SlideLen-SlidePos))
  1369.                             {
  1370.                             xDown = MouseX;
  1371.                             yDown = MouseY;
  1372.                             return 1;
  1373.                             }
  1374.             return 0;
  1375.             }
  1376.         void DrawButton(int Status)
  1377.             {
  1378.             SlidePos = Status;
  1379.             Status = SlideLen-Status;
  1380.             _setcolor(15);                                          // White
  1381.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc,xLoc,yLoc+SlideLen+10);                    
  1382.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc,xLoc+18,yLoc);
  1383.             _rectangle_w(_GFILLINTERIOR,xLoc+11,yLoc+2,xLoc+11,yLoc+SlideLen+10);
  1384.             _rectangle_w(_GFILLINTERIOR,xLoc+8,yLoc+SlideLen+11,xLoc+10,yLoc+SlideLen+10);
  1385.             _setcolor(7);                                           // Grey
  1386.             _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+1,xLoc+7,yLoc+SlideLen+10);                    
  1387.             _rectangle_w(_GFILLINTERIOR,xLoc+12,yLoc+1,xLoc+19,yLoc+SlideLen+10);
  1388.     
  1389.             _setcolor(10);                                            // Dark grey
  1390.             _rectangle_w(_GFILLINTERIOR,xLoc+19,yLoc,xLoc+19,yLoc+SlideLen+11);
  1391.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc+SlideLen+11,xLoc+19,yLoc+SlideLen+11);
  1392.             _rectangle_w(_GFILLINTERIOR,xLoc+8,yLoc+1,xLoc+8,yLoc+SlideLen+9);
  1393.             _rectangle_w(_GFILLINTERIOR,xLoc+9,yLoc+1,xLoc+11,yLoc+1);
  1394.                 
  1395.             _setcolor(0);
  1396.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+1+Status,xLoc+2,yLoc+Status+10);
  1397.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+1+Status,xLoc+17,yLoc+Status+1);
  1398.             _rectangle_w(_GFILLINTERIOR,xLoc+17,yLoc+1+Status,xLoc+17,yLoc+Status+10);
  1399.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+Status+10,xLoc+17,yLoc+Status+10);
  1400.                 
  1401.             _setcolor(7);
  1402.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+4,xLoc+14,yLoc+Status+7);
  1403.                 
  1404.             _setcolor(15);
  1405.             _rectangle_w(_GFILLINTERIOR,xLoc+3,yLoc+Status+2,xLoc+4,yLoc+Status+9);
  1406.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+2,xLoc+16,yLoc+Status+3);
  1407.                 
  1408.             _setcolor(10);
  1409.             _rectangle_w(_GFILLINTERIOR,xLoc+16,yLoc+Status+2,xLoc+16,yLoc+Status+9);
  1410.             _rectangle_w(_GFILLINTERIOR,xLoc+15,yLoc+Status+3,xLoc+15,yLoc+Status+9);
  1411.             _rectangle_w(_GFILLINTERIOR,xLoc+5,yLoc+Status+8,xLoc+14,yLoc+Status+8);
  1412.             _rectangle_w(_GFILLINTERIOR,xLoc+4,yLoc+Status+9,xLoc+14,yLoc+Status+9);
  1413.             }
  1414.     };
  1415.     
  1416. class HSlideButton : public Button
  1417.     { 
  1418.     private:
  1419.         int xLoc,yLoc;
  1420.         int SlideLen;
  1421.         int Height,Width;
  1422.         int SlidePos;
  1423.         int xDown,yDown;
  1424.     public:
  1425.         HSlideButton(int x,int y,int l)                                    // Constructor
  1426.             {               
  1427.             xLoc = x;
  1428.             yLoc = y;
  1429.             SlideLen = l;
  1430.             Height = 19;
  1431.             Width = SlideLen + 12;
  1432.             }       
  1433.         void ButtonDown(int MouseX,int MouseY)
  1434.             {
  1435.             xDown = MouseX;
  1436.             yDown = MouseY;
  1437.             HideMouseCursor();
  1438.             SetMouseYLimits(MouseY,MouseY);
  1439.             SetMouseXLimits(MouseX-SlidePos,SlideLen-SlidePos+MouseX);
  1440.             }       
  1441.         void ButtonUp()
  1442.             {
  1443.             ShowMouseCursor();
  1444.             SetMouseYLimits(0,479);
  1445.             SetMouseXLimits(0,639);
  1446.             }
  1447.         void ButtonMov(int MouseX,int MouseY)
  1448.             {
  1449.             WaitRetrace();
  1450.             _setcolor(7);
  1451.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+1,yLoc+2,xLoc+SlidePos+10,yLoc+7);
  1452.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+1,yLoc+12,xLoc+SlidePos+10,yLoc+17);
  1453.             _setcolor(0);
  1454.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+1,yLoc+9,xLoc+SlidePos+10,yLoc+10);
  1455.             _setcolor(15);
  1456.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+1,yLoc+11,xLoc+SlidePos+10,yLoc+11);
  1457.             if(SlidePos == SlideLen)
  1458.                 _rectangle_w(_GFILLINTERIOR,xLoc+SlideLen+10,yLoc+8,xLoc+SlideLen+10,yLoc+10);
  1459.             _setcolor(10);
  1460.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+1,yLoc+8,xLoc+SlidePos+10,yLoc+8);
  1461.             if(SlidePos == 0)
  1462.                 _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+9,xLoc+1,yLoc+11);    
  1463.             
  1464.             SlidePos += MouseX - xDown;
  1465.             
  1466.             _setcolor(0);
  1467.             _rectangle_w(_GFILLINTERIOR,xLoc+1+SlidePos,yLoc+2,xLoc+10+SlidePos,yLoc+2);
  1468.             _rectangle_w(_GFILLINTERIOR,xLoc+1+SlidePos,yLoc+2,xLoc+1+SlidePos,yLoc+17);
  1469.             _rectangle_w(_GFILLINTERIOR,xLoc+1+SlidePos,yLoc+17,xLoc+10+SlidePos,yLoc+17);
  1470.             _rectangle_w(_GFILLINTERIOR,xLoc+10+SlidePos,yLoc+2,xLoc+10+SlidePos,yLoc+17);
  1471.             
  1472.             _setcolor(7);
  1473.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+4,yLoc+5,xLoc+SlidePos+7,yLoc+14);
  1474.                     
  1475.             _setcolor(15);
  1476.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+2,yLoc+3,xLoc+SlidePos+9,yLoc+4);
  1477.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+2,yLoc+5,xLoc+SlidePos+3,yLoc+16);
  1478.                     
  1479.             _setcolor(10);
  1480.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+2,yLoc+16,xLoc+SlidePos+9,yLoc+16);
  1481.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+3,yLoc+15,xLoc+SlidePos+9,yLoc+15);
  1482.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+8,yLoc+5,xLoc+SlidePos+8,yLoc+14);
  1483.             _rectangle_w(_GFILLINTERIOR,xLoc+SlidePos+9,yLoc+4,xLoc+SlidePos+9,yLoc+14);
  1484.             
  1485.             xDown = MouseX;
  1486.  
  1487.             FunctionPTR->ButtonFunction(SlidePos);
  1488.             }
  1489.             
  1490.         int CheckButton(int MouseX,int MouseY)
  1491.             {
  1492.             if(MouseX >= (xLoc+1+SlidePos))
  1493.                 if(MouseX <= (xLoc+10+SlidePos))
  1494.                     if(MouseY >= (yLoc+2))
  1495.                         if(MouseY <= (yLoc+17))
  1496.                             {
  1497.                             xDown = MouseX;
  1498.                             yDown = MouseY;
  1499.                             return 1;
  1500.                             }
  1501.             return 0;
  1502.             }
  1503.         void DrawButton(int Status)
  1504.             {
  1505.             SlidePos = Status;
  1506.             _setcolor(15);                                          // White
  1507.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc,xLoc+SlideLen+10,yLoc);                    
  1508.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc,xLoc,yLoc+18);
  1509.             _rectangle_w(_GFILLINTERIOR,xLoc+2,yLoc+11,xLoc+SlideLen+10,yLoc+11);
  1510.             _rectangle_w(_GFILLINTERIOR,xLoc+SlideLen+11,yLoc+8,xLoc+SlideLen+10,yLoc+10);
  1511.             _setcolor(7);                                           // Grey
  1512.             _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+1,xLoc+SlideLen+10,yLoc+7);                    
  1513.             _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+12,xLoc+SlideLen+10,yLoc+19);
  1514.     
  1515.             _setcolor(10);                                            // Dark grey
  1516.             _rectangle_w(_GFILLINTERIOR,xLoc,yLoc+19,xLoc+SlideLen+11,yLoc+19);
  1517.             _rectangle_w(_GFILLINTERIOR,xLoc+SlideLen+11,yLoc,xLoc+SlideLen+11,yLoc+19);
  1518.             _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+8,xLoc+SlideLen+9,yLoc+8);
  1519.             _rectangle_w(_GFILLINTERIOR,xLoc+1,yLoc+9,xLoc+1,yLoc+11);
  1520.                 
  1521.             _setcolor(0);
  1522.             _rectangle_w(_GFILLINTERIOR,xLoc+1+Status,yLoc+2,xLoc+10+Status,yLoc+2);
  1523.             _rectangle_w(_GFILLINTERIOR,xLoc+1+Status,yLoc+2,xLoc+1+Status,yLoc+17);
  1524.             _rectangle_w(_GFILLINTERIOR,xLoc+1+Status,yLoc+17,xLoc+10+Status,yLoc+17);
  1525.             _rectangle_w(_GFILLINTERIOR,xLoc+10+Status,yLoc+2,xLoc+10+Status,yLoc+17);
  1526.                 
  1527.             _setcolor(7);
  1528.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+4,yLoc+5,xLoc+Status+7,yLoc+14);
  1529.                 
  1530.             _setcolor(15);
  1531.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+2,yLoc+3,xLoc+Status+9,yLoc+4);
  1532.                 _rectangle_w(_GFILLINTERIOR,xLoc+Status+2,yLoc+5,xLoc+Status+3,yLoc+16);
  1533.                 
  1534.             _setcolor(10);
  1535.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+2,yLoc+16,xLoc+Status+9,yLoc+16);
  1536.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+3,yLoc+15,xLoc+Status+9,yLoc+15);
  1537.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+8,yLoc+5,xLoc+Status+8,yLoc+14);
  1538.             _rectangle_w(_GFILLINTERIOR,xLoc+Status+9,yLoc+4,xLoc+Status+9,yLoc+14);
  1539.             }
  1540.     };
  1541.  
  1542. char Palette [] = { 0x00,0x00,0x00, 0x00,0x00,0x2A, 0x00,0x2A,0x00, 0x00,0x2A,0x2A, 
  1543.                     0x2A,0x00,0x00, 0x2A,0x00,0x2A, 0x2A,0x2A,0x00, 0x2A,0x2A,0x2A,
  1544.                     0x00,0x00,0x15, 0x00,0x00,0x3F, 0x18,0x18,0x18, 0x00,0x2A,0x3F,
  1545.                     0x2A,0x00,0x15, 0x2A,0x00,0x3F, 0x2A,0x2A,0x3F, 0x3F,0x3F,0x3F };
  1546. char TempPalette[48];
  1547.  
  1548. void FadeIn()
  1549.     {
  1550.     for (int i=0; i<48; i++)
  1551.         TempPalette[i] = 0;
  1552.     
  1553.     for(int k=0; k<64; k++)
  1554.         {    
  1555.         for(int i=0; i<48; i++)
  1556.             {
  1557.             if(Palette[i] != TempPalette[i])
  1558.                 TempPalette[i]++;
  1559.             }
  1560.         _outp(0x3C8,0);
  1561.         for(i=0; i<16; i++)
  1562.             {
  1563.             _outp(0x3C9,TempPalette[i*3]);
  1564.             _outp(0x3C9,TempPalette[i*3+1]);
  1565.             _outp(0x3C9,TempPalette[i*3+2]);
  1566.             }
  1567.         WaitRetrace();
  1568.         }
  1569.     }
  1570.     
  1571. void PlayScreen()
  1572.     {
  1573.     unsigned int MouseX,MouseY;
  1574.     
  1575.     _setcolor(15);
  1576.     _settextposition(1,28);
  1577.     _outtext("Omega ModPlayer for AWE32");
  1578.     _settextposition(2,28);
  1579.     _outtext("-------------------------");
  1580.     
  1581.     _settextposition(4,5);
  1582.     _outtext("Playing: ");
  1583.     _outtext(Header->SongName);
  1584.     _settextposition(4,35);
  1585.     _outtext("Pattern: ");
  1586.     _settextposition(4,46);
  1587.     _outtext("/");
  1588.     TempSTR[0] = (Header->SongLength-1)/10+48;
  1589.     TempSTR[1] = ((Header->SongLength-1) - ((Header->SongLength-1)/10)*10)+48;
  1590.     TempSTR[2] = 0;
  1591.     _outtext(TempSTR);
  1592.     
  1593.     _settextposition(4,55);
  1594.     _outtext("Row: ");
  1595.     
  1596.     _settextposition(9,4);
  1597.     _outtext("Channel 1");
  1598.     _settextposition(11,4);
  1599.     _outtext("Channel 2");
  1600.     _settextposition(13,4);
  1601.     _outtext("Channel 3");
  1602.     _settextposition(15,4);
  1603.     _outtext("Channel 4");
  1604.     
  1605.     _settextposition(7,30);
  1606.     _outtext("Pan");
  1607.     
  1608.     Button* Buttons[10];
  1609.     Buttons[0] = new HSlideButton(125,128,255);
  1610.     Buttons[1] = new HSlideButton(125,160,255);
  1611.     Buttons[2] = new HSlideButton(125,192,255);
  1612.     Buttons[3] = new HSlideButton(125,224,255);
  1613.     Buttons[4] = new VSlideButton(45,280,63);
  1614.     Buttons[5] = new VSlideButton(170,280,63);
  1615.     Buttons[6] = new VSlideButton(270,280,63);
  1616.     Buttons[7] = new VSlideButton(320,280,63);
  1617.     Buttons[8] = new VSlideButton(390,280,63);
  1618.     Buttons[9] = new VSlideButton(440,280,63);
  1619.     Buttons[0]->FunctionPTR = new Chan0Pan;
  1620.     Buttons[1]->FunctionPTR = new Chan1Pan;
  1621.     Buttons[2]->FunctionPTR = new Chan2Pan;
  1622.     Buttons[3]->FunctionPTR = new Chan3Pan;
  1623.     Buttons[4]->FunctionPTR = new AWE32MVolume;
  1624.     Buttons[5]->FunctionPTR = new AWE32Volume;
  1625.     Buttons[6]->FunctionPTR = new AWE32Bass;
  1626.     Buttons[7]->FunctionPTR = new AWE32Treble;
  1627.     Buttons[8]->FunctionPTR = new AWE32Reverb;
  1628.     Buttons[9]->FunctionPTR = new AWE32Chorus;
  1629.  
  1630.     Buttons[0]->DrawButton(0);
  1631.     Buttons[1]->DrawButton(255);
  1632.     Buttons[2]->DrawButton(255);
  1633.     Buttons[3]->DrawButton(0);
  1634.     
  1635.     Buttons[4]->DrawButton((MainVolumeL+7)/4-1);
  1636.     Buttons[5]->DrawButton((SynthVolumeL+7)/4-1);
  1637.     Buttons[6]->DrawButton(BassL*4L/15-1);
  1638.     Buttons[7]->DrawButton(TrebleL*4L/15-1);
  1639.     Buttons[8]->DrawButton(Reverb/4);
  1640.     Buttons[9]->DrawButton(Chorus/4);
  1641.     
  1642.        _settextposition(24,2);
  1643.     _outtext("Main Volume");
  1644.        _settextposition(24,18);
  1645.     _outtext("Synth Volume");
  1646.     
  1647.        _settextposition(24,34);
  1648.     _outtext("Bass");
  1649.        _settextposition(24,40);
  1650.     _outtext("Treble");
  1651.        _settextposition(24,48);
  1652.     _outtext("Reverb");
  1653.        _settextposition(24,56);
  1654.     _outtext("Chorus");
  1655.     
  1656.  
  1657.     InitMouse();
  1658.     ShowMouseCursor();
  1659.     
  1660.     FadeIn();
  1661.     
  1662.     OldIRQ0 = _dos_getvect(IRQ0);
  1663.     _disable();
  1664.     _outp(0x40,0x38);                                        // Set up timer to interrupt 50 times/sec
  1665.     _outp(0x40,0x5D);
  1666.     _outp(0x43,0);
  1667.     _dos_setvect(IRQ0,Beat);
  1668.     _enable();
  1669.     
  1670.  
  1671.     int key;
  1672.     while( key != 27)
  1673.         {
  1674.         if(_kbhit() != 0)
  1675.             key = _getch();
  1676.         
  1677.         if((GetMousePos(&MouseX,&MouseY)&1))                        // Is left mouse button pressed?
  1678.             for(int i=0; i<10; i++)
  1679.                 if(Buttons[i]->CheckButton(MouseX,MouseY))          // Check all buttons
  1680.                     {
  1681.                     Buttons[i]->ButtonDown(MouseX,MouseY);
  1682.                     
  1683.                     while(GetMouseButtonStat()&1)
  1684.                         if(MouseMov(&MouseX,&MouseY) == 1)
  1685.                             Buttons[i]->ButtonMov(MouseX,MouseY);
  1686.                     
  1687.                     Buttons[i]->ButtonUp();
  1688.                     break;
  1689.                     }
  1690.         }
  1691.     }
  1692.     
  1693.     
  1694. void Sleep(clock_t wait)
  1695.     {
  1696.     clock_t goal;
  1697.     
  1698.     goal = wait+clock();
  1699.     while(goal > clock());
  1700.     }
  1701.     
  1702. void SaveMixer()
  1703.     {
  1704.     _outp(AWE32Base-0x400+4,0x30);                            // Save main volume
  1705.     MainVolumeL = _inp(AWE32Base-0x400+5);
  1706.     _outp(AWE32Base-0x400+4,0x31);
  1707.     MainVolumeR = _inp(AWE32Base-0x400+5);                        
  1708.     
  1709.     _outp(AWE32Base-0x400+4,0x34);                          // Save synth volume
  1710.     SynthVolumeL = _inp(AWE32Base-0x400+5);
  1711.     _outp(AWE32Base-0x400+4,0x35);
  1712.     SynthVolumeR = _inp(AWE32Base-0x400+5);
  1713.     
  1714.     _outp(AWE32Base-0x400+4,0x44);                          // Save treble setting
  1715.     TrebleL = _inp(AWE32Base-0x400+5);
  1716.     _outp(AWE32Base-0x400+4,0x45);
  1717.     TrebleR = _inp(AWE32Base-0x400+5);
  1718.     
  1719.     _outp(AWE32Base-0x400+4,0x46);                          // Save bass setting
  1720.     BassL = _inp(AWE32Base-0x400+5);
  1721.     _outp(AWE32Base-0x400+4,0x47);
  1722.     BassR = _inp(AWE32Base-0x400+5);
  1723.     }
  1724. void RestoreMixer()
  1725.     {
  1726.     _outp(AWE32Base-0x400+4,0x30);                            // Restore main volume
  1727.     _outp(AWE32Base-0x400+5,MainVolumeL);
  1728.     _outp(AWE32Base-0x400+4,0x31);
  1729.     _outp(AWE32Base-0x400+5,MainVolumeR);
  1730.     
  1731.     _outp(AWE32Base-0x400+4,0x34);                          // Restore synth volume
  1732.     _outp(AWE32Base-0x400+5,SynthVolumeL);
  1733.     _outp(AWE32Base-0x400+4,0x35);
  1734.     _outp(AWE32Base-0x400+5,SynthVolumeR);
  1735.     
  1736.     _outp(AWE32Base-0x400+4,0x44);                          // Restore treble setting
  1737.     _outp(AWE32Base-0x400+5,TrebleL);
  1738.     _outp(AWE32Base-0x400+4,0x45);
  1739.     _outp(AWE32Base-0x400+5,TrebleR);
  1740.     
  1741.     _outp(AWE32Base-0x400+4,0x46);                          // Restore bass setting
  1742.     _outp(AWE32Base-0x400+5,BassL);
  1743.     _outp(AWE32Base-0x400+4,0x47);
  1744.     _outp(AWE32Base-0x400+5,BassR);
  1745.     }    
  1746.     
  1747. /*****************/
  1748. /* Main function */
  1749. /*****************/                          
  1750. void main(int argc,char* argv[], char* envp[])
  1751.     { 
  1752.     char* Bug = argv[1];
  1753.     
  1754.     _clearscreen(_GCLEARSCREEN);
  1755.     
  1756.     if(AWE32Detect() != 0)
  1757.         ExitWithError("Creative Labs Sound Blaster AWE32 not found");
  1758.         
  1759.     AWE32Init();
  1760.     CheckDRAM();
  1761.     if(DRAMSize == 0)
  1762.         ExitWithError("Your AWE32 doesn't have any RAM");
  1763.     
  1764.     SaveMixer();
  1765.     SetReverbEffect(Room1);
  1766.        SetChorusEffect(Chorus3);
  1767.     
  1768.     if(argc != 2)                                            // first argument is our program                                            
  1769.         ExitWithError("Usage: awe32mod example.mod");       // second argument is sound file
  1770.         
  1771.     if((Soundfile = fopen(Bug,"rb")) == NULL)                // open sound file
  1772.         ExitWithError("Could not open file");                  // file not found
  1773.         
  1774.     fread(Header,1,sizeof(SongInfo),Soundfile);              // read header
  1775.     if(strncmp(Header->FileID,"M.K.",4))
  1776.         ExitWithError("File not a 31 sample 4 channel sound module");
  1777.         
  1778.     cout << "SoundBlaster AWE32 found at " << hex << AWE32Base << "H";
  1779.     cout << " with " << dec << DRAMSize << "kB onboard DRAM" << endl;
  1780.     cout << endl;
  1781.     
  1782.     for(int k=0; k<128; k++)
  1783.         {
  1784.         if (Header->PattSeq[k] > NumberOfPatterns)
  1785.             NumberOfPatterns = Header->PattSeq[k];            // get number of patterns in song
  1786.         }
  1787.     
  1788.     NumberOfPatterns++;
  1789.     
  1790.     for(k=0; k<NumberOfPatterns; k++)
  1791.         {
  1792.         Patt[k] = new Pattern;
  1793.         fread(Patt[k],1,1024,Soundfile);
  1794.         }    
  1795.         
  1796.     DecodePatterns();
  1797.                  
  1798.     LoadInstruments();
  1799.     Sleep(1500);
  1800.     
  1801.     Channel[0].Pan = Left;
  1802.     Channel[1].Pan = Right; 
  1803.     Channel[2].Pan = Right;  
  1804.     Channel[3].Pan = Left;   
  1805.     for(i=0; i<4; i++)        
  1806.         {
  1807.         Channel[i].Status = 0;
  1808.         Channel[i].FirstNote = 1;
  1809.         Channel[i].VolumeSlide = 0;
  1810.         Channel[i].PitchSlide = 0;
  1811.         Channel[i].MaxSlide = 113;
  1812.         Channel[i].MinSlide = 856;
  1813.         Channel[i].ArpeggioD[0] = 0;
  1814.         }
  1815.     CalcLogTable();
  1816.                      
  1817.     _setvideomode(_VRES16COLOR);                           // 640*480 in 256 colors
  1818.     _outp(0x3C8,0);
  1819.     for(i=0; i<48; i++)
  1820.         _outp(0x3C9,0);
  1821.     Sleep(750);
  1822.  
  1823.     PlayScreen();
  1824.             
  1825.     _disable();                                                // Return timer to normal operation
  1826.     for(i=0; i<4; i++)
  1827.         if(Channel[i].FirstNote == 0)
  1828.             NoteOff(Channel[i].AWE32Chan);
  1829.             
  1830.     _outp(0x40,0);
  1831.     _outp(0x40,0);
  1832.     _outp(0x43,0);
  1833.     _dos_setvect(IRQ0,OldIRQ0);
  1834.                                 
  1835.     regs.x.ax = 2;
  1836.     int86(0x33,®s,®s);
  1837.     _setvideomode(_DEFAULTMODE);                                // Return to same video mode  
  1838.     RestoreMixer();
  1839.     }