home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / mtracker.zip / MTRACKER.C < prev    next >
C/C++ Source or Header  |  1991-09-28  |  72KB  |  2,398 lines

  1. /* NOTE! Remember to LZEXE after compilation! It will reduce EXE size by
  2.    more than half...                                                      */
  3.  
  4. #ifndef __COMPACT__
  5. #error Compile with COMPACT memory model!
  6. #endif
  7.  
  8. #include <alloc.h>
  9. #include <conio.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <dos.h>
  14. #include <dir.h>
  15.  
  16. #define MAXFILES 200
  17. #define MAXDIRS 100
  18.  
  19. struct STMHeader {
  20.            char name[20];
  21.            char tnam[8];
  22.            char d1a;
  23.            char typ; /* 1 = STS, 2 = STM, 5 = MTS, 6 = MTM */
  24.            unsigned int ver;
  25.            unsigned char tempo;
  26.            unsigned char patnum;
  27.            unsigned char volume;
  28.            char reserved[13];
  29.            struct {
  30.                 char name[13];
  31.                 char disk;
  32.                 char ch;  /* Reserved in STM/STS */
  33.                 unsigned char prg; /* Reserved in STM/STS */
  34.                 unsigned int length;
  35.                 unsigned int loops;
  36.                 unsigned int loope;
  37.                 unsigned char volume;
  38.                 unsigned char pan; /* Reserved in STM/STS */
  39.                 unsigned int rate;
  40.                 unsigned char nt;  /* Reserved in STM/STS */
  41.                 char reserved[5];
  42.               } inst[31];
  43.          } stm;
  44.  
  45. struct BPMHeader {
  46.            char name[32];
  47.            char typ; /* File type: bit 0-5 = file version
  48.                                    bit 6   = note display
  49.                                    bit 7   = song (0) / module (1) */
  50.            char tnam[8];
  51.            unsigned int tempo_hi;
  52.            unsigned int tempo_lo;
  53.            unsigned ihertz;
  54.            unsigned int signature; /* high byte / low byte */
  55.            struct {
  56.                 char name[12];
  57.                 unsigned int length;
  58.                 unsigned char volume;
  59.                 unsigned int loops;
  60.                 unsigned int loope;
  61.                 unsigned int dummy;
  62.               } inst[32];
  63.            char dummy[16];
  64.            unsigned char patnum;
  65.          } bpm;
  66.  
  67. struct MODHeader {
  68.            char name[20];
  69.            struct {
  70.                 char name[22];
  71.                 unsigned int length;  /* Number of words, not bytes */
  72.                 char finetune;
  73.                 unsigned char volume; /* 0 .. 64 */
  74.                 unsigned int loops;   /* Start pos in words from start */
  75.                 unsigned int loopl;   /* Loop length in words */
  76.               } inst[31];
  77.            unsigned char songlength;  /* Number of patterns in song
  78.            unsigned char dummy;       /* Restart byte */
  79.          } mod;
  80.  
  81. unsigned char systemarea[] = { 0xF0, 65, 16, 22, 18,
  82.                                0x10, 0, 1, /* System Area address */
  83.                                2,   /* [8]  Reverb Mode (0,1,2,3) */
  84.                                5,   /* [9]  Reverb Time (0..7) */
  85.                                4,   /* [10] Reverb Level (0..7) */
  86.                                9, 1, 8, 3, 2, 0, 0, 0, 9, /* Partial Resrv */
  87.                                1, 2, 3, 4, 5, 6, 7, 8, 9, /* MIDI channels */
  88.                                90,  /* [29] Master Volume */
  89.                                0,   /* [30] Checksum */
  90.                                0xF7 };
  91. unsigned char sampleheader[19] = { 0xF0,0x7E,1,
  92.                    0,    /* [3] = sample number */
  93.                    0,12, /* 12 bits per word */
  94.                    0x31,0x63,0x7, /* sampling period in nS */
  95.                    0,0,0, /* [9]  = total words in sample */
  96.                    0,0,0, /* [12] = loop start */
  97.                    0,0,0, /* [15] = loop end */
  98.                    0 };   /* 0 = looping mode */
  99. unsigned char sampleblock[122];
  100. unsigned char sampledata[319] =  { 0xF0,0x47,0,10,65,0,0,
  101.                                    24,0,0,0,0,0,60,1,
  102.                                    24,0,0,0,0,0,60,1,
  103.                                    24,0,0,0,0,0,60,1,
  104.                                    24,0,0,0,0,0,60,1,
  105.                                    24,0,0,0,0,0,60,1,
  106.                                    24,0,0,0,0,0,60,1,
  107.                                    24,0,0,0,0,0,60,1,
  108.                                    24,0,0,0,0,0,60,1,
  109.                                    24,0,0,0,0,0,60,1,
  110.                                    24,0,0,0,0,0,60,1,
  111.                                    24,0,0,0,0,0,60,1,
  112.                                    24,0,0,0,0,0,60,1,
  113.                                    24,0,0,0,0,0,60,1,
  114.                                    24,0,0,0,0,0,60,1,
  115.                                    24,0,0,0,0,0,60,1,
  116.                                    24,0,0,0,0,0,60,1,
  117.                                    24,0,0,0,0,0,60,1,
  118.                                    24,0,0,0,0,0,60,1,
  119.                                    24,0,0,0,0,0,60,1,
  120.                                    24,0,0,0,0,0,60,1,
  121.                                    24,0,0,0,0,0,60,1,
  122.                                    24,0,0,0,0,0,60,1,
  123.                                    24,0,0,0,0,0,60,1,
  124.                                    24,0,0,0,0,0,60,1,
  125.                                    24,0,0,0,0,0,60,1,
  126.                                    24,0,0,0,0,0,60,1,
  127.                                    24,0,0,0,0,0,60,1,
  128.                                    24,0,0,0,0,0,60,1,
  129.                                    24,0,0,0,0,0,60,1,
  130.                                    24,0,0,0,0,0,60,1,
  131.                                    24,0,0,0,0,0,60,1,
  132.                                    24,0,0,0,0,0,60,1,
  133.                    0,0,      /* undefined */
  134.                    1,0,      /* [265] = loop mode */
  135.                    0,0,0,0,  /* start point */
  136.                    0,0,0,0,  /* undefined */
  137.                    0,0,0,0,  /* [275] = endpoint */
  138.                    0,0,0,0,  /* [279] = loop point */
  139.                    0,0,0,0,  /* undefined */
  140.                    0,0,      /* LFO speed, 0 = 2 Hz */
  141.                    0,0,      /* LFO depth */
  142.                    0,0,      /* LFO delay */
  143.                    99,0,     /* filter */
  144.                    30,0,     /* release */
  145.                    99,0,     /* loudness */
  146.                    0,0,      /* [299] fine tuning */
  147.                    60,0,     /* nominal rec pitch */
  148.                    60,0,     /* [303] rec bandwidth */
  149.                    0,0,      /* forward */
  150.                    0,0,      /* velocity/filter */
  151.                    50,0,     /* velocity/loudness */
  152.                    0,0,      /* velocity/release */
  153.                    0,0,0,0,  /* undefined */
  154.                    0,0xF7 }; /* [317] = checksum of 7-316 */
  155. unsigned char sampleparam[319];
  156.  
  157. unsigned samplerates[42] = { 3920,4160,4400,4670,4940,5240,
  158.                  5550,5880,6230,6600,6990,7410,
  159.                  7849,8315,8810,9330,9890,10480,
  160.                  11100,11760,12460,13200,13990,
  161.                  14820,15697,16630,17620,18670,
  162.                  19780,20950,22200,23520,24920,
  163.                  26400,27970,29630,31400,33260,
  164.                  35240,37340,39560,41900 };
  165.  
  166. char notes[12][3] = { " C","C#"," D","D#"," E"," F",
  167.            "F#"," G","G#"," A","A#"," B" };
  168.  
  169. typedef unsigned char PA[1024];
  170. PA *pattern[128];
  171. unsigned char orders[256];
  172. unsigned char MIDIch[31];  /* MIDI channels, values 1..16 (0=undefined) */
  173. unsigned char MIDInt[31];  /* MIDI fixed notes (0=original, >128 = transpose) */
  174. unsigned char MIDIprg[31]; /* MIDI programs (0..127) or samples (130-145) */
  175. typedef char *P;
  176. P sample[31];
  177.  
  178. unsigned int j,urpo;
  179. char defnam[13], apu[80];
  180. char defdir[64] = "C:\\SOUNDS\\ST224\\SONG\\";
  181. char defext[6] = "*.mt?";
  182. char lmode='M';
  183.  
  184. char allfiles[MAXFILES][13];
  185. char alldirs[MAXDIRS][13];
  186.  
  187.  
  188. FILE *f;
  189. int i,MPUok,AKAIok,FILEok,FILE1st,FILElkm,mx,my,mode;
  190.  
  191. struct text_info tinfo;
  192.  
  193. char scrbuf[2048];
  194.  
  195. unsigned char overalldata[33];
  196.  
  197. /* ---------------------------- Common routines -------------------------- */
  198.  
  199. void ShowError(viesti)
  200. char *viesti;
  201. {
  202.   gotoxy(3,47);
  203.   textcolor(YELLOW);
  204.   textbackground(RED);
  205.   cprintf(" %-75s",viesti);
  206.   textcolor(WHITE);
  207.   textbackground(BLUE);
  208.   return;
  209. }
  210.  
  211. /* ---------------------------- Midi routines ---------------------------- */
  212.  
  213. #define COMDPORT  0x331
  214. #define STATPORT  0x331
  215. #define DATAPORT  0x330
  216. #define DRR       0x40
  217. #define DSR       0x80
  218. #define CMD_UART  0x3F
  219. #define CMD_RESET 0xFF
  220. #define MPU_ACK   0xFE
  221. #define GET_VERS  0xAC
  222.  
  223. unsigned ticktest;
  224.  
  225. void SetTick()
  226. {
  227.   ticktest=(unsigned)peek(0x0040,0x006C);
  228.   return;
  229. }
  230.  
  231. int GoneTicks(tk)
  232. unsigned tk;
  233. {
  234.   if (ticktest+tk<(unsigned)peek(0x0040,0x006C))
  235.     return 1;
  236.   else
  237.     return 0;
  238. }
  239.  
  240. int ResetMPU()
  241. {
  242.   outportb(COMDPORT,CMD_RESET);
  243.   /* Wait until MPU acknowledges command or 220 ms gone... */
  244.   SetTick();
  245.   while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
  246.   if (inportb(DATAPORT) != MPU_ACK)
  247.     {
  248.       ShowError("MPU does not acknowledge Reset, starting in demo mode!");
  249.       return 0;
  250.     }
  251.   return 1;
  252. }
  253.  
  254. int InitMPU()
  255. {
  256.   int i,vers=0;
  257.   gotoxy(3,47);
  258.   cprintf(" %-75s","Initializing MPU-compatible midi interface...");
  259.   if (!ResetMPU()) return 0;
  260.   SetTick();
  261.   if (inportb(STATPORT) & DRR) /* If MPU is not ready to receive yet.. */
  262.     {
  263.       ShowError("MPU does not respond, starting in demo mode!");
  264.       return 0; /* MPU error */
  265.     }
  266.   /* --- Try to get firmware version --- */
  267.   outportb(COMDPORT,GET_VERS);
  268.   do {
  269.     SetTick();
  270.     while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
  271.     if (GoneTicks(4))
  272.       {
  273.     ShowError("MPU does not respond, starting in demo mode!");
  274.     return 0; /* MPU error */
  275.       }
  276.   } while ((vers=inportb(DATAPORT))==MPU_ACK);
  277.   /* --- Command MPU to Dumb UART mode --- */
  278.   outportb(COMDPORT,CMD_UART);
  279.   SetTick();
  280.   while (!GoneTicks(4) && (inportb(STATPORT) & DSR)) ;
  281.   if (GoneTicks(4) || inportb(DATAPORT) != MPU_ACK)
  282.     {
  283.       ShowError("MPU does not respond, starting in demo mode!");
  284.       return 0; /* MPU error */
  285.     }
  286.   gotoxy(3,47);
  287.   cprintf(" %-75s","MPU-interface initialized OK.");
  288.   return vers; /* MPU OK, return firmware version number. */
  289. }
  290.  
  291. void SendData(dat)
  292. unsigned char dat;
  293. {
  294.   if (!MPUok) return;
  295.   while ((inportb(STATPORT) & DRR)) /* Wait until MPU ready */ ;
  296.   outportb(DATAPORT,dat);
  297.   return;
  298. }
  299.  
  300. int ReceiveData()
  301. {
  302.   register int i=20;
  303.   while (--i && (inportb(STATPORT) & DSR)) /* Wait until char ready */ ;
  304.   if (i) return (inportb(DATAPORT));
  305.   else return(256);
  306. }
  307.  
  308. void ClearMPU() /* Clear MPU data buffer */
  309. {
  310.   if (!MPUok) return;
  311.   while (!(inportb(STATPORT) & DSR)) inportb(DATAPORT);
  312.   return;
  313. }
  314.  
  315. void SendACK() /* Sends ACK to Akai X7000 */
  316. {
  317.   SendData( 0xF0 ); /* Start of SYSEX */
  318.   SendData( 0x7E ); /* Common non-realtime code */
  319.   SendData( 0x7F ); /* ACKS */
  320.   SendData( 0xF7 ); /* End Of SYSEX */
  321. }
  322.  
  323. int WaitACK()
  324. {
  325.   unsigned char handshake[3];
  326.   register int i=0,apu;
  327.   while ((apu=ReceiveData()) != 0xF0) /* Wait for SYSEX */ ;
  328.   while (i<3)
  329.     if ((apu=ReceiveData())<256) handshake[i++]=apu;
  330.   return (handshake[1]);
  331. }
  332.  
  333. void SendAkaiEx(fun) /* Sends Akai Exclusive to X7000 */
  334. char fun;
  335. {
  336.   SendData( 0xF0 );
  337.   SendData( 0x47 ); /* Akai identifier */
  338.   SendData( 0    ); /* Midi Channel, 0..15 */
  339.   SendData( fun  ); /* 1 = Request overall settings,
  340.                5 = System Exclusive Common Enable */
  341.   SendData( 65   ); /* S700 and X7000 identifier */
  342.   SendData( 0    ); /* Sample number */
  343.   SendData( 0    );
  344.   SendData( 0xF7 );
  345. }
  346.  
  347. /* ---------------------------- Midi Interrupt Handler ------------------- */
  348.  
  349. #define INTR 0x08
  350.  
  351. void interrupt ( *oldhandler)(void);
  352. char INTord,INTpat,INTcount,INTrow,oldrow,oldord;
  353. unsigned char INTtempo, oldtempo;
  354. long INTtime,oldtime;
  355. unsigned char INTnote,INTvol,INTch,INTins,INTstop,INTloop,INTvols,
  356.               INTplaying=0,INTi,INTj,INTnotes[4][4];
  357. unsigned char INTvolumes[16]; /* Controller 7 value for each midi ch */
  358. unsigned char *INTp;
  359.  
  360. void interrupt PlayInt()
  361. {
  362.   INTtempo++;
  363.   INTcount++;
  364.   if (INTcount == 42)
  365.     {
  366.       if (!INTstop) INTtime+=55; /* 55 ms per original tick */
  367.       oldhandler(); /* Go to original if about 55 ms gone */
  368.       INTcount=0;
  369.     }
  370.   else
  371.     outportb(0x20,0x20); /* End-of-interrupt */
  372.   if (INTtempo == stm.tempo && !INTstop) /* Time to play a quarternote */
  373.     {
  374.       INTtempo=0;
  375.       INTp = (char *)pattern[INTpat]+((unsigned)INTrow << 4);
  376.       for (INTi=0;INTi<4;INTi++,INTp+=4) /* Handle all 4 tracks in a loop */
  377.         {
  378.           /* Check if a command */
  379.           switch(*(INTp+2) & 15)
  380.             {
  381.               case 1: /* Set timebase to [INFO] */
  382.                 stm.tempo = *(INTp+3);
  383.                 break;
  384.               case 2: /* B?? = Break pattern and jump to order [INFO] */
  385.                 INTord=*(INTp+3);
  386.                 INTrow=-1;
  387.                 INTpat=orders[INTord];
  388.                 break;
  389.               case 3: /* C00 = Break pattern */
  390.                 INTrow=63;
  391.                 break;
  392.               default:break; /* No command */
  393.             }
  394.           /* Get the note volume = velocity */
  395.           INTvol=((*(INTp+1) & 7) << 1) + (*(INTp+2) & 0xF0);
  396.           if (INTvol==128) INTvol=127;
  397.           /* INTch = currently playing midich on this track */
  398.           INTch=INTnotes[INTi][1];
  399.           /* Play a new note */
  400.           if (*INTp<251)
  401.             {
  402.               INTins=*(INTp+1) >> 3; /* Instrument number */
  403.  
  404.               if (!INTins) /* Instrument == 0 -> use previus instrument */
  405.                 {
  406.                   INTins=INTnotes[INTi][2]; /* Instrument # */
  407.                 }
  408.               else /* Instrument > 0 -> normal case */
  409.                 {
  410.                   if (!(INTch=MIDIch[INTins-1])) continue; /* No MIDI ch */
  411.                   INTch+=0x8F;
  412.                 }
  413.               if (INTvol==130) INTvol=stm.inst[INTins-1].volume;
  414.               /* Check if a fixed note */
  415.               if ((INTnote=MIDInt[INTins-1])==0)
  416.                 INTnote=36+(*INTp & 15)+12*(*INTp >> 4);
  417.               /* Check if transposed note */
  418.               else if (INTnote>128)
  419.                 INTnote=36+(*INTp & 15)+12*(*INTp >> 4) + (INTnote - 192);
  420.               /* Turn off previous note on this channel (1..4) */
  421.               if (INTnotes[INTi][1])
  422.                 {
  423.                   switch (INTi)
  424.                     {
  425.                       case 0:
  426.                         if ( (INTnotes[0][1]==INTnotes[1][1] &&
  427.                               INTnotes[0][0]==INTnotes[1][0]) ||
  428.                              (INTnotes[0][1]==INTnotes[2][1] &&
  429.                               INTnotes[0][0]==INTnotes[2][0]) ||
  430.                              (INTnotes[0][1]==INTnotes[3][1] &&
  431.                               INTnotes[0][0]==INTnotes[3][0]) )
  432.                           goto no_off;
  433.                         break;
  434.                       case 1:
  435.                         if ( (INTnotes[1][1]==INTnotes[0][1] &&
  436.                               INTnotes[1][0]==INTnotes[0][0]) ||
  437.                              (INTnotes[1][1]==INTnotes[2][1] &&
  438.                               INTnotes[1][0]==INTnotes[2][0]) ||
  439.                              (INTnotes[1][1]==INTnotes[3][1] &&
  440.                               INTnotes[1][0]==INTnotes[3][0]) )
  441.                           goto no_off;
  442.                         break;
  443.                       case 2:
  444.                         if ( (INTnotes[2][1]==INTnotes[1][1] &&
  445.                               INTnotes[2][0]==INTnotes[1][0]) ||
  446.                              (INTnotes[2][1]==INTnotes[0][1] &&
  447.                               INTnotes[2][0]==INTnotes[0][0]) ||
  448.                              (INTnotes[2][1]==INTnotes[3][1] &&
  449.                               INTnotes[2][0]==INTnotes[3][0]) )
  450.                           goto no_off;
  451.                         break;
  452.                       case 3:
  453.                         if ( (INTnotes[3][1]==INTnotes[1][1] &&
  454.                               INTnotes[3][0]==INTnotes[1][0]) ||
  455.                              (INTnotes[3][1]==INTnotes[2][1] &&
  456.                               INTnotes[3][0]==INTnotes[2][0]) ||
  457.                              (INTnotes[3][1]==INTnotes[0][1] &&
  458.                               INTnotes[3][0]==INTnotes[0][0]) )
  459.                           goto no_off;
  460.                         break;
  461.                     }
  462.                   /* Clear a note off the screen */
  463.                   pokeb(0xB800,1610+160*(unsigned)INTnotes[INTi][2],' ');
  464.                   SendData( INTnotes[INTi][1] ); /* Note On */
  465.                   SendData( INTnotes[INTi][0] );
  466.                   SendData( 0 );         /* Velocity=0 -> Note Off */
  467.                 }
  468. no_off:
  469.               /* Show a note on the screen */
  470.               pokeb(0xB800,1610+160*(unsigned)INTins,14);
  471.               if (INTvols && INTvolumes[INTch & 15] != INTvol)
  472.                 {
  473.                   SendData( INTch + 0x20 );       /* Bx = Controller */
  474.                   SendData( 7 );                  /* 7 = Main Volume */
  475.                   SendData( (INTvol >> 1) + 64 ); /* New Volume */
  476.                   INTvolumes[INTch & 15]=INTvol;  /* Remember volume */
  477.                 }
  478.               INTnotes[INTi][0]=INTnote; /* Remember which note       */
  479.               INTnotes[INTi][1]=INTch;   /* Remember which MIDI ch    */
  480.               INTnotes[INTi][2]=INTins;  /* Remember which instrument */
  481.               INTnotes[INTi][3]=INTvol;  /* Remember what volume      */
  482.               SendData( INTch );         /* Note On    */
  483.               SendData( INTnote );       /* Note value */
  484.               if (INTvols)
  485.                 SendData( 127 );         /* Velocity   */
  486.               else
  487.                 SendData( INTvol );      /* Velocity */
  488.             }
  489.           /* Check for other than note on - commands. Can be note off, */
  490.           /* volume change or no change */
  491.           else if (INTch) /* If there was a note on this track */
  492.             {
  493.               /* Turn a note off? */
  494.               if (*INTp==254)
  495.                 {
  496.                   SendData( INTch );             /* Note On */
  497.                   SendData( INTnotes[INTi][0] ); /* Note value */
  498.                   SendData( 0 );                 /* Velocity -> Note Off */
  499.                   INTnotes[INTi][1]=0;           /* Tell we play nothing */
  500.                 }
  501.               /* Volume change? */
  502.               else if (INTvols && INTvol != INTnotes[INTi][3])
  503.                 {
  504.                   if (INTvol==130) /* Default instrument volume */
  505.                     INTvol=stm.inst[INTnotes[INTi][2]-1].volume;
  506.                   SendData( INTch + 0x20 );       /* Bx = Controller */
  507.                   SendData( 7 );                  /* 7 = Main Volume */
  508.                   SendData( (INTvol >> 1) + 64 ); /* New Volume */
  509.                   INTvolumes[INTch & 15]=INTvol;  /* Save midich-vol */
  510.                   INTnotes[INTi][3]=INTvol;       /* Save track-volume */
  511.                 }
  512.  
  513.             }
  514.         }
  515.       if (INTrow++ == 63) /* If next pattern... */
  516.         {
  517.           INTrow=0;
  518.           INTpat=orders[++INTord];
  519.           if (INTpat>=stm.patnum) /* If all patterns done... */
  520.             {
  521.               INTord=0;
  522.               INTpat=orders[0];
  523.               if (!INTloop)
  524.                 INTstop=1;
  525.               else
  526.                 INTtime=0L;
  527.             }
  528.         }
  529.     }
  530. }
  531.  
  532.  
  533. void Silent()
  534. {
  535.   int i;
  536.   for (i=0;i<4;i++)
  537.     {
  538.       if (INTnotes[i][0]) /* If there was a note on this channel... */
  539.     {
  540.       SendData( INTnotes[i][1] ); /* Note Off */
  541.       SendData( INTnotes[i][0] );
  542.       SendData( 0 );
  543.       INTnotes[i][0]=0;
  544.     }
  545.     }
  546.   return;
  547. }
  548.  
  549. void ShowTime(tim)
  550. long tim;
  551. {
  552.   gotoxy(24,6);
  553.   cprintf("%2d:%02d:%02d",
  554.     (int)(tim/60000L),
  555.     ((int)(tim/1000L)) % 60,
  556.     (int)(tim % 100L));
  557.   return;
  558. }
  559.  
  560. void ShowPat(pat,row)
  561. int pat,row;
  562. {
  563.   int i;
  564.   unsigned char *p = (char *)pattern[pat] + (row << 4);
  565.   unsigned char vol;
  566.   if (!FILEok) return;
  567.   gotoxy(4,45);
  568.   cprintf("%3d:%2d",pat,row);
  569.   for (i=0;i<4;i++)
  570.     {
  571.        /* Note, 255 = no change, 254 = off */
  572.        gotoxy(13+i*17,45);
  573.        if (*p<251)
  574.          cprintf("%2.2s%d",notes[*p & 15],(*p >> 4)+3);
  575.        else if (*p==254)
  576.          cprintf("   ");
  577.        /* Instrument, 0 = no change */
  578.        if (*(p+1) & 0xF8)
  579.          {
  580.            gotoxy(17+i*17,45);
  581.            cprintf("%2d",*(p+1) >> 3);
  582.          }
  583.        /* Volume, 130 = use default for this instrument */
  584.        vol=((*(p+1) & 7) << 1) + (*(p+2) & 0xF0);
  585.        if (vol==128)
  586.          vol=127;
  587.        gotoxy(20+i*17,45);
  588.        if (*p<251 || stm.ver < 15)
  589.          if (vol==130)
  590.            cprintf("max");
  591.          else
  592.            cprintf("%3d",vol);
  593.        /* Command */
  594.        gotoxy(24+i*17,45);
  595.        if (*(p+2) & 15)
  596.      cprintf("%c%02X",(*(p+2) & 15)+64,*(p+3));
  597.        else
  598.      cprintf("   ");
  599.        p += 4;
  600.     }
  601.   return;
  602. }
  603.  
  604. void ShowOrd(cnt)
  605. unsigned char cnt;
  606. {
  607.   int i,j,k;
  608.   if (!FILEok) return;
  609.   if (cnt<5)
  610.     {
  611.       j=0;
  612.       k=cnt+5;
  613.     }
  614.   else if (cnt>122)
  615.     {
  616.       j=116;
  617.       k=cnt-111;
  618.     }
  619.   else
  620.     {
  621.       j=cnt-5;
  622.       k=10;
  623.     }
  624.   for (i=0;i<12;i++,j++)
  625.     {
  626.       gotoxy(52,i+5);
  627.       if (orders[j] < 99)
  628.     cprintf("%3d ",orders[j]);
  629.       else
  630.     cprintf("    ");
  631.     }
  632.   gotoxy(55,k);
  633.   putch(17);
  634.   return;
  635. }
  636.  
  637. void Play()
  638. {
  639.   unsigned i;
  640.   if (!FILEok) return;
  641.   INTcount=41;
  642.   INTtempo=stm.tempo-1;
  643.   INTstop=0;
  644.   for (i=0;i<4;i++) INTnotes[i][0]=0;
  645.  
  646.   gotoxy(3,47);
  647.   cprintf(" %-75s","Playing song...");
  648.   oldrow=INTrow;
  649.   ShowPat(INTpat,INTrow);
  650.   ShowOrd(INTord);
  651.   ShowTime(INTtime);
  652.   gotoxy(63,16);
  653.   if (INTloop)
  654.     putch(2);
  655.   else
  656.     putch(1);
  657.   gotoxy(63,14);
  658.   if (INTvols)
  659.     putch(2);
  660.   else
  661.     putch(1);
  662.  
  663.   for (i=11+160*11;i<11+42*160;i+=160)
  664.     pokeb(0xB800,i,YELLOW+16*BLUE);
  665.  
  666.   for (i=0;i<31;i++) /* Go through all the MIDI tracks... */
  667.     {
  668.       if (i<16) INTvolumes[i]=0;
  669.       if (!INTvols && MIDIch[i])
  670.         {
  671.           /* --- Send Volume values --- */
  672.           SendData ( 0xB0 + MIDIch[i] - 1 ); /* Controller */
  673.           SendData ( 0x07 );                 /* Main Volume */
  674.           SendData ( stm.inst[i].volume );   /* Send Volume value */
  675.         }
  676.     }
  677.  
  678.   if (!INTplaying)
  679.     {
  680.       oldhandler = getvect(INTR);
  681.  
  682.       disable(); /* Disable interrupts */
  683.       outportb(0x43,0x34);
  684.       outportb(0x40,15);
  685.       outportb(0x40,6);  /* Frequency = 1191564/1551 ≈ 768 Hz ≈ 128 BPM */
  686.       outportb(0x43,0x90);
  687.       setvect(INTR, PlayInt);
  688.       enable();  /* Enable interrupts */
  689.  
  690.     }
  691.   INTplaying=1;
  692.  
  693.   return;
  694. }
  695.  
  696. void Stop()
  697. {
  698.   unsigned i;
  699.  
  700.   if (!FILEok) return;
  701.   if (INTplaying)
  702.     {
  703.       disable(); /* Disable interrupts */
  704.       outportb(0x43,0x34);
  705.       outportb(0x40,0);
  706.       outportb(0x40,0);  /* Frequency = 1191564/65536 = 18.18 Hz */
  707.       enable();  /* Enable interrupts */
  708.       setvect(INTR, oldhandler);
  709.     }
  710.  
  711.   for (i=10+160*11;i<10+42*160;i+=160)
  712.     pokeb(0xB800,i,' ');
  713.  
  714.   gotoxy(3,47);
  715.   cprintf(" %-75s","Play stopped.");
  716.   INTrow=0;
  717.   INTord=0;
  718.   INTpat=orders[INTord];
  719.   INTtime=0L;
  720.   INTplaying=0;
  721.   Silent();
  722.   stm.tempo=96;
  723.   textcolor(WHITE);
  724.   gotoxy(12,5);
  725.   cprintf("%3d",stm.tempo);
  726.   ShowPat(INTpat,INTrow);
  727.   ShowOrd(INTord);
  728.  
  729.   return;
  730. }
  731.  
  732. void Pause()
  733. {
  734.   if (!FILEok) return;
  735.  
  736.   if (INTplaying)
  737.     {
  738.       disable(); /* Disable interrupts */
  739.       outportb(0x43,0x34);
  740.       outportb(0x40,0);
  741.       outportb(0x40,0);  /* Frequency = 1191564/65536 = 18.18 Hz */
  742.       enable();  /* Enable interrupts */
  743.       setvect(INTR, oldhandler);
  744.     }
  745.  
  746.   gotoxy(3,47);
  747.   cprintf(" %-75s","Play paused.");
  748.   INTplaying=0;
  749.   Silent();
  750.   ShowPat(INTpat,INTrow);
  751.   ShowOrd(INTord);
  752.   ShowTime(INTtime);
  753.  
  754.   return;
  755. }
  756.  
  757. void ShowPlay()
  758. {
  759.   int i;
  760.   if (!INTplaying || !FILEok) return;
  761.   if (INTstop)
  762.     Stop();
  763.   else if (INTtime != oldtime)
  764.     {
  765.       if (stm.tempo != oldtempo)
  766.     {
  767.       oldtempo = stm.tempo;
  768.       textcolor(WHITE);
  769.       gotoxy(12,5);
  770.       cprintf("%3d",stm.tempo);
  771.     }
  772.       ShowTime(INTtime);
  773.       oldtime = INTtime;
  774.       if (INTrow != oldrow)
  775.     {
  776.       ShowPat(INTpat,oldrow);
  777.       oldrow=INTrow;
  778.       if (INTord != oldord)
  779.         {
  780.           ShowOrd(INTord);
  781.           oldord=INTord;
  782.         }
  783.     }
  784.     }
  785.   return;
  786. }
  787.  
  788. /* ---------------------------- Mouse routines --------------------------- */
  789.  
  790. void MoveMouse(x,y)
  791. int x,y;
  792. {
  793.   struct REGPACK reg;
  794.   reg.r_ax=4;
  795.   reg.r_cx=x;
  796.   reg.r_dx=y;
  797.   intr(0x33,®);
  798.   return;
  799. }
  800.  
  801. int InitMouse()
  802. {
  803.   struct REGPACK reg;
  804.   reg.r_ax = 0;
  805.   intr(0x33,®);
  806.   if (reg.r_ax==0xffff)
  807.     {
  808.       unsigned buttons=reg.r_bx;
  809.       reg.r_ax=8;
  810.       reg.r_cx=0;
  811.       reg.r_dx=399;
  812.       intr(0x33,®); /* Vertical area 0..49 */
  813.       reg.r_ax=10;
  814.       reg.r_bx=0;
  815.       reg.r_cx=0x00FF;
  816.       reg.r_dx=0x0E00;
  817.       intr(0x33,®); /* Define software text cursor masks */
  818.       MoveMouse(0,0);
  819.       return buttons;
  820.     }
  821.   else
  822.     return 0;
  823. }
  824.  
  825. void MouseOn()
  826. {
  827.   struct REGPACK reg;
  828.   reg.r_ax=1;
  829.   intr(0x33,®);
  830.   return;
  831. }
  832.  
  833. void MouseOff()
  834. {
  835.   struct REGPACK reg;
  836.   reg.r_ax=2;
  837.   intr(0x33,®);
  838.   return;
  839. }
  840.  
  841. int GetClick(mx,my)
  842. int *mx,*my;
  843. {
  844.   static int bdown;
  845.   struct REGPACK reg;
  846.   reg.r_ax = 6;
  847.   reg.r_bx = 0;
  848.   intr(0x33,®);
  849.   if (!(reg.r_ax & 1)) bdown=0;
  850.   if (bdown) return 0; /* Don't check presses until released, too */
  851.   reg.r_ax = 5;
  852.   reg.r_bx = 0;
  853.   intr(0x33,®);
  854.   *mx = (reg.r_cx >> 3)+1;
  855.   *my = (reg.r_dx >> 3)+1;
  856.   if (reg.r_ax & 1) bdown=1;
  857.   return (reg.r_ax & 1);
  858. }
  859.  
  860. void GetMouse(mx,my)
  861. int *mx,*my;
  862. {
  863.   struct REGPACK reg;
  864.   reg.r_ax = 3;
  865.   reg.r_bx = 0;
  866.   intr(0x33,®);
  867.   *mx = (reg.r_cx >> 3)+1;
  868.   *my = (reg.r_dx >> 3)+1;
  869.   ShowPlay();
  870.   gotoxy(*mx,*my);
  871.   return;
  872. }
  873.  
  874. /* ---------------------------- Special routines ------------------------- */
  875.  
  876. void CalcChecksum(dat,pos)
  877. unsigned char *dat;
  878. int pos;
  879. {
  880.   unsigned int checksum=0,i;
  881.   for (i=5;i<pos;i++) checksum+=dat[i];
  882.   checksum = (128 - (checksum % 128)) % 128;
  883.   dat[pos]=(unsigned char)checksum;
  884.   return;
  885. }
  886.  
  887. int InitLAPC(mode)
  888. char mode;
  889. {
  890.   int i;
  891.   if (!AKAIok) return 0;
  892.   if (mode)
  893.     for (i=20;i<28;i++) systemarea[i]=16; /* Part OFF */
  894.   else
  895.     for (i=20;i<28;i++) systemarea[i]=i-19; /* Part ON */
  896.   CalcChecksum(systemarea,30);
  897.   gotoxy(3,47);
  898.   cprintf(" %-75s","Initializing LAPC-I synth module...");
  899.   for (i=0;i<100;i++) ReceiveData();
  900.   for (i=0;i<32;i++) SendData(systemarea[i]);
  901.   gotoxy(3,47);
  902.   cprintf(" %-75s","LAPC-I synth initialized OK.");
  903.   return 1;
  904. }
  905.  
  906. int InitAkai() /* Request and send overall parameters from/to Akai X7000 */
  907. {
  908.   int apu,i=0;
  909.   if (!MPUok) return 0;
  910.   gotoxy(3,47);
  911.   cprintf(" %-75s","Initializing Akai X7000 sampler...");
  912.   SendAkaiEx(5); /* Enable system common reception */
  913.   ClearMPU(); /* Empty the MPU buffer */
  914.   SendAkaiEx(1); /* Request overall parameters */
  915.   SetTick();
  916.   do {
  917.     if ((apu=ReceiveData())<256)
  918.       {
  919.         overalldata[i++]=apu;
  920.         SetTick();
  921.       }
  922.   } while (!GoneTicks(6) && i<33); /* Until EOX */
  923.   if (GoneTicks(6) || apu != 247)
  924.     {
  925.       ShowError("AKAI X7000 does not respond, using plain synth mode!");
  926.       return 0;
  927.     }
  928.   /* Change parameters the way we want them... */
  929.   overalldata[7]=0;    /* Midi Reception Channel = 1 */
  930.   overalldata[2]=0;    /* MIDI Channel no. (in header) = 1 */
  931.   overalldata[11]=0;   /* Midi Transmission Channel = 1 */
  932.   overalldata[9]=3;    /* Polyphonic */
  933.   overalldata[13]=64;  /* Multi Program */
  934.   overalldata[14]=0;   /* - // - */
  935.   overalldata[15]=12;  /* Pitch Wheel Range = 1 octave */
  936.   overalldata[17]=127; /* Program Change Off */
  937.   overalldata[18]=1;   /* - // - */
  938.   /* Clear and calculate XOR checksum... */
  939.   for (overalldata[31]=0,i=7;i<31;i++) overalldata[31] ^= overalldata[i];
  940.   /* Send Overall Settings to Akai */
  941.   for (i=0;i<33;i++) SendData(overalldata[i]);
  942.   gotoxy(3,47);
  943.   cprintf(" %-75s","Akai X7000 sampler initialized OK.");
  944.   return 1;
  945. }
  946.  
  947. void DoParams(endp,loopp)
  948. unsigned endp,loopp;
  949. {
  950.   if (loopp<endp) sampleparam[265]=2; /* Looping Mode */
  951.   sampleparam[275]=endp & 127;
  952.   sampleparam[276]=(endp >> 7) & 1;
  953.   sampleparam[277]=(endp >> 8) & 127;
  954.   sampleparam[278]=endp >> 15;
  955.   sampleparam[279]=loopp & 127;
  956.   sampleparam[280]=(loopp >> 7) & 1;
  957.   sampleparam[281]=(loopp >> 8) & 127;
  958.   sampleparam[282]=loopp >> 15;
  959.   sampleheader[9] = endp & 127;
  960.   sampleheader[10]=(endp >> 7) & 127;
  961.   sampleheader[11]=(endp >> 14) & 127;
  962.   sampleheader[12]= loopp & 127;
  963.   sampleheader[13]=(loopp >> 7) & 127;
  964.   sampleheader[14]=(loopp >> 14) & 127;
  965.   sampleheader[15]=endp & 127;
  966.   sampleheader[16]=(endp >> 7) & 127;
  967.   sampleheader[17]=(endp >> 14) & 127;
  968.   return;
  969. }
  970.  
  971.  
  972. void SendInit() /* Sending Program/Sample, Volume and Pan data to synths. */
  973. {
  974.   int i,j,semitone,apui,trk;
  975.   char sfntun;
  976.   unsigned char smpl,rate;
  977.   unsigned char *p;
  978.   unsigned k,blk,apuw;
  979.   long drate,apul;
  980.  
  981.   if (!FILEok) return;
  982.   gotoxy(3,47);
  983.   cprintf(" %-75s","Sending Program, Sample, Volume and Pan data...");
  984.  
  985.   for (trk=0;trk<31;trk++) /* Go through all the MIDI tracks... */
  986.     if (MIDIch[trk]) /* Handle only tracks that have channel assigned... */
  987.       {
  988.     /* --- Send Pan values --- */
  989.     SendData ( 0xB0 + MIDIch[trk] - 1 ); /* Controller */
  990.     SendData ( 0x0A );                   /* Pan Position */
  991.     SendData ( stm.inst[trk].pan );      /* Send Pan value */
  992.     /* --- Send Volume values --- */
  993.     SendData ( 0xB0 + MIDIch[trk] - 1 ); /* Controller */
  994.     SendData ( 0x07 );                   /* Main Volume */
  995.     SendData ( stm.inst[trk].volume );   /* Send Volume value */
  996.     /* --- Send Program / Sample information --- */
  997.     if (MIDIprg[trk]<128) /* Send just program data, no samples */
  998.       {
  999.         SendData ( 0xC0 + MIDIch[trk] - 1 ); /* Program Change */
  1000.         SendData ( MIDIprg[trk] ); /* Send new patch number */
  1001.       }
  1002.     else if (MIDIprg[trk]>129 && AKAIok && stm.inst[trk].length>=200 &&
  1003.          (p=sample[trk])!=NULL) /* Test if OK to send sample data. */
  1004.       {
  1005.         gotoxy(3,47);
  1006.         cprintf(" %-75s"," ");
  1007.         smpl=MIDIprg[trk]-130;  /* smpl = sample number */
  1008.         sampleheader[3]=smpl; /* Set header sample number */
  1009.         memcpy(sampleparam,sampledata,319); /* Make parameter work area */
  1010.         sampleparam[5]=smpl; /* Set sample parameter sample number */
  1011.  
  1012.         if (stm.inst[trk].loope != 65535) /* Looped sample */
  1013.           {
  1014.         if (stm.inst[trk].loope<stm.inst[trk].length)
  1015.           stm.inst[trk].length=stm.inst[trk].loope;
  1016.         else if (stm.inst[trk].loope>stm.inst[trk].length)
  1017.           stm.inst[trk].loope=stm.inst[trk].length;
  1018.         DoParams(stm.inst[trk].loope,stm.inst[trk].loops);
  1019.           }
  1020.         else
  1021.           DoParams(stm.inst[trk].length,stm.inst[trk].length);
  1022.  
  1023.         /* --- Send Raw Sample --- */
  1024.         ClearMPU(); /* Empty the MPU buffer */
  1025.         for (i=0;i<19;i++) SendData(sampleheader[i]);
  1026.         if (WaitACK() != 0x7F)
  1027.           {
  1028.             ShowError("Akai does not acknowledge sample header!");
  1029.             return;
  1030.           }
  1031.         k=0; blk=0;
  1032.         do {
  1033.           sampleblock[0]=blk++ & 127;
  1034.           for (sampleblock[121]=0,j=1;j<61;j++,k++)
  1035.             {
  1036.               sampleblock[121] ^=
  1037.                 (sampleblock[j+j-1]=((*p ^ 0x80) >> 5) + 60);
  1038.               sampleblock[121] ^=
  1039.                 (sampleblock[j+j]=(*(p++) & 31) << 2);
  1040.             }
  1041.           for (i=0;i<122;i++) SendData(sampleblock[i]);
  1042.           if ((WaitACK()) != 0x7F)
  1043.             {
  1044.               ShowError("Akai does not acknowledge sample block!");
  1045.               continue;
  1046.             }
  1047.           gotoxy(3,47);
  1048.           cprintf(" Sending sample %d point %d... ",smpl+1,k);
  1049.         } while (k < stm.inst[trk].length);
  1050.         SendData(0xF7); /* Send EOX */
  1051.         /* --- Send sample parameters --- */
  1052.         drate=(long)stm.inst[trk].rate;
  1053.         apuw=65000;
  1054.         for (i=0;i<41;i++)
  1055.           {
  1056.             apul=samplerates[i];
  1057.             if ((unsigned)abs(apul-drate) < apuw)
  1058.               {
  1059.                 rate=i+36;
  1060.                 apuw=(unsigned)abs(apul-drate);
  1061.                 apui=(int)(drate-apul);
  1062.               }
  1063.           }
  1064.         semitone = (int)(drate/24);
  1065.         apui = apui % semitone;
  1066.         sfntun = 16 * apui / semitone;
  1067.         sampleparam[299]=sfntun & 127;
  1068.         sampleparam[300]=(sfntun >> 7) & 1;
  1069.         sampleparam[303]=rate;
  1070.         sampleparam[1+8*MIDIch[trk]]=99; /* Keyrange for AKAI program */
  1071.         for (sampleparam[317]=0,i=7;i<317;i++)
  1072.           sampleparam[317] ^= sampleparam[i];
  1073.         for (i=0;i<319;i++) SendData(sampleparam[i]);
  1074.       }
  1075.       }
  1076.   gotoxy(3,47);
  1077.   cprintf(" %-75s","Initialization data sent OK.");
  1078.   return;
  1079. }
  1080.  
  1081. int ShowFiles()
  1082. {
  1083.   int done,lkm=0;
  1084.   char haku[80];
  1085.   struct ffblk ffb;
  1086.  
  1087.   strcpy(haku,defdir);
  1088.   strcat(haku,defext);
  1089.   textcolor(WHITE);
  1090.   gotoxy(53,18);
  1091.   cprintf("%-25.25s",defdir);
  1092.  
  1093.   window(52,22,77,40);
  1094.   clrscr();
  1095.   window(52,22,77,41);
  1096.  
  1097.   done = findfirst(haku,&ffb,0);
  1098.   while (!done)
  1099.     {
  1100.       if (lkm<38) cprintf(" %-12s",ffb.ff_name);
  1101.       if (lkm<MAXFILES) strcpy(allfiles[lkm],ffb.ff_name);
  1102.       lkm++;
  1103.       done=findnext(&ffb);
  1104.     }
  1105.   for(;lkm<MAXFILES;lkm++) allfiles[lkm][0]='\0';
  1106.   window(1,1,80,50);
  1107.   return (lkm);
  1108. }
  1109.  
  1110. int ShowDirs(haku)
  1111. char *haku;
  1112. {
  1113.   int done,lkm=0;
  1114.   char apu[80];
  1115.   struct ffblk ffb;
  1116.  
  1117.   strcpy(apu,haku);
  1118.   strcat(apu,"*");
  1119.   textcolor(WHITE);
  1120.   gotoxy(53,18);
  1121.   cprintf("%-25.25s",haku);
  1122.  
  1123.   window(52,22,77,40);
  1124.   clrscr();
  1125.  
  1126.   done = findfirst(apu,&ffb,FA_DIREC);
  1127.   while (!done)
  1128.     {
  1129.       if (ffb.ff_attrib==FA_DIREC)
  1130.     {
  1131.       if (lkm<38) cprintf(" %-12s",ffb.ff_name);
  1132.       if (lkm<MAXDIRS) strcpy(alldirs[lkm],ffb.ff_name);
  1133.       lkm++;
  1134.     }
  1135.       done=findnext(&ffb);
  1136.     }
  1137.   for(;lkm<MAXDIRS;lkm++) alldirs[lkm][0]='\0';
  1138.   window(1,1,80,50);
  1139.   return (lkm);
  1140. }
  1141.  
  1142. void ChangeDir(nam)
  1143. char *nam;
  1144. {
  1145.   int i;
  1146.   if (!strcmp(nam,"..")) /* If one directory up.. */
  1147.     {
  1148.       i=strlen(defdir)-2;
  1149.       while (defdir[i] != '\\') defdir[i--]='\0';
  1150.     }
  1151.   else if (!strcmp(nam,".")) return; /* Nothing to do, if current dir */
  1152.   else
  1153.     {
  1154.       strcat(defdir,nam);
  1155.       strcat(defdir,"\\");
  1156.     }
  1157.   gotoxy(53,18);
  1158.   cprintf("%-25.25s",defdir);
  1159.   return;
  1160. }
  1161.  
  1162. int ChangeDrive(nam)
  1163. char nam;
  1164. {
  1165.   strcpy(defdir,"X:\\");
  1166.   defdir[0]=nam+'A';
  1167.   if (getcurdir(nam+1,defdir+3))
  1168.     {
  1169.       ShowError("Error: Drive not valid!");
  1170.       return 0;
  1171.     }
  1172.   if (defdir[strlen(defdir)-1] != '\\') strcat(defdir,"\\");
  1173.   gotoxy(53,18);
  1174.   cprintf("%-25.25s",defdir);
  1175.   gotoxy(3,47);
  1176.   cprintf(" %-75s","New default drive selected.");
  1177.   return 1;
  1178. }
  1179.  
  1180. int SelectDrive()
  1181. {
  1182.   int i;
  1183.   gettext(51,20,56,29,scrbuf);
  1184.   window(51,20,56,29);
  1185.   textcolor(LIGHTGRAY);
  1186.   clrscr();
  1187.   cprintf("╔════╗║    ║║    ║║    ║║    ║║    ║║    ║║    ║║    ║╚════");
  1188.   window(1,1,80,50);
  1189.   gotoxy(56,29);putch('╝');
  1190.   textcolor(WHITE);
  1191.   for (i=0;i<8;i++)
  1192.     {
  1193.       gotoxy(53,21+i);
  1194.       putch(i+'C');putch(':');
  1195.     }
  1196.   gotoxy(2,49);
  1197.   cprintf("Select drive to make current.\r");
  1198.   do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
  1199.   if (mx>51 && mx<56 && my>20 && my<29) /* If selected a drive... */
  1200.     i=ChangeDrive(my-19);
  1201.   else
  1202.     i=0;
  1203.   MouseOff();
  1204.   puttext(51,20,56,29,scrbuf);
  1205.   MouseOn();
  1206.   return i;
  1207. }
  1208.  
  1209. void SelectCh(trk)
  1210. unsigned char trk;
  1211. {
  1212.   int i;
  1213.   gettext(24,12,29,30,scrbuf);
  1214.   window(24,12,29,30);
  1215.   textcolor(LIGHTGRAY);
  1216.   clrscr();
  1217.   cprintf("╔════╗║    ║║    ║║    ║║    ║║    ║║    ║║    ║║    ║");
  1218.   cprintf("║    ║║    ║║    ║║    ║║    ║║    ║║    ║║    ║║    ║╚════");
  1219.   window(1,1,80,50);
  1220.   gotoxy(29,30);putch('╝');
  1221.   textcolor(WHITE);
  1222.   gotoxy(26,13);
  1223.   cprintf("--");
  1224.   for (i=1;i<17;i++)
  1225.     {
  1226.       gotoxy(26,13+i);
  1227.       cprintf("%2d",i);
  1228.     }
  1229.   gotoxy(2,49);
  1230.   cprintf("Select MIDI channel for track %d.\r",trk);
  1231.   do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
  1232.   if (mx>25 && mx<28 && my>12 && my<30) /* If selected a channel... */
  1233.     MIDIch[trk]=my-13;
  1234.   MouseOff();
  1235.   puttext(24,12,29,30,scrbuf);
  1236.   for (i=0;i<31;i++)
  1237.     {
  1238.       gotoxy(32,12+i);
  1239.       if (MIDIch[i]) { textcolor(WHITE); cprintf("%2d",MIDIch[i]); }
  1240.       else { textcolor(LIGHTGRAY); cprintf("__"); }
  1241.     }
  1242.   textcolor(WHITE);
  1243.   MouseOn();
  1244.   return;
  1245. }
  1246.  
  1247. void SelectNote(trk)
  1248. unsigned char trk;
  1249. {
  1250.   int i,oct,not;
  1251.   MouseOff();
  1252.   gettext(16,12,65,29,scrbuf);
  1253.   textcolor(LIGHTGRAY);
  1254.   gotoxy(16,12);
  1255.   cprintf("╔════════════════════════════════════════════════╗");
  1256.   for (not=13;not<29;not++)
  1257.     {
  1258.       gotoxy(16,not);putch('║');
  1259.       gotoxy(65,not);putch('║');
  1260.     }
  1261.   gotoxy(16,29);
  1262.   cprintf("╚════════════════════════════════════════════════╝");
  1263.   window(17,13,64,28);
  1264.   textcolor(WHITE);
  1265.   clrscr();
  1266.   window(17,13,64,29);
  1267.   /* Fixed notes */
  1268.   for (oct=0;oct<10;oct++)
  1269.     for (not=0;not<12;not++)
  1270.       cprintf("%2s%d ",notes[not],oct);
  1271.   /* Transposed notes */
  1272.   for (not=-36;not<0;not++)
  1273.     cprintf("%02d ",not);
  1274.   for (not=0;not<36;not++)
  1275.     cprintf("+%02d ",not);
  1276.   gotoxy(1,1);cprintf(" --");
  1277.   window(1,1,80,50);
  1278.   MouseOn();
  1279.   do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
  1280.   if (mx>16 && mx<65 && my>12 && my<23) /* If selected a fixed note... */
  1281.     MIDInt[trk]=(my-13)*12+(mx-17)/4;
  1282.   else if (mx>16 && mx<65 && my>22 && my<29) /* If selected a fixed note... */
  1283.     MIDInt[trk]=192 + (my-26)*12 + (mx-17)/4;
  1284.   MouseOff();
  1285.   puttext(16,12,65,29,scrbuf);
  1286.   for (i=0;i<31;i++)
  1287.     {
  1288.       gotoxy(47,12+i);
  1289.       if ( MIDInt[i] > 0 && MIDInt[i] < 128 )
  1290.         {
  1291.           textcolor(WHITE);
  1292.           cprintf("%2s%d",notes[MIDInt[i] % 12],MIDInt[i] / 12);
  1293.         }
  1294.       else if ( MIDInt[i] > 191 )
  1295.         {
  1296.           textcolor(WHITE);
  1297.           cprintf("+%02d",MIDInt[i] - 192);
  1298.         }
  1299.       else if ( MIDInt[i] > 127 )
  1300.         {
  1301.           textcolor(WHITE);
  1302.           cprintf("%02d",MIDInt[i] - 192);
  1303.         }
  1304.       else
  1305.         {
  1306.           textcolor(LIGHTGRAY);
  1307.           cprintf("___");
  1308.         }
  1309.     }
  1310.   MouseOn();
  1311.   textcolor(WHITE);
  1312.   return;
  1313. }
  1314.  
  1315. void SelectPrg(trk)
  1316. unsigned char trk;
  1317. {
  1318.   int i;
  1319.   MouseOff();
  1320.   gettext(23,11,56,30,scrbuf);
  1321.   textcolor(LIGHTGRAY);
  1322.   gotoxy(23,11);
  1323.   cprintf("╔════════════════════════════════╗");
  1324.   for (i=12;i<30;i++)
  1325.     {
  1326.       gotoxy(23,i);putch('║');
  1327.       gotoxy(56,i);putch('║');
  1328.     }
  1329.   gotoxy(23,30);
  1330.   cprintf("╚════════════════════════════════╝");
  1331.   window(24,12,55,29);
  1332.   clrscr();
  1333.   window(24,12,55,30);
  1334.   textcolor(WHITE);
  1335.   cprintf("S01 S02 S03 S04 S05 S06 S07 S08 ");
  1336.   cprintf("S09 S10 S11 S12 S13 S14 S15 S16 ");
  1337.   for (i=1;i<129;i++) cprintf("%3d ",i);
  1338.   window(1,1,80,50);
  1339.   MouseOn();
  1340.   do { GetMouse(&mx,&my); } while (!GetClick(&mx,&my));
  1341.   if (mx>23 && mx<56 && my>13 && my<30) /* If selected a program... */
  1342.     MIDIprg[trk]=(my-14)*8+(mx-24)/4;
  1343.   else if (mx>23 && mx<56 && my>11 && my<14) /* If selected a sample... */
  1344.     MIDIprg[trk]=130+(my-12)*8+(mx-24)/4;
  1345.   else
  1346.     MIDIprg[trk]=128;
  1347.   MouseOff();
  1348.   puttext(23,11,56,30,scrbuf);
  1349.   for (i=0;i<31;i++)
  1350.     {
  1351.       gotoxy(35,12+i);
  1352.       if (MIDIprg[i] < 128) /* Programs = 0..127 */
  1353.         {
  1354.           textcolor(WHITE);
  1355.           cprintf("%3d",MIDIprg[i]+1); /* Show them as 1..128 */
  1356.         }
  1357.       else if (MIDIprg[i] > 129) /* Samples = 130-135 */
  1358.         {
  1359.           textcolor(WHITE);
  1360.           cprintf("S%02d",MIDIprg[i]-129);
  1361.         }
  1362.       else /* Undefined = 128 */
  1363.         {
  1364.           MIDIprg[i]=128;
  1365.           textcolor(LIGHTGRAY);
  1366.           cprintf("___");
  1367.         }
  1368.     }
  1369.   MouseOn();
  1370.   textcolor(WHITE);
  1371.   return;
  1372. }
  1373.  
  1374. void ToggleDisp()
  1375. {
  1376.   static int mode;
  1377.   int i;
  1378.   if (!FILEok) return;
  1379.   mode ^= 1;
  1380.   gotoxy(20,11);
  1381.   textcolor(LIGHTGRAY);
  1382.   if (mode)
  1383.     cprintf("LoopS LoopE");
  1384.   else
  1385.     cprintf("Bytes    Hz");
  1386.   textcolor(WHITE);
  1387.   MouseOff();
  1388.   for (i=0;i<31;i++)
  1389.     {
  1390.       if (stm.inst[i].length)
  1391.     {
  1392.       gotoxy(20,12+i);
  1393.       if (mode)
  1394.         {
  1395.           if (stm.inst[i].loope != 65535)
  1396.         {
  1397.           cprintf("%5u",stm.inst[i].loops);
  1398.           gotoxy(26,12+i);
  1399.           cprintf("%5u",stm.inst[i].loope);
  1400.         }
  1401.           else
  1402.         {
  1403.           textcolor(LIGHTGRAY);
  1404.           cprintf("_____ _____");
  1405.           textcolor(WHITE);
  1406.         }
  1407.         }
  1408.       else
  1409.         {
  1410.           cprintf("%5u",stm.inst[i].length);
  1411.           gotoxy(26,12+i);
  1412.           cprintf("%5d",stm.inst[i].rate);
  1413.         }
  1414.     }
  1415.     }
  1416.   MouseOn();
  1417.   return;
  1418. }
  1419.  
  1420. void ClearSong()
  1421. {
  1422.   int i;
  1423.   textcolor(LIGHTGRAY);
  1424.   gotoxy(12,4);
  1425.   cprintf("____________________");
  1426.   gotoxy(12,8);
  1427.   cprintf("________");
  1428.   gotoxy(23,8);
  1429.   cprintf("     ");
  1430.   gotoxy(12,5);
  1431.   cprintf("___");
  1432.   gotoxy(12,6);
  1433.   cprintf("___");
  1434.   gotoxy(12,7);
  1435.   cprintf("___");
  1436.   for (i=0;i<31;i++)
  1437.     {
  1438.       MIDInt[i]=0;    /* Undefined note */
  1439.       gotoxy(47,12+i);
  1440.       cprintf("___");
  1441.       MIDIch[i]=0;    /* Undefined channel */
  1442.       gotoxy(32,12+i);
  1443.       cprintf("__");
  1444.       MIDIprg[i]=128; /* Undefined program */
  1445.       gotoxy(35,12+i);
  1446.       cprintf("___");
  1447.       gotoxy(7,12+i);
  1448.       cprintf("____________");
  1449.       gotoxy(20,12+i);
  1450.       cprintf("_____");
  1451.       gotoxy(26,12+i);
  1452.       cprintf("_____");
  1453.       gotoxy(39,12+i);
  1454.       cprintf("___");
  1455.       gotoxy(43,12+i);
  1456.       cprintf("___");
  1457.     }
  1458.   gotoxy(4,45);
  1459.   cprintf("___:__");
  1460.   for (i=0;i<4;i++)
  1461.     {
  1462.        gotoxy(13+i*17,45);
  1463.        cprintf("___ __ ___ ___");
  1464.     }
  1465.   for (i=0;i<12;i++)
  1466.     {
  1467.       gotoxy(52,i+5);
  1468.       cprintf("    ");
  1469.     }
  1470.   textcolor(WHITE);
  1471.   return;
  1472. }
  1473.  
  1474. void ShowSong()
  1475. {
  1476.   int i;
  1477.   textcolor(WHITE);
  1478.   gotoxy(12,4);
  1479.   cprintf("%-20.20s",stm.name);
  1480.   gotoxy(12,8);
  1481.   cprintf("%8.8s",stm.tnam);
  1482.   gotoxy(23,8);
  1483.   cprintf("%d.%d   ", stm.ver & 255, stm.ver >> 8);
  1484.   gotoxy(12,5);
  1485.   cprintf("%3d",stm.tempo);
  1486.   gotoxy(12,6);
  1487.   cprintf("%3d",stm.volume);
  1488.   gotoxy(12,7);
  1489.   cprintf("%3d",stm.patnum);
  1490.   for (i=0;i<31;i++)
  1491.     {
  1492.       if (!stm.inst[i].length)
  1493.     {
  1494.       textcolor(LIGHTGRAY);
  1495.       gotoxy(7,12+i);
  1496.       cprintf("____________");
  1497.       gotoxy(20,12+i);
  1498.       cprintf("_____");
  1499.       gotoxy(26,12+i);
  1500.       cprintf("_____");
  1501.       gotoxy(39,12+i);
  1502.       cprintf("___");
  1503.       gotoxy(43,12+i);
  1504.       cprintf("___");
  1505.       MIDInt[i]=0;    /* Undefined note */
  1506.       gotoxy(47,12+i);
  1507.       cprintf("___");
  1508.       MIDIch[i]=0;    /* Undefined channel */
  1509.       gotoxy(32,12+i);
  1510.       cprintf("__");
  1511.       MIDIprg[i]=128; /* Undefined program */
  1512.       gotoxy(35,12+i);
  1513.       cprintf("___");
  1514.       continue;
  1515.     }
  1516.       if (stm.typ & 4) /* MidiTracker modules */
  1517.     {
  1518.       MIDInt[i]=stm.inst[i].nt;
  1519.       gotoxy(47,12+i);
  1520.       if ( MIDInt[i] > 0 && MIDInt[i] < 128 )
  1521.         {
  1522.           textcolor(WHITE);
  1523.           cprintf("%2s%d",notes[MIDInt[i] % 12],MIDInt[i] / 12);
  1524.         }
  1525.       else if ( MIDInt[i] > 191 )
  1526.         {
  1527.           textcolor(WHITE);
  1528.           cprintf("+%02d",MIDInt[i] - 192);
  1529.         }
  1530.       else if ( MIDInt[i] > 127 )
  1531.         {
  1532.           textcolor(WHITE);
  1533.           cprintf("%02d",MIDInt[i] - 192);
  1534.         }
  1535.       else
  1536.         {
  1537.           textcolor(LIGHTGRAY);
  1538.           cprintf("___");
  1539.         }
  1540.       MIDIch[i]=stm.inst[i].ch;
  1541.       gotoxy(32,12+i);
  1542.       if (MIDIch[i]) { textcolor(WHITE); cprintf("%2d",MIDIch[i]); }
  1543.       else { textcolor(LIGHTGRAY); cprintf("__"); }
  1544.       MIDIprg[i]=stm.inst[i].prg;
  1545.       gotoxy(35,12+i);
  1546.       if (MIDIprg[i] < 128) /* Programs = 0..127 */
  1547.         {
  1548.           textcolor(WHITE);
  1549.           cprintf("%3d",MIDIprg[i]+1); /* Show them as 1..128 */
  1550.         }
  1551.       else if (MIDIprg[i] > 129) /* Samples = 130-145 */
  1552.         {
  1553.           textcolor(WHITE);
  1554.           cprintf("S%02d",MIDIprg[i]-129);
  1555.         }
  1556.       else /* Undefined = 128 */
  1557.         {
  1558.           MIDIprg[i]=128;
  1559.           textcolor(LIGHTGRAY);
  1560.           cprintf("___");
  1561.         }
  1562.     }
  1563.       else /* STM modules */
  1564.     {
  1565.       textcolor(LIGHTGRAY);
  1566.       MIDInt[i]=0;    /* Undefined note */
  1567.       gotoxy(47,12+i);
  1568.       cprintf("___");
  1569.       MIDIch[i]=0;    /* Undefined channel */
  1570.       gotoxy(32,12+i);
  1571.       cprintf("__");
  1572.       MIDIprg[i]=128; /* Undefined program */
  1573.       gotoxy(35,12+i);
  1574.       cprintf("___");
  1575.       stm.inst[i].volume=stm.inst[i].volume+63; /* 64 -> 127 */
  1576.       stm.inst[i].pan=64; /* Pan to middle */
  1577.     }
  1578.       textcolor(WHITE);
  1579.       gotoxy(7,12+i);
  1580.       cprintf("%-12s",stm.inst[i].name);
  1581.       gotoxy(20,12+i);
  1582.       cprintf("%5u",stm.inst[i].length);
  1583.       gotoxy(26,12+i);
  1584.       cprintf("%5d",stm.inst[i].rate);
  1585.       gotoxy(39,12+i);
  1586.       cprintf("%3d",stm.inst[i].volume);
  1587.       gotoxy(43,12+i);
  1588.       cprintf("%3d",stm.inst[i].pan);
  1589.     }
  1590.   textcolor(WHITE);
  1591.   INTord=0;
  1592.   ShowOrd(INTord);
  1593.   INTpat=orders[0];
  1594.   ShowPat(INTpat,0);
  1595.   return;
  1596. }
  1597.  
  1598. void ConvertPattern()
  1599. {
  1600.   unsigned int w2;
  1601.   unsigned char b1, b2, b3, b4, b5, b6;
  1602.  
  1603.   unsigned char *p = (unsigned char *)pattern[i];
  1604.  
  1605.   for (j=0;j<256;j++)         /* Handle 256 notes = 4 ch * 64 rows */
  1606.     {
  1607.       w2 = *p & 0x0F;
  1608.       w2 = (w2 << 8) + *(p+1);
  1609.       if ( ! w2 )
  1610.         {
  1611.           b1 = 0x0F;
  1612.           b2 = 0x0F;
  1613.           b3 = 0;
  1614.         }
  1615.       else
  1616.         {
  1617.           b2 = 2;
  1618.           do {
  1619.             if (w2<220)
  1620.               {
  1621.                 b2++;
  1622.                 w2 = w2 << 1;
  1623.               }
  1624.             if (w2>440)
  1625.               {
  1626.                 b2--;
  1627.                 w2 = w2 >> 1;
  1628.               }
  1629.           } while (w2<220 || w2>440);
  1630.           if      ( w2>424 && w2<431) b1=0;
  1631.           else if ( w2>399 && w2<411) b1=1;
  1632.           else if ( w2>378 && w2<385) b1=2;
  1633.           else if ( w2>356 && w2<366) b1=3;
  1634.           else if ( w2>334 && w2<343) b1=4;
  1635.           else if ( w2>316 && w2<325) b1=5;
  1636.           else if ( w2>298 && w2<306) b1=6;
  1637.           else if ( w2>280 && w2<290) b1=7;
  1638.           else if ( w2>264 && w2<275) b1=8;
  1639.           else if ( w2>249 && w2<260) b1=9;
  1640.           else if ( w2>236 && w2<244) b1=10;
  1641.           else if ( w2>223 && w2<231) b1=11;
  1642.           b3 = (*(p+2) >> 4) + (*p & 0x10); /* Instrument */
  1643.         }
  1644.       b4 = 65;
  1645.       b5 = *(p+2) & 15; /* Command */
  1646.       b6 = *(p+3);      /* Command byte */
  1647.       switch (b5) /* Commands */
  1648.         {
  1649.           case 0: b5=0;break;    /* $A */
  1650.           case 1: b5=6;break;
  1651.           case 2: b5=5;break;
  1652.           case 3: b5=7;break;
  1653.           case 4: b5=8;break;
  1654.           case 0x0A: b5=4;break;
  1655.           case 0x0B: b5=2;break;
  1656.           case 0x0C:
  1657.              b4=b6;
  1658.              b5=0;
  1659.              b6=0;
  1660.              if (b4>64) b4=64;
  1661.              break;
  1662.           case 0x0D: b5=3;break;
  1663.           case 0x0F:
  1664.              b5=1;
  1665.              b6=b6*16;
  1666.              break;
  1667.           default: b5=0;
  1668.         }
  1669.       if (b5==0) b6=0;
  1670.       *(p) = b1 + (b2 << 4);
  1671.       *(p+1) = (b3 << 3) + (b4 & 7);
  1672.       *(p+2) = b5 + (b4 & 0xF8) * 2;
  1673.       *(p+3) = b6;
  1674.       p += 4; /* Next note */
  1675.     }
  1676. }
  1677.  
  1678. int ReadModule(nam)
  1679. char *nam;
  1680. {
  1681.   char fnam[100];
  1682.   size_t loadsize;
  1683.   unsigned apusana;
  1684.   unsigned int bpmpat[6];
  1685.   unsigned char *p;
  1686.  
  1687.   FILEok=0;
  1688.   gotoxy(66,20);
  1689.   cprintf("            ");
  1690.   gotoxy(3,47);
  1691.   cprintf(" %-75s","Loading module...");
  1692.  
  1693.   /* Free the memory previously allocated for samples */
  1694.   for (i=30;i>=0;i--) { free(sample[i]); sample[i] = NULL; }
  1695.   /* Free the memory allocated for patterns */
  1696.   for (i=0;i<stm.patnum;i++) { free(pattern[i]); pattern[i] = NULL; }
  1697.  
  1698.   strcpy(fnam,defdir);
  1699.   strcat(fnam,nam);
  1700.   if (!(f = fopen(fnam,"rb")))
  1701.     {
  1702.       sprintf(apu,"Error: %s!",sys_errlist[errno]);
  1703.       ShowError(apu);
  1704.       return -1;
  1705.     }
  1706.   if (lmode=='S' || lmode=='M') /* STM and MTM modules */
  1707.     {
  1708.       urpo = fread(&stm,sizeof(stm),1,f);
  1709.       if (stm.typ > 6)
  1710.         {
  1711.           ShowError("Not a recognized module!");
  1712.           fclose(f);
  1713.           return -2;
  1714.         }
  1715.       urpo = fread(&orders,128,1,f);
  1716.       gotoxy(3,47);
  1717.       cprintf("Loading patterns...");
  1718.       for (i=0;i<stm.patnum;i++)
  1719.         {
  1720.           if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
  1721.             {
  1722.               sprintf(apu,"Not enough memory to load pattern %d !",i);
  1723.               ShowError(apu);
  1724.               fclose(f);
  1725.               return -4;
  1726.             }
  1727.           if (!fread(pattern[i],sizeof(PA),1,f))
  1728.             {
  1729.               sprintf(apu,"Disk read error loading pattern %d !",i);
  1730.               ShowError(apu);
  1731.               fclose(f);
  1732.               return -5;
  1733.             }
  1734.         }
  1735.     }
  1736.   else if (lmode=='B') /* BPM modules */
  1737.     {
  1738.       urpo = fread(&bpm,sizeof(bpm),1,f);
  1739.       if ((bpm.typ & 63) != 1)
  1740.         {
  1741.           ShowError("Not a recognized module!");
  1742.           fclose(f);
  1743.           return -2;
  1744.         }
  1745.       /* Now copy all needed info to STM struct */
  1746.       memcpy(stm.name,bpm.name,20);
  1747.       memcpy(stm.tnam,bpm.tnam,8);
  1748.       if (bpm.typ & 0x80)
  1749.         stm.typ=2;
  1750.       else
  1751.         stm.typ=1;
  1752.       stm.ver=(bpm.typ & 63);
  1753.       stm.tempo= 12000 / (bpm.tempo_hi & 255);
  1754.       stm.patnum=bpm.patnum;
  1755.       stm.volume=127;
  1756.       for (i=0;i<31;i++)
  1757.         {
  1758.           memcpy(stm.inst[i].name,bpm.inst[i].name,12);
  1759.           stm.inst[i].name[12]=' ';
  1760.           stm.inst[i].length=bpm.inst[i].length;
  1761.           stm.inst[i].volume=(bpm.inst[i].volume * 64 / 100);
  1762.           stm.inst[i].loops=bpm.inst[i].loops;
  1763.           stm.inst[i].loope=bpm.inst[i].loope;
  1764.           stm.inst[i].rate=bpm.ihertz;
  1765.         }
  1766.       urpo = fread(&orders,256,1,f);
  1767.       /* Go over extra info bytes */
  1768.       fseek(f,10L,SEEK_CUR);
  1769.       gotoxy(3,47);
  1770.       cprintf("Loading patterns...");
  1771.       for (i=0;i<stm.patnum;i++)
  1772.         {
  1773.           urpo = fread(&bpmpat,sizeof(bpmpat),1,f); /* Read pattern header */
  1774.           if (bpmpat[5] != 64)
  1775.             {
  1776.               sprintf(apu,"Invalid pattern %d size (%d bytes) !",i,bpmpat[5]);
  1777.               ShowError(apu);
  1778.               fclose(f);
  1779.               return -8;
  1780.             }
  1781.           if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
  1782.             {
  1783.               sprintf(apu,"Not enough memory to load pattern %d !",i);
  1784.               ShowError(apu);
  1785.               fclose(f);
  1786.               return -4;
  1787.             }
  1788.           if (!fread(pattern[i],sizeof(PA),1,f))
  1789.             {
  1790.               sprintf(apu,"Disk read error loading pattern %d !",i);
  1791.               ShowError(apu);
  1792.               fclose(f);
  1793.               return -5;
  1794.             }
  1795.           for (j=0;j<1024;j+=4)
  1796.             {
  1797.               p = (unsigned char *)pattern[i] + j;
  1798.               if (*p < 0xFC) *p -= 32; /* Transpose 2 octaves down */
  1799.               *(p+1)=(*(p+1) << 3) + 8; /* Instrument, bits 0-5 -> BYTE1/8 */
  1800.               *(p+2)=(*(p+2) & 127 | 112); /* Volume to BYTE2/2 */
  1801.             }
  1802.         }
  1803.     }
  1804.   else if (lmode=='A') /* MOD modules */
  1805.     {
  1806.       urpo = fread(&mod,sizeof(mod),1,f);
  1807.       fseek(f,1080L,SEEK_SET);
  1808.       urpo = fread(&bpmpat,4,1,f);
  1809.       fseek(f,952L,SEEK_SET);
  1810.       if ( memcmp(&bpmpat,"M.K.",4) ) /* Check if this is 31-inst module */
  1811.         {
  1812.           fseek(f,472L,SEEK_SET);
  1813.           stm.ver = 15; /* 15-instrument module */
  1814.           mod.songlength=mod.inst[15].name[0];
  1815.         }
  1816.       else
  1817.         stm.ver = 31; /* 31-instrument module */
  1818.  
  1819.       /* Now copy all needed info to STM struct */
  1820.       memcpy(stm.name,mod.name,20);
  1821.       memcpy(stm.tnam,"Amiga NT",8);
  1822.       stm.typ = 2; /* Must be a module */
  1823.       stm.tempo = 96; /* Tempo? */
  1824.       stm.patnum = mod.songlength;
  1825.       stm.volume = 127;
  1826.       for (i=0;i<31;i++)
  1827.         {
  1828.           if (i>14 && stm.ver==15)
  1829.             stm.inst[i].length=0;
  1830.           else
  1831.             {
  1832.               if ( (! memcmp(mod.inst[i].name,"st-",3) ||
  1833.                     ! memcmp(mod.inst[i].name,"ST-",3) ) &&
  1834.                     mod.inst[i].name[5]==':')
  1835.                 memcpy(stm.inst[i].name,mod.inst[i].name+6,12);
  1836.               else
  1837.                 memcpy(stm.inst[i].name,mod.inst[i].name,12);
  1838.               stm.inst[i].name[12] = 0;
  1839.               _AX = mod.inst[i].length;
  1840.               asm xchg ah,al
  1841.               asm shl ax,1
  1842.               stm.inst[i].length = _AX;
  1843.               stm.inst[i].volume = mod.inst[i].volume;
  1844.               _AX = mod.inst[i].loops;
  1845.               asm xchg ah,al
  1846.               asm shl ax,1
  1847.               stm.inst[i].loops = _AX;
  1848.               _AX = mod.inst[i].loopl;
  1849.               if (_AX == 256)
  1850.                 stm.inst[i].loope = 65535;
  1851.               else
  1852.                 {
  1853.                   asm xchg ah,al
  1854.                   asm shl ax,1
  1855.                   stm.inst[i].loope = _AX + stm.inst[i].loops;
  1856.                 }
  1857.               stm.inst[i].rate = 8448; /* Sample hertz? */
  1858.             }
  1859.         }
  1860.       urpo = fread(&orders,128,1,f);
  1861.       if (stm.ver==31)
  1862.         urpo = fread(&bpmpat,4,1,f); /* Read over the M.K. signum */
  1863.       for (i=stm.patnum;i<128;i++)
  1864.         orders[i]=99;
  1865.       stm.patnum = 0;
  1866.       for (i=0;i<128;i++)
  1867.         if (orders[i]>stm.patnum && orders[i]<99)
  1868.           stm.patnum = orders[i];
  1869.       stm.patnum++;
  1870.       for (i=0;i<stm.patnum;i++)
  1871.         {
  1872.           gotoxy(3,47);
  1873.           cprintf("Converting pattern %d ...",i);
  1874.           if ((pattern[i] = (PA *)malloc(sizeof(PA)))==NULL)
  1875.             {
  1876.               sprintf(apu,"Not enough memory to load pattern %d !",i);
  1877.               ShowError(apu);
  1878.               fclose(f);
  1879.               return -4;
  1880.             }
  1881.           if (!fread(pattern[i],sizeof(PA),1,f))
  1882.             {
  1883.               sprintf(apu,"Disk read error loading pattern %d !",i);
  1884.               ShowError(apu);
  1885.               fclose(f);
  1886.               return -5;
  1887.             }
  1888.           ConvertPattern();
  1889.         }
  1890.     }
  1891.   else if (!urpo)
  1892.     {
  1893.       ShowError("Module Header Read Error!");
  1894.       fclose(f);
  1895.       return -3;
  1896.     }
  1897.   /* Load samples, if Akai initialized OK and we are reading a module. */
  1898.   if (AKAIok && (stm.typ & 2))
  1899.     {
  1900.       /* Load the samples */
  1901.       for (i=0;i<31;i++)
  1902.     {
  1903.       if (!stm.inst[i].length) continue; /* Don't load if 0 length */
  1904.       gotoxy(3,47);
  1905.       cprintf("Loading sample %d (%5u bytes)... ",i,stm.inst[i].length);
  1906.       loadsize = (size_t)stm.inst[i].length;
  1907.       if (stm.inst[i].length > 32752) stm.inst[i].length=32752;
  1908.       /* If loading STM samples, use 16 byte boundaries. */
  1909.       if ((loadsize & 0x0F) && (lmode=='S'))
  1910.         loadsize = (loadsize & 0xFFF0) + 0x10;
  1911.       if ((sample[i] = (char *)malloc(loadsize))==NULL)
  1912.         {
  1913.           sprintf(apu,"Not enough memory to load sample %d !",i+1);
  1914.           ShowError(apu);
  1915.           fclose(f);
  1916.           return -4;
  1917.         }
  1918.       /* If we hit the end of file, end the for-loop here. */
  1919.       if ((urpo=fread(sample[i],1,loadsize,f)) < loadsize-16)
  1920.         {
  1921.           if (loadsize > 16)
  1922.             {
  1923.               sprintf(apu,
  1924.               "Error loading sample %d (expected %d, read %d bytes) !",
  1925.               i+1,(unsigned int)loadsize,urpo);
  1926.               ShowError(apu);
  1927.               fclose(f);
  1928.               return -4;
  1929.             }
  1930.         }
  1931.       if (lmode=='B')
  1932.         {
  1933.           for (j=0;j<stm.inst[i].length;j++)
  1934.             *((char *)sample[i] + j) ^= 0x80;
  1935.         }
  1936.     }
  1937.     }
  1938.   fclose(f);
  1939.   gotoxy(66,20);
  1940.   cprintf("%-12s",nam);
  1941.   strcpy(defnam,nam);
  1942.   gotoxy(3,47);
  1943.   sprintf(apu,"Loaded OK, %ld bytes memory free.",coreleft());
  1944.   cprintf(" %-75s",apu);
  1945.   FILEok=1;
  1946.   return 0;
  1947. }
  1948.  
  1949. int SaveModule()
  1950. {
  1951.   int i;
  1952.   char fnam[100];
  1953.   size_t savesize;
  1954.   char *p;
  1955.  
  1956.   gotoxy(3,47);
  1957.   cprintf(" %-75s","Saving module...");
  1958.  
  1959.   strcpy(fnam,defdir);
  1960.   p=strchr(defnam,'.');
  1961.   if (stm.typ==1 || !AKAIok)
  1962.     {
  1963.       stm.typ = 5; /* MidiTracker type, 5=song, 6=module */
  1964.       if (p)
  1965.         strcpy(p,".MTS");
  1966.       else
  1967.         strcat(defnam,".MTS");
  1968.     }
  1969.   else if (stm.typ==2)
  1970.     {
  1971.       stm.typ = 6; /* MidiTracker type, 5=song, 6=module */
  1972.       if (p)
  1973.         strcpy(p,".MTM");
  1974.       else
  1975.         strcat(defnam,".MTM");
  1976.     }
  1977.   strcat(fnam,defnam);
  1978.   gotoxy(66,20);
  1979.   cprintf("%-12s",defnam);
  1980.  
  1981.   if (!(f = fopen(fnam,"wb")))
  1982.     {
  1983.       sprintf(apu,"Error: %s!",sys_errlist[errno]);
  1984.       ShowError(apu);
  1985.       return -1;
  1986.     }
  1987.   for (i=0;i<31;i++)
  1988.     {
  1989.       stm.inst[i].nt=MIDInt[i];
  1990.       stm.inst[i].ch=MIDIch[i];
  1991.       stm.inst[i].prg=MIDIprg[i];
  1992.     }
  1993.   urpo = fwrite(&stm,sizeof(stm),1,f);
  1994.   if (!urpo)
  1995.     {
  1996.       ShowError("Disk write error saving module header!");
  1997.       fclose(f);
  1998.       return -3;
  1999.     }
  2000.   urpo = fwrite(&orders,128,1,f);
  2001.   gotoxy(3,47);
  2002.   cprintf("Saving patterns...");
  2003.   for (i=0;i<stm.patnum;i++)
  2004.     {
  2005.       if (!fwrite(pattern[i],sizeof(PA),1,f))
  2006.         {
  2007.           sprintf(apu,"Disk write error saving pattern %d !",i);
  2008.           ShowError(apu);
  2009.           fclose(f);
  2010.           return -5;
  2011.         }
  2012.     }
  2013.   /* Saving samples, if Akai initialized OK. */
  2014.   if (AKAIok && (stm.typ & 2))
  2015.     {
  2016.       /* Save the samples */
  2017.       for (i=0;i<31;i++)
  2018.         {
  2019.           if (!stm.inst[i].length) continue; /* Don't save if 0 length */
  2020.           gotoxy(3,47);
  2021.           cprintf("Saving sample %d (%5u bytes)... ",i,stm.inst[i].length);
  2022.           savesize = (size_t)stm.inst[i].length;
  2023.           if (!fwrite(sample[i],savesize,1,f))
  2024.             {
  2025.               sprintf(apu,"Disk write error saving sample %d !",i+1);
  2026.               ShowError(apu);
  2027.               fclose(f);
  2028.               return -5;
  2029.             }
  2030.         }
  2031.     }
  2032.   fclose(f);
  2033.   gotoxy(3,47);
  2034.   cprintf(" %-75s","Module saved OK.");
  2035.   return 0;
  2036. }
  2037.  
  2038. int Screen()
  2039. {
  2040.   int i;
  2041.   textmode(C4350);
  2042.   textbackground(BLUE);
  2043.   clrscr();
  2044.   cprintf("\n");
  2045.   textcolor(LIGHTGRAY);
  2046.   cprintf(" ╔═════════╗                                                        ╔═════════╗\r\n");
  2047.   textcolor(YELLOW);
  2048.   gotoxy(14,2);
  2049.   cprintf("MidiTracker v0.9 Made in Finland by Patrick Aalto 1991\r\n");
  2050.   textcolor(LIGHTGRAY);
  2051.   cprintf(" ║         ╚════════════════════╦═════════════════╦════╦════════════╝         ║\r\n");
  2052.   cprintf(" ║ Module: ___________________  ║ ┌───┐┌───┐┌───┐ ║    ║                      ║\r\n");
  2053.   cprintf(" ║ Tempo : ___ ╔════════════════╣ │ « ││ > ││ » │ ║    ║                      ║\r\n");
  2054.   cprintf(" ║ Volume: ___ ║       00:00:00 ║ └───┘└───┘└───┘ ║    ║                      ║\r\n");
  2055.   cprintf(" ║ PatCnt: ___ ╚════════════════╣ ┌────────┐┌───┐ ║    ║                      ║\r\n");
  2056.   cprintf(" ║ Trackr: ________ v           ║ │  STOP  ││ ║ │ ║    ║                      ║\r\n");
  2057.   cprintf(" ╠══════════════════════════════╣ └────────┘└───┘ ║    ║                      ║\r\n");
  2058.   cprintf(" ║                              ╚═════════════════╣    ║                      ║\r\n");
  2059.   cprintf(" ║ Nr Name         Bytes    Hz Ch P/S Vol Pan Not ║    ║                      ║\r\n");
  2060.   cprintf(" ║  1 ____________ _____ _____ __ ___ ___ ___ ___ ║    ║                      ║\r\n");
  2061.   cprintf(" ║  2 ____________ _____ _____ __ ___ ___ ___ ___ ║    ╟────────┬──────┬──────╢\r\n");
  2062.   cprintf(" ║  3 ____________ _____ _____ __ ___ ___ ___ ___ ║    ║ VOLS   │ SAVE │      ║\r\n");
  2063.   cprintf(" ║  4 ____________ _____ _____ __ ___ ___ ___ ___ ║    ╟────────┼──────┼──────╢\r\n");
  2064.   cprintf(" ║  5 ____________ _____ _____ __ ___ ___ ___ ___ ║    ║ LOOP   │ INIT │ EXIT ║\r\n");
  2065.   cprintf(" ║  6 ____________ _____ _____ __ ___ ___ ___ ___ ╠════╩════════╧══════╧══════╣\r\n");
  2066.   cprintf(" ║  7 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2067.   cprintf(" ║  8 ____________ _____ _____ __ ___ ___ ___ ___ ║            ┌──────────────╢\r\n");
  2068.   cprintf(" ║  9 ____________ _____ _____ __ ___ ___ ___ ___ ╟────────────┤              ║\r\n");
  2069.   cprintf(" ║ 10 ____________ _____ _____ __ ___ ___ ___ ___ ║            └──────────────╢\r\n");
  2070.   cprintf(" ║ 11 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2071.   cprintf(" ║ 12 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2072.   cprintf(" ║ 13 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2073.   cprintf(" ║ 14 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2074.   cprintf(" ║ 15 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2075.   cprintf(" ║ 16 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2076.   cprintf(" ║ 17 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2077.   cprintf(" ║ 18 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2078.   cprintf(" ║ 19 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2079.   cprintf(" ║ 20 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2080.   cprintf(" ║ 21 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2081.   cprintf(" ║ 22 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2082.   cprintf(" ║ 23 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2083.   cprintf(" ║ 24 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2084.   cprintf(" ║ 25 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2085.   cprintf(" ║ 26 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2086.   cprintf(" ║ 27 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2087.   cprintf(" ║ 28 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2088.   cprintf(" ║ 29 ____________ _____ _____ __ ___ ___ ___ ___ ║                           ║\r\n");
  2089.   cprintf(" ║ 30 ____________ _____ _____ __ ___ ___ ___ ___ ╟─────┬─────┬─────┬─────┬───╢\r\n");
  2090.   cprintf(" ║ 31 ____________ _____ _____ __ ___ ___ ___ ___ ║ MTM │ STM │ BPM │ MOD │ D ║\r\n");
  2091.   cprintf(" ╠════════╤════════════════╤════════════════╤═════╩═════╧════╤╧═════╧═════╧═══╣\r\n");
  2092.   cprintf(" ║        │ Not I# Vol Cmd │ Not I# Vol Cmd │ Not I# Vol Cmd │ Not I# Vol Cmd ║\r\n");
  2093.   cprintf(" ║ ___:__ │ ___ __ ___ ___ │ ___ __ ___ ___ │ ___ __ ___ ___ │ ___ __ ___ ___ ║\r\n");
  2094.   cprintf(" ╠════════╧════════════════╧════════════════╧════════════════╧════════════════╣\r\n");
  2095.   cprintf(" ║                                                                            ║\r\n");
  2096.   cprintf(" ╚════════════════════════════════════════════════════════════════════════════╝\r\n");
  2097.   gotoxy(42,5);putch(16);
  2098.   gotoxy(79,22);putch(24);
  2099.   gotoxy(79,40);putch(25);
  2100.   gotoxy(56,5);putch(24);
  2101.   gotoxy(56,16);putch(25);
  2102.   textcolor(BLACK);
  2103.   gotoxy(4,3);cprintf("OVERALL");
  2104.   gotoxy(52,4);cprintf("LINK");
  2105.   gotoxy(18,6);cprintf("TIME:");
  2106.   gotoxy(71,3);cprintf("COMMAND");
  2107.   gotoxy(4,10);cprintf("INSTRUMENTS AND MIDI TRACKS");
  2108.   gotoxy(4,44);cprintf("PATTERN");
  2109.   gotoxy(53,21);cprintf("MT MODULES");
  2110.   gotoxy(53,19);cprintf("DIRECTORY");
  2111.   return 0;
  2112. }
  2113.  
  2114. void HandleMouse(mode)
  2115. int *mode;
  2116. {
  2117.   int oldmode = *mode;
  2118.   int x,y,done=0;
  2119.   do {
  2120.     if (!INTplaying) ClearMPU(); /* Keep incoming midi buffer clear */
  2121.     GetMouse(&mx,&my);
  2122.     if (mx==53 && my==18) *mode = 1; /* Drive */
  2123.     else if (mx>52 && my>21 && mx<77 && my<41 && mx!=65) *mode = 2; /* File */
  2124.     else if (mx>51 && my==42)
  2125.       {
  2126.     if (mx<57) *mode = 3; /* STM */
  2127.     else if (mx>57 && mx<63) *mode = 4; /* STS */
  2128.     else if (mx>63 && mx<69) *mode = 5; /* BPM */
  2129.     else if (mx>69 && mx<75) *mode = 6; /* MOD */
  2130.     else if (mx>75 && mx<79) *mode = 7; /* Dir */
  2131.     else *mode = 0;
  2132.       }
  2133.     else if (mx<72 && mx>65 && my==16) *mode=8; /* Send Init */
  2134.     else if (mx>72 && my==16) *mode=9; /* Exit */
  2135.     else if (mx>39 && my>3 && mx<45 && my<7) *mode=10; /* Play */
  2136.     else if (mx>34 && my>6 && mx<45 && my<10) *mode=11; /* Stop */
  2137.     else if (mx<34 && mx>31 && my>11 && my<43) *mode=12; /* Select Ch */
  2138.     else if (mx<50 && mx>46 && my>11 && my<43) *mode=13; /* Select Note */
  2139.     else if (mx<38 && mx>34 && my>11 && my<43) *mode=14; /* Select Prg */
  2140.     else if (mx<65 && mx>56 && my==16) *mode=15; /* LOOP ON/OFF */
  2141.     else if (mx>44 && my>6 && mx<50 && my<10) *mode=16; /* Pause */
  2142.     else if (mx>19 && mx<31 && my>11 && my<43) *mode=17; /* Display Toggle */
  2143.     else if (mx==56 && (my==5 || my==16)) *mode=18; /* Scroll links */
  2144.     else if (my>3 && my<7 && ((mx>34 && mx<40) ||
  2145.                   (mx>44 && mx<50))) *mode=19; /* Search */
  2146.     else if (mx<72 && mx>65 && my==14) *mode=20; /* Save */
  2147.     else if (mx==79 && (my==22 || my==40)) *mode=21; /* Scroll files */
  2148.     else if (mx<65 && mx>56 && my==14) *mode=22; /* VOLS ON/OFF */
  2149.     else
  2150.       *mode = 0;
  2151.  
  2152.     if (*mode != oldmode)
  2153.       {
  2154.     gotoxy(2,49);
  2155.     oldmode = *mode;
  2156.     switch(*mode)
  2157.       {
  2158.         case 0: cprintf("Move mouse to select option.           \r");break;
  2159.         case 1: cprintf("Click to change current drive.         \r");break;
  2160.         case 2: if (lmode=='D')
  2161.               cprintf("Click on directory to make current.    \r");
  2162.             else
  2163.               cprintf("Click on filename to load.             \r");
  2164.             break;
  2165.         case 3: cprintf("Click to handle MidiTracker modules.   \r");break;
  2166.         case 4: cprintf("Click to handle ScreamTracker modules. \r");break;
  2167.         case 5: cprintf("Click to handle B's ProTracker modules.\r");break;
  2168.         case 6: cprintf("Click to handle Amiga modules.         \r");break;
  2169.         case 7: cprintf("Click to select search directory.      \r");break;
  2170.         case 8: cprintf("Click to initialize synth(s).          \r");break;
  2171.         case 9: cprintf("Click to Exit MidiTracker.             \r");break;
  2172.         case 10:cprintf("Click to Play song.                    \r");break;
  2173.         case 11:cprintf("Click to Stop (and rewind) song.       \r");break;
  2174.         case 12:cprintf("Click to select MIDI channel.          \r");break;
  2175.         case 13:cprintf("Click to select fixed/transposed note. \r");break;
  2176.         case 14:cprintf("Click to select MIDI program / sample#.\r");break;
  2177.         case 15:cprintf("Click to toggle Looping Mode.          \r");break;
  2178.         case 16:cprintf("Click to Pause song.                   \r");break;
  2179.         case 17:cprintf("Click to toggle displayed data.        \r");break;
  2180.         case 18:cprintf("Click to scroll links.                 \r");break;
  2181.         case 19:cprintf("Click to search in pattern.            \r");break;
  2182.         case 20:cprintf("Click to save song/module.             \r");break;
  2183.         case 21:cprintf("Click to scroll files.                 \r");break;
  2184.         case 22:cprintf("Click to toggle Volume Mode.           \r");break;
  2185.       }
  2186.       }
  2187.     else if (GetClick(&mx,&my) && *mode)
  2188.       {
  2189.     gotoxy(2,49);
  2190.     cprintf("Working...                                         \r");
  2191.     switch(*mode)
  2192.       {
  2193.         /* -- Clicked on a new drive -- */
  2194.         case 1:
  2195.            if (SelectDrive())
  2196.          if (lmode == 'D')
  2197.            ShowDirs(defdir);
  2198.          else
  2199.            ShowFiles();
  2200.            break;
  2201.         /* -- Clicked on a file/directory -- */
  2202.         case 2:
  2203.            if (mx>65) x=1; else x=0;
  2204.            y = (my-22)*2+FILE1st;
  2205.            switch(lmode)
  2206.          {
  2207.            case 'M': case 'S': case 'B': case 'A':
  2208.              if (INTplaying)
  2209.                {
  2210.                  ShowError("Cannot load while playing!");
  2211.                  break;
  2212.                }
  2213.              if (allfiles[x+y][0])
  2214.                {
  2215.                  ClearSong();
  2216.                  ReadModule(allfiles[x+y]);
  2217.                  if (FILEok) ShowSong();
  2218.                }
  2219.              break;
  2220.            case 'D':
  2221.              if (alldirs[x+y][0])
  2222.                {
  2223.                  MouseOff();
  2224.                  ChangeDir(alldirs[x+y]);
  2225.                  ShowDirs(defdir);
  2226.                  MouseOn();
  2227.                }
  2228.              break;
  2229.          }
  2230.            break;
  2231.         /* -- Selection of input file types -- */
  2232.         case 3:
  2233.           strcpy(defext,"*.mt?");
  2234.           lmode='M';
  2235.           textcolor(BLACK);gotoxy(53,21);cprintf("MT MODULES ");
  2236.           FILElkm=ShowFiles();
  2237.           break;
  2238.         case 4:
  2239.           strcpy(defext,"*.st?");
  2240.           lmode='S';
  2241.           textcolor(BLACK);gotoxy(53,21);cprintf("ST MODULES ");
  2242.           FILElkm=ShowFiles();
  2243.           break;
  2244.         case 5:
  2245.           strcpy(defext,"*.bpm");
  2246.           lmode='B';
  2247.           textcolor(BLACK);gotoxy(53,21);cprintf("BP MODULES ");
  2248.           FILElkm=ShowFiles();
  2249.           break;
  2250.         case 6:
  2251.           strcpy(defext,"*.mod");
  2252.           lmode='A';
  2253.           textcolor(BLACK);gotoxy(53,21);cprintf("AMIGA MODS ");
  2254.           FILElkm=ShowFiles();
  2255.           break;
  2256.         case 7:
  2257.           lmode='D';
  2258.           textcolor(BLACK);gotoxy(53,21);cprintf("DIRECTORIES");
  2259.           FILElkm=ShowDirs(defdir);
  2260.           break;
  2261.         case 8:
  2262.           if (!INTplaying)
  2263.         SendInit();
  2264.           else
  2265.         ShowError("Cannot initialize while playing!");
  2266.           break;
  2267.         case 9:
  2268.           if (!INTplaying)
  2269.         done=1;
  2270.           else
  2271.         ShowError("Cannot exit while playing!");
  2272.           break;
  2273.         case 10:
  2274.           if (!INTplaying) Play();
  2275.           break;
  2276.         case 11:
  2277.           Stop();
  2278.               ShowTime(INTtime);
  2279.           break;
  2280.         case 12:
  2281.           SelectCh(my-12);
  2282.           break;
  2283.         case 13:
  2284.           SelectNote(my-12);
  2285.           break;
  2286.         case 14:
  2287.           SelectPrg(my-12);
  2288.           break;
  2289.         case 15:
  2290.           INTloop ^= 1;
  2291.           gotoxy(63,16);
  2292.           MouseOff();
  2293.           if (INTloop) putch(2); else putch(1);
  2294.           MouseOn();
  2295.           break;
  2296.         case 16:
  2297.           Pause();
  2298.           break;
  2299.         case 17:
  2300.           ToggleDisp();
  2301.           break;
  2302.         case 18:
  2303.           if (my==5 && INTord>0)
  2304.         INTord-=1;
  2305.           else if (my==16 && orders[INTord+1]<stm.patnum)
  2306.         INTord+=1;
  2307.           ShowOrd(INTord);
  2308.           INTpat=orders[INTord];
  2309.           ShowPat(INTpat,INTrow);
  2310.           break;
  2311.         case 19:
  2312.           if (mx<42 && (INTord>0 || INTrow>0))
  2313.         {
  2314.           if (!INTrow) { INTord-=1; INTrow=63; }
  2315.           else INTrow-=1;
  2316.         }
  2317.           else if (mx>42 && (orders[INTord+1]<stm.patnum ||
  2318.                  INTrow<63))
  2319.         {
  2320.           if (INTrow==63) { INTord+=1; INTrow=0; }
  2321.           else INTrow+=1;
  2322.         }
  2323.           ShowOrd(INTord);
  2324.           INTpat=orders[INTord];
  2325.           ShowPat(INTpat,INTrow);
  2326.           break;
  2327.         case 20:
  2328.           if (FILEok)
  2329.         SaveModule();
  2330.           else
  2331.         ShowError("No module loaded, cannot save!");
  2332.           break;
  2333.         case 21:
  2334.           if (my==22 && FILE1st>0)
  2335.                 {
  2336.           FILE1st-=2;
  2337.                   movetext(52,22,77,39,52,23);
  2338.                   gotoxy(52,22);
  2339.                   cprintf(" %-12s %-12s",
  2340.                             allfiles[FILE1st],allfiles[FILE1st+1]);
  2341.                 }
  2342.           else if (my==40 && FILE1st+36<FILElkm)
  2343.                 {
  2344.           FILE1st+=2;
  2345.                   movetext(52,23,77,40,52,22);
  2346.                   gotoxy(52,40);
  2347.                   cprintf(" %-12s %-12s",
  2348.                             allfiles[FILE1st+36],allfiles[FILE1st+37]);
  2349.                 }
  2350.           break;
  2351.         case 22:
  2352.           INTvols ^= 1;
  2353.           gotoxy(63,14);
  2354.           MouseOff();
  2355.           if (INTvols) putch(2); else putch(1);
  2356.           MouseOn();
  2357.           break;
  2358.         default: break;
  2359.       }
  2360.     oldmode = -1;
  2361.       }
  2362.  
  2363.   } while (!done);
  2364. }
  2365.  
  2366. main()
  2367. {
  2368.   for (i=30;i>=0;i--) sample[i]=NULL;
  2369.   for (i=0;i<128;i++) orders[i]=99;
  2370.   for (i=0;i<31;i++) MIDIprg[i]=128;
  2371.   if (!InitMouse())
  2372.     {
  2373.       cprintf("Sorry, but MidiTracker requires a mouse!\r\n");
  2374.       exit(1);
  2375.     }
  2376.   gettextinfo(&tinfo);
  2377.   Screen();
  2378.   textcolor(WHITE);
  2379.   FILEok = 0;
  2380.   MPUok = InitMPU();
  2381.   MouseOn();
  2382.   getcwd(defdir,64);
  2383.   if (defdir[strlen(defdir)-1] != '\\') strcat(defdir,"\\");
  2384.   ShowFiles();
  2385.   if (MPUok) AKAIok = InitAkai();
  2386.   InitLAPC(1);
  2387.   mode = -1;
  2388.   HandleMouse(&mode);
  2389.   MouseOff();
  2390.   InitLAPC(0);
  2391.   if (MPUok) ResetMPU();
  2392.   for (i=30;i>=0;i--) free(sample[i]);
  2393.   textattr(tinfo.attribute);
  2394.   textmode(tinfo.currmode);
  2395.   clrscr();
  2396.   return 0;
  2397. }
  2398.