/* SampPlay SAMPLE PLAYER                                               */
/* Play Samples with keyboard                                       */


#include  <io.h>
#include  <conio.h>
#include  <alloc.h>
#include  <dir.h>
#include  <dos.h>
#include  <bios.h>
#include  <stdio.h>
#include  <fcntl.h>
#include  <string.h>
#include  <stdlib.h>

#include  <sbc.h>
#include  <sbcvoice.h>
#include  <mkbrk.h>


#include  <loaddrv.c>

#define ALT 0x08;

/* Function Prototypes */
char far *LoadFile(char *szFilename) ;


char *note[25] = {"C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1",
                                 "C2","C#2","D2","D#2","E2","F2","F#2","G2","G#2","A2","A#2","B2","C3"};

char far *Sampbuf[25];
char fname[50][25];
char path[80];

int chan;
int dsp_res_p,dsp_rd_p,dsp_wr_p,dsp_datavail_p;
unsigned char midibyte;

int kbdmode = 0;


main(int argc,char **argv)
{
       int i;

       for(i = 0;i<25;i++)
               strcpy(fname[i],"");

       if(!init())
       {
               if(argc > 1)
                       loadset(argv[1]);

               chan = 0;

               textcolor(GREEN);

               draw_screen();

               while(1)
               {
                       if(kbdmode)
                               process_playkey();
                       else
                         if(kbhit())
                                process_key();
               }
       }
}



init()
{
        extern  char far * near voice_drv;
        int i;

        if ( ! GetEnvSetting() )
        {
                 if (sbc_check_card() & 4)
                 {
                               if (sbc_test_int())
                               {
                                        if (sbc_test_dma() >= 0)
                                        {
                                                 if ((voice_drv = LoadDriver("CT-VOICE.DRV")) != 0)
                                                 {
                                                               if (!ctvm_init())
                                                               {
                                                                       for(i = 0;i<25;i++)
                                                                               Sampbuf[i] = 0;
                                                                       strcpy(path,"*.*");
                                                                       ctvm_speaker(1);
                                                                       return(0);
                                                               }
                                                               else
                                                               {
                                                                 printf("Initialization of driver failed!\n");
                                                                 return(1);
                                                               }
                                                 }
                                                 else
                                                 {
                                                         printf("Error loading CT-VOICE.DRV!\n");
                                                         return(1);
                                                 }
                                        }
                                        else
                                        {
                                                 printf("Error on DMA channel.\n");
                                                 return(1);
                                        }
                               }
                               else
                               {
                                        printf("Error on interrupt.\n");
                                        return(1);
                               }
                 }
                 else
                 {
                               printf("Sound Blaster Card not found or wrong I/O settings.\n") ;
                               return(1);
                 }
        }
        else
        {
                 printf("BLASTER environment not set or incomplete or invalid.\n");
                 return(1);
        }
}

quit()
{
int i;
       for(i = 0; i < 25 ; i++)
               freemem(FP_SEG(Sampbuf[i]));

       ctvm_speaker(0);
       ctvm_terminate();

       textcolor(LIGHTGRAY);
       clrscr();
       exit(0);
}

draw_screen()
{
unsigned segp;
int i;
long freemem;
unsigned max_blocks;

               max_blocks = allocmem(0xffff,&segp);
               freemem = max_blocks;
               freemem = freemem << 4;

               clrscr();

               printf("SAMPPLAY Sample Player for SoundBlaster cards                Free memory: %ld\n",freemem);
               printf("---------------------------------------------\n\n");
               printf("(Alt-J) Jam on the keyboard!  (Alt-K) Load Key with Sample\n");
               printf("(Alt-L) List files  (Alt-P) Path  (Alt-S) Set save/load  (Alt-Z) Clear All\n\n");
/*
               for(i = 0;i<25;i++)
                 printf("Slot %d (%s) =>  %s\n",i,tonename[i],strupr(fname[i]));
*/
}



int process_key()
{
int scan,modifiers;

       scan = (bioskey(0) >> 8) & 0xFF;
       modifiers = bioskey(2);

       if(scan == 1) quit();

       if(modifiers & 8)
       {
               switch(scan) {
                       case 37 :                          /* Alt-K */
                               {
                                       printf("Press the key to load with sample");
                                       scan = (bioskey(0) >> 8) & 0xFF;

                                       switch(scan) {
                                               case 44 : loadsample(0);break;  /* z */
                                               case 31 : loadsample(1);break;  /* s */
                                               case 45 : loadsample(2);break;  /* x */
                                               case 32 : loadsample(3);break;  /* d */
                                               case 46 : loadsample(4);break;  /* c */
                                               case 47 : loadsample(5);break;  /* v */
                                               case 34 : loadsample(6);break;  /* g */
                                               case 48 : loadsample(7);break;  /* b */
                                               case 35 : loadsample(8);break;   /* h */
                                               case 49 : loadsample(9);break;    /* n */
                                               case 36 : loadsample(10);break;  /* j */
                                               case 50 : loadsample(11);break;  /* m */
                                               case 51 : loadsample(12);break;  /* , */

                                               case 16 : loadsample(12);break;  /* q */
                                               case 3  : loadsample(13);break;  /* 2 */
                                               case 17 : loadsample(14);break;  /* w */
                                               case 4  : loadsample(15);break;  /* 3 */
                                               case 18 : loadsample(16);break;  /* e */
                                               case 19 : loadsample(17);break;  /* f */
                                               case 6  : loadsample(18);break;  /* 5 */
                                               case 20 : loadsample(19);break;  /* t */
                                               case 7  : loadsample(20);break;  /* 6 */
                                               case 21 : loadsample(21);break;  /* y */
                                               case 8  : loadsample(22);break;  /* 7 */
                                               case 22 : loadsample(23);break;  /* u */
                                               case 23 : loadsample(24);break;  /* i */
                                       }
                                       draw_screen();
                               }break;
          /*   case 0x24 : goto_kbdmode();break;  */
                       case 0x26 : listfiles();break;     /* Alt-L */
                       case 0x19 : changepath();break;    /* Alt-P */
                       case 0x1f : setsaveload();break;   /* Alt-S */
                       case 0x2C : clearall();break;      /* Alt-Z */
               }
       }
       else
       {
               switch(scan) {
                       case 0x25: goto_kbdmode();          /* K */

               }
       }
}


unsigned char old_key,old_release;

process_playkey()
{
unsigned char key;


       key=get_mkbrk_code();

       if(key != old_key)
       {
               if(key >= 0x80)
               {
                       if((key-0x80) == old_key)
                       {
                               ctvm_stop();
                               old_key = key;
                       }
               }
               else
               {
                       if(old_key < 0x80)
                               ctvm_stop();

                       switch(key) {
                               case 44 : play(Sampbuf[0]);break;                /* z */
                               case 31 : play(Sampbuf[1]);break;                /* s */
                               case 45 : play(Sampbuf[2]);break;                /* x */
                               case 32 : play(Sampbuf[3]);break;               /* d */
                               case 46 : play(Sampbuf[4]);break;               /* c */
                               case 47 : play(Sampbuf[5]);break;               /* v */
                               case 34 : play(Sampbuf[6]);break;               /* g */
                               case 48 : play(Sampbuf[7]);break;               /* b */
                               case 35 : play(Sampbuf[8]);break;               /* h */
                               case 49 : play(Sampbuf[9]);break;               /* n */
                               case 36 : play(Sampbuf[10]);break;               /* j */
                               case 50 : play(Sampbuf[11]);break;               /* m */
                               case 51 : play(Sampbuf[12]);break;               /* , */

                               case 16 : play(Sampbuf[12]);break;               /* q */
                               case 3  : play(Sampbuf[13]);break;              /* 2 */
                               case 17 : play(Sampbuf[14]);break;             /* w */
                               case 4  : play(Sampbuf[15]);break;             /* 3 */
                               case 18 : play(Sampbuf[16]);break;             /* e */
                               case 19 : play(Sampbuf[17]);break;              /* f */
                               case 6  : play(Sampbuf[18]);break;             /* 5 */
                               case 20 : play(Sampbuf[19]);break;             /* t */
                               case 7  : play(Sampbuf[20]);break;             /* 6 */
                               case 21 : play(Sampbuf[21]);break;            /* y */
                               case 8  : play(Sampbuf[22]);break;           /* 7 */
                               case 22 : play(Sampbuf[23]);break;           /* u */
                               case 23 : play(Sampbuf[24]);break;           /* i */

                               case  1 : exit_kbdmode();break;
                       }
                       old_key = key;
               }
       }
}


goto_kbdmode()
{
       init_mkbrk();
       kbdmode = 1;
       gotoxy(1,22);
       printf("KEYBOARD MODE");
}

exit_kbdmode()
{
/*      while(get_mkbrk_code() != 0x81); */
       exit_mkbrk();
       kbdmode = 0;
       draw_screen();
}


play(char far *buf)
{
       ctvm_stop();

       if(buf != 0)
       {
               buf += ((VOCHDR far *)buf)->voice_offset ;
               ctvm_output(buf);
       }
}


listfiles()
{
struct ffblk ffblk;
int done;

       clrscr();

       printf("Path: %s\n\n",path);
       done = findfirst("*.*",&ffblk,0);
       while (!done)
       {
               printf("%16s", ffblk.ff_name);
               done = findnext(&ffblk);
       }
       printf("\n\nPress any key...");
       getch();
       draw_screen();
}

changepath()
{
char temppath[80];

       clrscr();
       printf("Enter new path (%s): ",path);
       gets(temppath);

       if(strlen(temppath) != 0)
       {
               if(chdir(temppath))
                       printf("Couldn't change to that path!\n");
               else
               {
                       strcpy(path,temppath);
                       printf("New path: %s\n",strupr(path));
               }
               delay(1000);
       }
       draw_screen();
}

setsaveload()
{
int fhand;
char textlen;
char setfname[80] = "";
int scan,i;

       clrscr();
       printf("(S)ave (L)oad (A)bort\n\n");

       scan = 0;
       while((scan != 0x1f) && (scan != 0x26) && (scan !=0x1e))
         scan = (bioskey(0) >> 8) & 0xFF;

       switch(scan){
         case 0x1f :                   /* Save Set */
         {
                       printf("Name of Set to save: ");
                       gets(setfname);

                       if(strstr(strupr(setfname),".SET") == NULL)
                               strcat(setfname,".SET");

                       if((fhand = _creat(setfname,0)) != -1)
                       {
                               if((fhand = _open(setfname,O_WRONLY|O_TEXT)) != -1)
                               {
                                       for(i = 0; i < 25 ;i++)
                                       {
                                               textlen = strlen(fname[i]);
                                               _write(fhand,&textlen,1);
                                               _write(fhand,fname[i],(unsigned)textlen);
                                       }
                                       _close(fhand);

                               }
                               else
                                       printf("Error opening %s!\n",strupr(setfname));
                       }
                       else
                               printf("Error creating %s!\n",strupr(setfname));
               } break;

         case 0x26 :                  /* Load Set  */
         {
                       printf("Name of Set to load: ");
                       gets(setfname);
                       loadset(setfname);
         }
       }
       draw_screen();
}

loadset(char *sn)
{
int fhand,i;
char textlen;
char infname[80] = "";
char settmp[80];

       strcpy(settmp,sn);

       if(strstr(strupr(settmp),".SET") == NULL)
               strcat(settmp,".SET");

       if( (fhand = _open(settmp,O_RDONLY|O_TEXT)) != -1)
       {
               for(i = 0; i < 25 ; i++)
               {
                       freemem(FP_SEG(Sampbuf[i]));
                       strcpy(fname[i],"");
               }

               for(i = 0; i < 25 ; i++)
               {
                       _read(fhand,&textlen,1);

                       if(textlen != 0)
                       {
                               _read(fhand,infname,(unsigned)textlen);
                               infname[textlen] = 0;
                               if ( (Sampbuf[i] = LoadFile(strcat(infname,".VOC"))) != 0 )
                               {
                                       infname[strchr(infname,'.')-infname] = 0;
                                       strcpy(fname[i],infname);
                               }
                               else
                               {
                                       printf("Error loading %s\n",strupr(infname));
                                       delay(1000);
                               }
                       }
               }
               _close(fhand);
       }
       else
       {
               printf("Couldn't load %s!\n",strupr(settmp));
               delay(1000);
       }
}



loadsample(int slot)
{
char tempname[50];

       clrscr();

       printf("VOC sample to assign to %s: ",note[slot]);
       gets(tempname);

       if(strlen(tempname) != 0)
       {
               if(strstr(strupr(tempname),".VOC") == NULL)
               strcat(tempname,".VOC");

               freemem(FP_SEG(Sampbuf[slot]));

               if ( (Sampbuf[slot] = LoadFile(tempname)) != 0 )
               {
                       tempname[strchr(tempname,'.')-tempname] = 0;
                       strcpy(fname[slot],tempname);
                       printf("Loaded OK.\n");
               }
               delay(1000);
       }
       draw_screen();
}

clearall()
{
int i,scan;

       printf("Clear All (y\\n)?");

       scan = 0;
       while( (scan != 21) && (scan != 49) )
               scan = (bioskey(0) >> 8) & 0xFF;

       if(scan == 21)
       {
               for(i = 0; i < 25 ; i++)
               {
                       freemem(FP_SEG(Sampbuf[i]));
                       Sampbuf[i] = 0;
                       strcpy(fname[i],"");
               }
       }
       draw_screen();
}


char far *LoadFile (char *szFilename)
{
        char        far *lpFileBuf=0, far *lpTmpPtr ;
        int         Handle ;
        unsigned    wByteRead;
        long        lFileSize ;


        /* open file */
        if ((Handle=_open(szFilename,O_RDONLY)) != -1)
        {
                 lFileSize = filelength(Handle) ;

                 if (allocmem((unsigned)((lFileSize+15) >> 4),&wByteRead) == -1)
                 {
                               FP_SEG(lpFileBuf) = wByteRead ;
                               FP_OFF(lpFileBuf) = 0 ;

                               lpTmpPtr = lpFileBuf ;

                               do
                               {
                                        if (DosRead(Handle,lpTmpPtr,0x8000,&wByteRead) != 0)
                                        {
                                                 if ( !(FP_OFF(lpTmpPtr) += wByteRead) )
                                                               FP_SEG(lpTmpPtr) += 0x1000 ;
                                        }
                                        else
                                        {
                                                 printf("Load file error.\n");
                                                 wByteRead = 0 ;
                                                 lpFileBuf = 0 ;
                                                 freemem(FP_SEG(lpFileBuf)) ;
                                        }

                               } while (wByteRead == 0x8000) ;
                 }
                 else
                               printf("Memory allocation error.\n");

                 _close(Handle) ;
        }
        else
                 printf("Open %s fails.\n",strupr(szFilename)) ;


        return(lpFileBuf) ;
}



DosRead (int Handle, char far *Buffer, unsigned wLen, unsigned *wByteRead)
{
        union REGS regs;
        struct SREGS segregs;

        regs.h.ah = 0x3f ;
        regs.x.bx = Handle;
        regs.x.dx = FP_OFF(Buffer);
        regs.x.cx = wLen;
        segregs.ds = FP_SEG(Buffer);

        intdosx(&regs, &regs, &segregs);

        if(regs.x.cflag)    /* error */
                 *wByteRead = 0;
        else
                 *wByteRead = regs.x.ax ;


        return(*wByteRead);
}