123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /*
- Copyright (C) 1994-1995 Apogee Software, Ltd.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- /**********************************************************************
- module: PCFX.C
- author: James R. Dose
- date: April 1, 1994
- Low level routines to support PC sound effects created by Muse.
- (c) Copyright 1994 James R. Dose. All Rights Reserved.
- **********************************************************************/
- #include <dos.h>
- #include <stdlib.h>
- #include <conio.h>
- #include "dpmi.h"
- #include "task_man.h"
- #include "interrup.h"
- #include "pcfx.h"
- #define TRUE ( 1 == 1 )
- #define FALSE ( !TRUE )
- static void PCFX_Service( task *Task );
- static long PCFX_LengthLeft;
- static char *PCFX_Sound = NULL;
- static int PCFX_LastSample;
- static short PCFX_Lookup[ 256 ];
- static int PCFX_UseLookupFlag = FALSE;
- static int PCFX_Priority;
- static unsigned long PCFX_CallBackVal;
- static void ( *PCFX_CallBackFunc )( unsigned long ) = NULL;
- static int PCFX_TotalVolume = PCFX_MaxVolume;
- static task *PCFX_ServiceTask = NULL;
- static int PCFX_VoiceHandle = PCFX_MinVoiceHandle;
- int PCFX_Installed = FALSE;
- int PCFX_ErrorCode = PCFX_Ok;
- #define PCFX_SetErrorCode( status ) \
- PCFX_ErrorCode = ( status );
- /*---------------------------------------------------------------------
- Function: PCFX_ErrorString
- Returns a pointer to the error message associated with an error
- number. A -1 returns a pointer the current error.
- ---------------------------------------------------------------------*/
- char *PCFX_ErrorString
- (
- int ErrorNumber
- )
- {
- char *ErrorString;
- switch( ErrorNumber )
- {
- case PCFX_Warning :
- case PCFX_Error :
- ErrorString = PCFX_ErrorString( PCFX_ErrorCode );
- break;
- case PCFX_Ok :
- ErrorString = "PC FX ok.";
- break;
- case PCFX_NoVoices :
- ErrorString = "No free voices available to PC FX.";
- break;
- case PCFX_VoiceNotFound :
- ErrorString = "No voice with matching handle found.";
- break;
- case PCFX_DPMI_Error :
- ErrorString = "DPMI Error in PCFX.";
- break;
- default :
- ErrorString = "Unknown PC FX error code.";
- break;
- }
- return( ErrorString );
- }
- /**********************************************************************
- Memory locked functions:
- **********************************************************************/
- #define PCFX_LockStart PCFX_Stop
- /*---------------------------------------------------------------------
- Function: PCFX_Stop
- Halts playback of the currently playing sound effect.
- ---------------------------------------------------------------------*/
- int PCFX_Stop
- (
- int handle
- )
- {
- unsigned flags;
- if ( ( handle != PCFX_VoiceHandle ) || ( PCFX_Sound == NULL ) )
- {
- PCFX_SetErrorCode( PCFX_VoiceNotFound );
- return( PCFX_Warning );
- }
- flags = DisableInterrupts();
- // Turn off speaker
- outp( 0x61, inp( 0x61 ) & 0xfc );
- PCFX_Sound = NULL;
- PCFX_LengthLeft = 0;
- PCFX_Priority = 0;
- PCFX_LastSample = 0;
- RestoreInterrupts( flags );
- if ( PCFX_CallBackFunc )
- {
- PCFX_CallBackFunc( PCFX_CallBackVal );
- }
- return( PCFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_Service
- Task Manager routine to perform the playback of a sound effect.
- ---------------------------------------------------------------------*/
- static void PCFX_Service
- (
- task *Task
- )
- {
- unsigned value;
- if ( PCFX_Sound )
- {
- if ( PCFX_UseLookupFlag )
- {
- value = PCFX_Lookup[ *PCFX_Sound ];
- PCFX_Sound++;
- }
- else
- {
- value = *( short int * )PCFX_Sound;
- PCFX_Sound += sizeof( short int );
- }
- if ( ( PCFX_TotalVolume > 0 ) && ( value != PCFX_LastSample ) )
- {
- PCFX_LastSample = value;
- if ( value )
- {
- outp( 0x43, 0xb6 );
- outp( 0x42, value );
- outp( 0x42, value >> 8 );
- outp( 0x61, inp( 0x61 ) | 0x3 );
- }
- else
- {
- outp( 0x61, inp( 0x61 ) & 0xfc );
- }
- }
- if ( --PCFX_LengthLeft == 0 )
- {
- PCFX_Stop( PCFX_VoiceHandle );
- }
- }
- }
- /*---------------------------------------------------------------------
- Function: PCFX_VoiceAvailable
- Checks if a voice can be play at the specified priority.
- ---------------------------------------------------------------------*/
- int PCFX_VoiceAvailable
- (
- int priority
- )
- {
- if ( priority < PCFX_Priority )
- {
- return( FALSE );
- }
- return( TRUE );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_Play
- Starts playback of a Muse sound effect.
- ---------------------------------------------------------------------*/
- int PCFX_Play
- (
- PCSound *sound,
- int priority,
- unsigned long callbackval
- )
- {
- unsigned flags;
- if ( priority < PCFX_Priority )
- {
- PCFX_SetErrorCode( PCFX_NoVoices );
- return( PCFX_Warning );
- }
- PCFX_Stop( PCFX_VoiceHandle );
- PCFX_VoiceHandle++;
- if ( PCFX_VoiceHandle < PCFX_MinVoiceHandle )
- {
- PCFX_VoiceHandle = PCFX_MinVoiceHandle;
- }
- flags = DisableInterrupts();
- PCFX_LengthLeft = sound->length;
- if ( !PCFX_UseLookupFlag )
- {
- PCFX_LengthLeft >>= 1;
- }
- PCFX_Priority = priority;
- PCFX_Sound = &sound->data;
- PCFX_CallBackVal = callbackval;
- RestoreInterrupts( flags );
- return( PCFX_VoiceHandle );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_SoundPlaying
- Checks if a sound effect is currently playing.
- ---------------------------------------------------------------------*/
- int PCFX_SoundPlaying
- (
- int handle
- )
- {
- int status;
- status = FALSE;
- if ( ( handle == PCFX_VoiceHandle ) && ( PCFX_LengthLeft > 0 ) )
- {
- status = TRUE;
- }
- return( status );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_SetTotalVolume
- Sets the total volume of the sound effects.
- ---------------------------------------------------------------------*/
- int PCFX_SetTotalVolume
- (
- int volume
- )
- {
- unsigned flags;
- flags = DisableInterrupts();
- volume = max( volume, 0 );
- volume = min( volume, PCFX_MaxVolume );
- PCFX_TotalVolume = volume;
- if ( volume == 0 )
- {
- outp( 0x61, inp( 0x61 ) & 0xfc );
- }
- RestoreInterrupts( flags );
- return( PCFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_GetTotalVolume
- Returns the total volume of the sound effects.
- ---------------------------------------------------------------------*/
- int PCFX_GetTotalVolume
- (
- void
- )
- {
- return( PCFX_TotalVolume );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_LockEnd
- Used for determining the length of the functions to lock in memory.
- ---------------------------------------------------------------------*/
- static void PCFX_LockEnd
- (
- void
- )
- {
- }
- /*---------------------------------------------------------------------
- Function: PCFX_UseLookup
- Sets up a pitch lookup table for PC sound effects.
- ---------------------------------------------------------------------*/
- void PCFX_UseLookup
- (
- int use,
- unsigned value
- )
- {
- int pitch;
- int index;
- PCFX_Stop( PCFX_VoiceHandle );
- PCFX_UseLookupFlag = use;
- if ( use )
- {
- pitch = 0;
- for( index = 0; index < 256; index++ )
- {
- PCFX_Lookup[ index ] = pitch;
- pitch += value;
- }
- }
- }
- /*---------------------------------------------------------------------
- Function: PCFX_SetCallBack
- Set the function to call when a voice stops.
- ---------------------------------------------------------------------*/
- void PCFX_SetCallBack
- (
- void ( *function )( unsigned long )
- )
- {
- PCFX_CallBackFunc = function;
- }
- /*---------------------------------------------------------------------
- Function: PCFX_Init
- Initializes the sound effect engine.
- ---------------------------------------------------------------------*/
- int PCFX_Init
- (
- void
- )
- {
- int status;
- if ( PCFX_Installed )
- {
- PCFX_Shutdown();
- }
- status = PCFX_LockMemory();
- if ( status != PCFX_Ok )
- {
- PCFX_UnlockMemory();
- return( status );
- }
- PCFX_UseLookup( TRUE, 60 );
- PCFX_Stop( PCFX_VoiceHandle );
- PCFX_ServiceTask = TS_ScheduleTask( &PCFX_Service, 140, 2, NULL );
- TS_Dispatch();
- PCFX_CallBackFunc = NULL;
- PCFX_Installed = TRUE;
- PCFX_SetErrorCode( PCFX_Ok );
- return( PCFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_Shutdown
- Ends the use of the sound effect engine.
- ---------------------------------------------------------------------*/
- int PCFX_Shutdown
- (
- void
- )
- {
- if ( PCFX_Installed )
- {
- PCFX_Stop( PCFX_VoiceHandle );
- TS_Terminate( PCFX_ServiceTask );
- PCFX_UnlockMemory();
- PCFX_Installed = FALSE;
- }
- PCFX_SetErrorCode( PCFX_Ok );
- return( PCFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_UnlockMemory
- Unlocks all neccessary data.
- ---------------------------------------------------------------------*/
- void PCFX_UnlockMemory
- (
- void
- )
- {
- DPMI_UnlockMemoryRegion( PCFX_LockStart, PCFX_LockEnd );
- DPMI_Unlock( PCFX_LengthLeft );
- DPMI_Unlock( PCFX_Sound );
- DPMI_Unlock( PCFX_LastSample );
- DPMI_Unlock( PCFX_Lookup );
- DPMI_Unlock( PCFX_UseLookupFlag );
- DPMI_Unlock( PCFX_Priority );
- DPMI_Unlock( PCFX_CallBackVal );
- DPMI_Unlock( PCFX_CallBackFunc );
- DPMI_Unlock( PCFX_TotalVolume );
- DPMI_Unlock( PCFX_ServiceTask );
- DPMI_Unlock( PCFX_VoiceHandle );
- DPMI_Unlock( PCFX_Installed );
- DPMI_Unlock( PCFX_ErrorCode );
- }
- /*---------------------------------------------------------------------
- Function: PCFX_LockMemory
- Locks all neccessary data.
- ---------------------------------------------------------------------*/
- int PCFX_LockMemory
- (
- void
- )
- {
- int status;
- status = DPMI_LockMemoryRegion( PCFX_LockStart, PCFX_LockEnd );
- status |= DPMI_Lock( PCFX_LengthLeft );
- status |= DPMI_Lock( PCFX_Sound );
- status |= DPMI_Lock( PCFX_LastSample );
- status |= DPMI_Lock( PCFX_Lookup );
- status |= DPMI_Lock( PCFX_UseLookupFlag );
- status |= DPMI_Lock( PCFX_Priority );
- status |= DPMI_Lock( PCFX_CallBackVal );
- status |= DPMI_Lock( PCFX_CallBackFunc );
- status |= DPMI_Lock( PCFX_TotalVolume );
- status |= DPMI_Lock( PCFX_ServiceTask );
- status |= DPMI_Lock( PCFX_VoiceHandle );
- status |= DPMI_Lock( PCFX_Installed );
- status |= DPMI_Lock( PCFX_ErrorCode );
- if ( status != DPMI_Ok )
- {
- PCFX_UnlockMemory();
- PCFX_SetErrorCode( PCFX_DPMI_Error );
- return( PCFX_Error );
- }
- return( PCFX_Ok );
- }
|