123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /*
- 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: ADLIBFX.C
- author: James R. Dose
- date: April 1, 1994
- Low level routines to support Adlib 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 "al_midi.h"
- #include "adlibfx.h"
- #define TRUE ( 1 == 1 )
- #define FALSE ( !TRUE )
- static void ADLIBFX_SendOutput( int reg, int data );
- static void ADLIBFX_Service( task *Task );
- static long ADLIBFX_LengthLeft;
- static int ADLIBFX_Block;
- static ALSound *ADLIBFX_Sound = NULL;
- static char *ADLIBFX_SoundPtr = NULL;
- static int ADLIBFX_Priority;
- static unsigned long ADLIBFX_CallBackVal;
- static void ( *ADLIBFX_CallBackFunc )( unsigned long ) = NULL;
- static int ADLIBFX_SoundVolume;
- static int ADLIBFX_TotalVolume = ADLIBFX_MaxVolume;
- static task *ADLIBFX_ServiceTask = NULL;
- static int ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
- int ADLIBFX_Installed = FALSE;
- int ADLIBFX_ErrorCode = ADLIBFX_Ok;
- #define ADLIBFX_SetErrorCode( status ) \
- ADLIBFX_ErrorCode = ( status );
- /*---------------------------------------------------------------------
- Function: ADLIBFX_ErrorString
- Returns a pointer to the error message associated with an error
- number. A -1 returns a pointer the current error.
- ---------------------------------------------------------------------*/
- char *ADLIBFX_ErrorString
- (
- int ErrorNumber
- )
- {
- char *ErrorString;
- switch( ErrorNumber )
- {
- case ADLIBFX_Warning :
- case ADLIBFX_Error :
- ErrorString = ADLIBFX_ErrorString( ADLIBFX_ErrorCode );
- break;
- case ADLIBFX_Ok :
- ErrorString = "Adlib FX ok.";
- break;
- case ADLIBFX_NoVoices :
- ErrorString = "No free voices available in Adlib FX.";
- break;
- case ADLIBFX_VoiceNotFound :
- ErrorString = "No voice with matching handle found.";
- break;
- case ADLIBFX_DPMI_Error :
- ErrorString = "DPMI Error in AdlibFX.";
- break;
- default :
- ErrorString = "Unknown Adlib FX error code.";
- break;
- }
- return( ErrorString );
- }
- /**********************************************************************
- Memory locked functions:
- **********************************************************************/
- #define ADLIBFX_LockStart ADLIBFX_SendOutput
- /*---------------------------------------------------------------------
- Function: ADLIBFX_SendOutput
- Writes a byte of data to the specified register on the Adlib card.
- ---------------------------------------------------------------------*/
- static void ADLIBFX_SendOutput
- (
- int reg,
- int data
- )
- {
- int i;
- int adlib_port = 0x388;
- unsigned flags;
- flags = DisableInterrupts();
- outp( adlib_port, reg );
- for( i = 6; i ; i-- )
- {
- inp( adlib_port );
- }
- outp( adlib_port + 1, data );
- for( i = 35; i ; i-- )
- {
- inp( adlib_port );
- }
- RestoreInterrupts( flags );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_Stop
- Halts playback of the currently playing sound effect.
- ---------------------------------------------------------------------*/
- int ADLIBFX_Stop
- (
- int handle
- )
- {
- unsigned flags;
- if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
- {
- ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
- return( ADLIBFX_Warning );
- }
- flags = DisableInterrupts();
- ADLIBFX_SendOutput( 0xb0, 0 );
- ADLIBFX_Sound = NULL;
- ADLIBFX_SoundPtr = NULL;
- ADLIBFX_LengthLeft = 0;
- ADLIBFX_Priority = 0;
- RestoreInterrupts( flags );
- if ( ADLIBFX_CallBackFunc )
- {
- ADLIBFX_CallBackFunc( ADLIBFX_CallBackVal );
- }
- return( ADLIBFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_Service
- Task Manager routine to perform the playback of a sound effect.
- ---------------------------------------------------------------------*/
- static void ADLIBFX_Service
- (
- task *Task
- )
- {
- int value;
- if ( ADLIBFX_SoundPtr )
- {
- value = *ADLIBFX_SoundPtr++;
- if ( value != 0 )
- {
- ADLIBFX_SendOutput( 0xa0, value );
- ADLIBFX_SendOutput( 0xb0, ADLIBFX_Block );
- }
- else
- {
- ADLIBFX_SendOutput( 0xb0, 0 );
- }
- ADLIBFX_LengthLeft--;
- if ( ADLIBFX_LengthLeft <= 0 )
- {
- ADLIBFX_Stop( ADLIBFX_VoiceHandle );
- }
- }
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_SetVolume
- Sets the volume of the currently playing sound effect.
- ---------------------------------------------------------------------*/
- int ADLIBFX_SetVolume
- (
- int handle,
- int volume
- )
- {
- unsigned flags;
- int carrierlevel;
- flags = DisableInterrupts();
- if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
- {
- RestoreInterrupts( flags );
- ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
- return( ADLIBFX_Warning );
- }
- volume = min( volume, ADLIBFX_MaxVolume );
- volume = max( volume, 0 );
- ADLIBFX_SoundVolume = volume;
- volume *= ADLIBFX_TotalVolume;
- volume /= ADLIBFX_MaxVolume;
- carrierlevel = ADLIBFX_Sound->cScale & 0x3f;
- carrierlevel ^= 0x3f;
- carrierlevel *= ( volume / 2 ) + 0x80;
- carrierlevel /= ADLIBFX_MaxVolume;
- carrierlevel ^= 0x3f;
- carrierlevel |= ADLIBFX_Sound->cScale & 0xc0;
- ADLIBFX_SendOutput( 0x43, carrierlevel );
- RestoreInterrupts( flags );
- return( ADLIBFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_SetTotalVolume
- Sets the total volume of the sound effect.
- ---------------------------------------------------------------------*/
- int ADLIBFX_SetTotalVolume
- (
- int volume
- )
- {
- volume = max( volume, 0 );
- volume = min( volume, ADLIBFX_MaxVolume );
- ADLIBFX_TotalVolume = volume;
- ADLIBFX_SetVolume( ADLIBFX_VoiceHandle, ADLIBFX_SoundVolume );
- return( ADLIBFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_GetTotalVolume
- Returns the total volume of the sound effect.
- ---------------------------------------------------------------------*/
- int ADLIBFX_GetTotalVolume
- (
- void
- )
- {
- return( ADLIBFX_TotalVolume );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_VoiceAvailable
- Checks if a voice can be play at the specified priority.
- ---------------------------------------------------------------------*/
- int ADLIBFX_VoiceAvailable
- (
- int priority
- )
- {
- if ( priority < ADLIBFX_Priority )
- {
- return( FALSE );
- }
- return( TRUE );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_Play
- Starts playback of a Muse sound effect.
- ---------------------------------------------------------------------*/
- int ADLIBFX_Play
- (
- ALSound *sound,
- int volume,
- int priority,
- unsigned long callbackval
- )
- {
- unsigned flags;
- int carrierlevel;
- if ( priority < ADLIBFX_Priority )
- {
- ADLIBFX_SetErrorCode( ADLIBFX_NoVoices );
- return( ADLIBFX_Warning );
- }
- ADLIBFX_Stop( ADLIBFX_VoiceHandle );
- ADLIBFX_VoiceHandle++;
- if ( ADLIBFX_VoiceHandle < ADLIBFX_MinVoiceHandle )
- {
- ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
- }
- flags = DisableInterrupts();
- ADLIBFX_LengthLeft = sound->length;
- ADLIBFX_Priority = priority;
- ADLIBFX_Sound = sound;
- ADLIBFX_SoundPtr = &sound->data;
- ADLIBFX_CallBackVal = callbackval;
- ADLIBFX_Block = ( ( sound->block & 7 ) << 2 ) | 0x20;
- volume = min( volume, ADLIBFX_MaxVolume );
- volume = max( volume, 0 );
- ADLIBFX_SoundVolume = volume;
- volume *= ADLIBFX_TotalVolume;
- volume /= ADLIBFX_MaxVolume;
- carrierlevel = sound->cScale & 0x3f;
- carrierlevel ^= 0x3f;
- carrierlevel *= ( volume / 2 ) + 0x80;
- carrierlevel /= ADLIBFX_MaxVolume;
- carrierlevel ^= 0x3f;
- carrierlevel |= sound->cScale & 0xc0;
- ADLIBFX_SendOutput( 0x20, sound->mChar );
- ADLIBFX_SendOutput( 0x40, sound->mScale );
- ADLIBFX_SendOutput( 0x60, sound->mAttack );
- ADLIBFX_SendOutput( 0x80, sound->mSus );
- ADLIBFX_SendOutput( 0xe0, sound->mWave );
- ADLIBFX_SendOutput( 0x23, sound->cChar );
- ADLIBFX_SendOutput( 0x43, carrierlevel );
- ADLIBFX_SendOutput( 0x63, sound->cAttack );
- ADLIBFX_SendOutput( 0x83, sound->cSus );
- ADLIBFX_SendOutput( 0xe3, sound->cWave );
- ADLIBFX_SendOutput( 0xc0, 0 );
- RestoreInterrupts( flags );
- return( ADLIBFX_VoiceHandle );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_SoundPlaying
- Checks if a sound effect is currently playing.
- ---------------------------------------------------------------------*/
- int ADLIBFX_SoundPlaying
- (
- int handle
- )
- {
- int status;
- status = FALSE;
- if ( ( handle == ADLIBFX_VoiceHandle ) && ( ADLIBFX_LengthLeft > 0 ) )
- {
- status = TRUE;
- }
- return( status );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_LockEnd
- Used for determining the length of the functions to lock in memory.
- ---------------------------------------------------------------------*/
- static void ADLIBFX_LockEnd
- (
- void
- )
- {
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_SetCallBack
- Set the function to call when a voice stops.
- ---------------------------------------------------------------------*/
- void ADLIBFX_SetCallBack
- (
- void ( *function )( unsigned long )
- )
- {
- ADLIBFX_CallBackFunc = function;
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_Init
- Initializes the sound effect engine.
- ---------------------------------------------------------------------*/
- int ADLIBFX_Init
- (
- void
- )
- {
- int status;
- if ( ADLIBFX_Installed )
- {
- ADLIBFX_Shutdown();
- }
- status = DPMI_LockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
- status |= DPMI_Lock( ADLIBFX_VoiceHandle );
- status |= DPMI_Lock( ADLIBFX_Sound );
- status |= DPMI_Lock( ADLIBFX_ErrorCode );
- status |= DPMI_Lock( ADLIBFX_SoundPtr );
- status |= DPMI_Lock( ADLIBFX_LengthLeft );
- status |= DPMI_Lock( ADLIBFX_Priority );
- status |= DPMI_Lock( ADLIBFX_CallBackFunc );
- status |= DPMI_Lock( ADLIBFX_Block );
- if ( status != DPMI_Ok )
- {
- ADLIBFX_SetErrorCode( ADLIBFX_DPMI_Error );
- return( ADLIBFX_Error );
- }
- //JIM
- // AL_ReserveVoice( 0 );
- ADLIBFX_Stop( ADLIBFX_VoiceHandle );
- ADLIBFX_ServiceTask = TS_ScheduleTask( &ADLIBFX_Service, 140, 2, NULL );
- TS_Dispatch();
- ADLIBFX_Installed = TRUE;
- ADLIBFX_CallBackFunc = NULL;
- ADLIBFX_SetErrorCode( ADLIBFX_Ok );
- return( ADLIBFX_Ok );
- }
- /*---------------------------------------------------------------------
- Function: ADLIBFX_Shutdown
- Ends the use of the sound effect engine.
- ---------------------------------------------------------------------*/
- int ADLIBFX_Shutdown
- (
- void
- )
- {
- if ( ADLIBFX_Installed )
- {
- ADLIBFX_Stop( ADLIBFX_VoiceHandle );
- TS_Terminate( ADLIBFX_ServiceTask );
- ADLIBFX_ServiceTask = NULL;
- //JIM
- // AL_ReleaseVoice( 0 );
- ADLIBFX_Installed = FALSE;
- DPMI_UnlockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
- DPMI_Unlock( ADLIBFX_VoiceHandle );
- DPMI_Unlock( ADLIBFX_Sound );
- DPMI_Unlock( ADLIBFX_ErrorCode );
- DPMI_Unlock( ADLIBFX_SoundPtr );
- DPMI_Unlock( ADLIBFX_LengthLeft );
- DPMI_Unlock( ADLIBFX_Priority );
- DPMI_Unlock( ADLIBFX_CallBackFunc );
- DPMI_Unlock( ADLIBFX_Block );
- }
- ADLIBFX_SetErrorCode( ADLIBFX_Ok );
- return( ADLIBFX_Ok );
- }
|