/* MIDIPlay SAMPLE PLAYER, plays samples triggered from MIDI in         */
/* Vet i fan om det kommer att funka det h�r... DSP:n anv�nds ju        */
/* b�de av Voice och MIDI!  J�vla skit...                                                                       */

#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  "\dvl\bc\sbdevel\loaddrv.c"

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

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

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


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

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

       if(!init())
       {
               if(argc > 1)
                       loadset(argv[1]);
               if(argc == 3)
                       chkmidivalid(argv[2]);
               else
                       chan = 0;

               textcolor(GREEN);

               draw_screen();

               while(1)
               {
                       if(bioskey(1))
                       {
                         if(! process_key())
                         break;
                       }
                /*  midi(); */

               }
               quit();
       }
}



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<16;i++)
                                                                               Sampbuf[i] = 0;
                                                                       strcpy(path,"*.*");
                                                                       dsp_rd_p = ct_io_addx+0xA;
                                                                       dsp_wr_p = ct_io_addx+0xC;
                                                                       dsp_datavail_p = ct_io_addx+0xE;
                                                                       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 <16 ; i++)
               freemem(FP_SEG(Sampbuf[i]));

       ctvm_speaker(0);
       ctvm_terminate();

       textcolor(LIGHTGRAY);
       clrscr();
}

draw_screen()
{
unsigned segp;
int i;
               clrscr();

               printf("SAMPPLAY Sample Player for SoundBlaster cards                Free blocks: %u\n",allocmem(0xffff,&segp));
               printf("---------------------------------------------                MIDI Channel: %d\n\n",chan+1);
               printf("(0-F) Load Sample into slot  (M)IDI Channel\n");
               printf("(L)ist files  (P)ath  (S)et save/load                \n\n");
               for(i = 0;i<16;i++)
                 printf("Slot %X  (Note number %d)  =>  %s\n",i,60+i,strupr(fname[i]));
}



int process_key()
{
int scan;

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

               if(scan == 1) return(0);

               switch(scan) {
                 case 2 : loadsample(1);break;
                 case 3 : loadsample(2);break;
                 case 4 : loadsample(3);break;
                 case 5 : loadsample(4);break;
                 case 6 : loadsample(5);break;
                 case 7 : loadsample(6);break;
                 case 8 : loadsample(7);break;
                 case 9 : loadsample(8);break;
                 case 10 : loadsample(9);break;
                 case 11 : loadsample(0);break;
                 case 0x1e : loadsample(0xA);break;
                 case 0x30 : loadsample(0xB);break;
                 case 0x2e : loadsample(0xC);break;
                 case 0x20 : loadsample(0xD);break;
                 case 0x12 : loadsample(0xE);break;
                 case 0x21 : loadsample(0xF);break;

                 case 0x32 : setmidichan();break;
                 case 0x26 : listfiles();break;
                 case 0x19 : changepath();break;
                 case 0x1f : setsaveload();
               }
               return(1);
}



midi()
{
       getmidibyte();
       if(midibyte == 0x90+chan)               /* note on */
       {
               getmidibyte();                  /* note number */
               if((midibyte >= 60) && (midibyte <= 75))
                       if(Sampbuf[midibyte-60] != 0)
                               playsamp(Sampbuf[midibyte-60]);
       }
       if(midibyte == 0x80 +chan)              /* note off */
       {
               ctvm_stop();
       }
}

getmidibyte()
{
       while((inportb(dsp_wr_p) & 128) == 128);
       outportb(dsp_wr_p,0x30);  /* MIDI READ command */
       while((inportb(dsp_datavail_p) & 128) == 0);
       midibyte = inportb(dsp_rd_p);
}


playsamp(char far *buf)
{
        buf += ((VOCHDR far *)buf)->voice_offset ;
        ctvm_output(buf);
}


setmidichan()
{
char midichan[5];
       clrscr();
       printf("New MIDI receiving channel: ");
       gets(midichan);
       chkmidivalid(midichan);
       draw_screen();
}

chkmidivalid(char *mc)
{
       if( (atoi(mc) > 16) || (atoi(mc) < 1) )
       {
               printf("Invalid channel entry.\n");
               delay(1000);
       }
       else
         chan = atoi(mc)-1;
}


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<16 ;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 <16 ; i++)
               {
                       freemem(FP_SEG(Sampbuf[i]));
                       strcpy(fname[i],"");
               }

               for(i = 0; i <16 ; 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 file to load into slot %X: ",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();
}

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);
}