/* ------------------------------------------------------------------------ */
/*  @@ Source Documentation                         *** C Version ***       */
/*                                                                          */
/*  TITLE : DEMOWMP.C                                                       */
/*                                                                          */
/*  DESCRIPTION :                                                           */
/*      This program demostrates how to perform Wave out using the          */
/*      CTWMEM.DRV driver. The Wave out is using the Conventional           */
/*      memory method.                                                      */
/*                                                                          */
/*      The program retrieves BLASTER environment for the Card settings     */
/*      and passes it to the driver.                                        */
/*                                                                          */
/*      Note that the program included the module LOADDRV.C to load         */
/*      the loadable CTWMEM.DRV into memory.                                */
/*      The input WAV file is limited by convetional memory availablle.     */
/*                                                                          */
/*  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

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

#include "sbkwave.h"
#include "sbkmacro.h"
#include "sbkx.h"
#include "loaddrv.c"


#define TWO_KBYTES  2048l
#define PARA_ADJ    15l      /* 15 bytes for paragraph adjustment */

/*
## DMA_UNIT is unit of half embedded DMA in size of 2 kbytes .
## Change this value (from 1 - 16) if allocating own DMA buffer.
## This value effect the smoothy of sound output proportionally.
*/
#define DMA_UNIT    4
#define DMA_SIZE    ((DMA_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)


/* Function Prototypes */
char far *LoadFile(char *szFilename) ;
int PrepareCTWMEMDrv(char * BlasterEnv) ;
int SetOutputParam(void) ;
void OutputWave (WORD wIOHandle,BYTE far *lpBuf) ;

/* Globla variable */
volatile WORD ct_wave_status ;      /* wave i/o status */
static char far * lpOrigin ;        /* original pointer of driver buffer */


main(int argc, char * argv[])
{
    char far *lpWaveBuf ;
    char * BlasterEnv ;
    WORD  wIOHandle ;


    if (argc < 2)
    {
        printf("\nUsage : DEMOWMP wav_filename") ;
        exit (0) ;
    }

    printf ("\nPlay %s at conventional memory.",argv[1]) ;

    /* Retrieve the BLASTER environment settings */
    if ((BlasterEnv = getenv("BLASTER")) != NULL)
    {
        if (!PrepareCTWMEMDrv(BlasterEnv))
        {
            if (!ctwmInit())
            {
                if ((lpWaveBuf = LoadFile(argv[1])) != NULL)
                {
                    wIOHandle = (WORD)SetOutputParam() ;
                    if ((int)wIOHandle != -1)
                        OutputWave(wIOHandle,(BYTE far *)lpWaveBuf) ;

                    sbkFreeMem(lpWaveBuf) ;
                }
                ctwmTerminate() ;
            }
            /* free driver buffer */
            sbkFreeMem(lpOrigin) ;
        }
    }
    else
        printf("BLASTER environment not set or incomplete or invalid.\n") ;

    return 0 ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*  PrepareCTWMEMDrv(char * BlasterEnv)                                     */
/*                                                                          */
/*  Description :                                                           */
/*      Load and endorse CTWMEM.DRV.                                        */
/*                                                                          */
/*  Entry :                                                                 */
/*      BlasterEnv - pointer to the BLASTER environment.                    */
/*                                                                          */
/*  Exit :                                                                  */
/*      zero if sucessful, non-zero otherwise.                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int PrepareCTWMEMDrv(char * BlasterEnv)
{
    DWORD   dwVersion = 0 ;


    if ((CTwmemDrv = sbkLoadDriver("CTWMEM.DRV",UNUSED,
                        (char far **)&lpOrigin)) != NULL)
    {
        /* Retrieves CTWMEM.DRV version */
        if (!ctwmGetParam(CTWAV_DRIVERVERSION,(DWORD far *)&dwVersion))
        {
            if ((dwVersion & 0xffff) >= 0x0305)
            {
                /* Passes BLASTER environment settings to driver */
                if (!ctwmGetEnvSettings((char far *)BlasterEnv))
                    return(0) ;
                else
                    printf("\nDriver : BLASTER environment is not valid");
            }
            else
            {
                printf("\nInvalid CTWMEM.DRV - ") ;
                printf("I need CTWMEM.DRV version 3.05 or higher.\n") ;
            }
        }
        else
            printf("\nDriver : Unrecognized CTWMEM.DRV\n");
    }
    return(1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   char far *LoadFile (char *szFilename)                                  */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Load file into memory.                                             */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       szFileName :- File to be loaded.                                   */
/*                                                                          */
/*   EXIT:                                                                  */
/*       Pointer to the loaded memory buffer if successfull, else returns   */
/*       NULL pointer.                                                      */
/*                                                                          */
/* ------------------------------------------------------------------------ */

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


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

        if ((lpFileBuf = sbkAllocMem((DWORD)(lFileSize + 15l))) != NULL)
        {
            lpTmpPtr = lpFileBuf ;

            do
            {
                FPSEG(lpTmpPtr) += (FPOFF(lpTmpPtr) >> 4) ;
                FPOFF(lpTmpPtr) &= 0x000f ;

                if (sbkDosRead(Handle,lpTmpPtr,0x8000,(WORD far *)&wByteRead))
                {
                    printf("Load file error.\n");
                    wByteRead = 0 ;
                    lpFileBuf = 0 ;
                    sbkFreeMem(lpFileBuf) ;
                }
                else
                    FPOFF(lpTmpPtr) += wByteRead ;

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

        sbkDosClose(Handle) ;
    }
    else
        printf("\nOpen %s failed.",szFilename) ;

    return(lpFileBuf) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   SetOutputParam(void)                                                   */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Set the necessary output parameters.                               */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       none.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       i/o wave handle if successful otherwise return -1.                 */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int SetOutputParam(void)
{
    DWORD dwValue;
    WORD  wIOHandle ;
    char  far * lpDmaBuf ;


    if (!ctwmGetParam(CTWAV_IOHANDLES,(DWORD far *)&dwValue))
    {
        if (dwValue)
        {   /* wave i/o handle */
            wIOHandle = (WORD)(dwValue - 1) ;

            /* set i/o wave status */
            if (!ctwmSetIOParam(wIOHandle,CTWAV_IO_LPSTATUSWORD,
                      (DWORD)(WORD far *)&ct_wave_status))
                {
                /* Allocate two DMA buffer. */
                if ((lpDmaBuf = sbkAllocMem((DWORD)(DMA_SIZE * 2l))) != NULL)
                {
                    /* convert to 32-bit linear address */
                    dwValue = (DWORD)(((DWORD)FPSEG(lpDmaBuf) << 4) +
                                 FPOFF(lpDmaBuf)) ;

                    /* Set up DMA buffer. If failed, the DMA buffer
                       may have crossed the 64 k boundary, thus use
                       the 2nd Dma buffer */
                    if (!ctwmSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                        return((int)wIOHandle) ;

                    dwValue += (DWORD)DMA_SIZE ;
                    if (!ctwmSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                        return((int)wIOHandle) ;

                    printf ("\nDriver : Error setting DMA buffer.") ;
                }
                else
                    printf("\nDOS : Error allocating DMA buffer.") ;
            }
            else
                printf ("\nError setting ct_wave_status.") ;
        }
        else
            printf ("\nI/O wave handle unavailable.") ;
    }
    else
        printf ("\nError retrieving i/o wave handles.") ;

    return(-1) ;

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   OutputWave (WORD wIOHandle,BYTE far *lpWaveBuf)                        */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Output Wave from a memory buffer. The user is allowed to control   */
/*       the Wave output from the keyboard.                                 */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       lpWaveBuf  - Memory buffer to be output.                           */
/*       wIOHandle  - i/o wave handle.                                      */
/*                                                                          */
/*   EXIT:                                                                  */
/*      none.                                                               */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void OutputWave (WORD wIOHandle,BYTE far *lpWaveBuf)
{

    WORD  wKey, Pause = 0 ;
    WORD  fExit = 1 ;


    /* turn on speaker */
    ctwmSetSpeaker(1) ;

    if (!ctwmOutputCM(wIOHandle,lpWaveBuf))
    {
        printf("\n\t[Esc] - to stop\n");
        printf("\t[P  ] - to pause\n");
        printf("\t[C  ] - to continue\n");

        /* loop until Wave stop */
        while (fExit)
        {
            if(!ct_wave_status)
                ctwmOutputCM(wIOHandle,lpWaveBuf) ;

            if (sbkBiosKeybrd(KEYBRD_READY))
            {
                wKey = (WORD)(sbkBiosKeybrd((WORD)KEYBRD_READ) & 0xff) ;

                switch (wKey)
                {
                    case 0x1b :
                        printf ("\nWave stop.") ;
                        ctwmStop(wIOHandle) ;
                        fExit = 0 ;
                        break ;

                    case 'P' :
                    case 'p' :
                        if (!Pause)
                        {
                            printf("\nWave pauses...") ;
                            ctwmPause(wIOHandle) ;
                            Pause = 1 ;
                        }
                        break ;

                    case 'C' :
                    case 'c' :
                        if (Pause)
                        {
                            printf("\nWave continues...") ;
                            ctwmContinue(wIOHandle) ;
                            Pause = 0 ;
                        }
                        break ;
                }
            }
        }
    }
    else
    {
        printf("\nDriver : Error output Wave.") ;
        printf(" - %x",ctwmGetDrvError()) ;
    }
}
/* End of file */
