123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- /*
- 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: SNDSRC.C
- author: James R. Dose
- date: March 26, 1994
- Low level routines to support the Disney Sound Source.
- (c) Copyright 1994 James R. Dose. All Rights Reserved.
- **********************************************************************/
- #define STEREO 1
- #define SIXTEEN_BIT 2
- #define MONO_8BIT 0
- #define STEREO_8BIT ( STEREO )
- #define MONO_16BIT ( SIXTEEN_BIT )
- #define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
- #include <stdlib.h>
- #include <dos.h>
- #include <conio.h>
- #include "dpmi.h"
- #include "task_man.h"
- #include "sndcards.h"
- #include "user.h"
- #include "sndsrc.h"
- #define TRUE ( 1 == 1 )
- #define FALSE ( !TRUE )
- static int SS_Installed = FALSE;
- static int SS_Port = SS_DefaultPort;
- static int SS_OffCommand = 0xc;
- static char *SS_BufferStart;
- static char *SS_BufferEnd;
- static char *SS_CurrentBuffer;
- static int SS_BufferNum = 0;
- static int SS_NumBuffers = 0;
- static int SS_TotalBufferSize = 0;
- static int SS_TransferLength = 0;
- static int SS_CurrentLength = 0;
- static char *SS_SoundPtr;
- volatile int SS_SoundPlaying;
- static task *SS_Timer;
- void ( *SS_CallBack )( void );
- int SS_ErrorCode = SS_Ok;
- #define SS_SetErrorCode( status ) \
- SS_ErrorCode = ( status );
- /*---------------------------------------------------------------------
- Function: SS_ErrorString
- Returns a pointer to the error message associated with an error
- number. A -1 returns a pointer the current error.
- ---------------------------------------------------------------------*/
- char *SS_ErrorString
- (
- int ErrorNumber
- )
- {
- char *ErrorString;
- switch( ErrorNumber )
- {
- case SS_Error :
- ErrorString = SS_ErrorString( SS_ErrorCode );
- break;
- case SS_Ok :
- ErrorString = "Sound Source ok.";
- break;
- case SS_NotFound :
- ErrorString = "Could not detect Sound Source.";
- break;
- case SS_NoSoundPlaying :
- ErrorString = "No sound playing in SndSrc.";
- break;
- case SS_DPMI_Error :
- ErrorString = "DPMI Error in SndSrc.";
- break;
- default :
- ErrorString = "Unknown Sound Source error code.";
- break;
- }
- return( ErrorString );
- }
- /**********************************************************************
- Memory locked functions:
- **********************************************************************/
- #define SS_LockStart SS_ServiceInterrupt
- /*---------------------------------------------------------------------
- Function: SS_ServiceInterrupt
- Handles interrupt generated by sound card at the end of a voice
- transfer. Calls the user supplied callback function.
- ---------------------------------------------------------------------*/
- static void SS_ServiceInterrupt
- (
- task *Task
- )
- {
- int port = SS_Port;
- int count;
- count = 0;
- while( ( inp( port + 1 ) & 0x40 ) == 0 )
- {
- outp( port, *SS_SoundPtr++ );
- outp( port + 2, SS_OffCommand );
- outp( port + 2, 4 );
- SS_CurrentLength--;
- if ( SS_CurrentLength == 0 )
- {
- // Keep track of current buffer
- SS_CurrentBuffer += SS_TransferLength;
- SS_BufferNum++;
- if ( SS_BufferNum >= SS_NumBuffers )
- {
- SS_BufferNum = 0;
- SS_CurrentBuffer = SS_BufferStart;
- }
- SS_CurrentLength = SS_TransferLength;
- SS_SoundPtr = SS_CurrentBuffer;
- // Call the caller's callback function
- if ( SS_CallBack != NULL )
- {
- SS_CallBack();
- }
- }
- count++;
- // Only do at most 14 samples per tick
- if ( count > 13 )
- {
- break;
- }
- }
- }
- /*---------------------------------------------------------------------
- Function: SS_StopPlayback
- Ends the transfer of digitized sound to the Sound Source.
- ---------------------------------------------------------------------*/
- void SS_StopPlayback
- (
- void
- )
- {
- if ( SS_SoundPlaying )
- {
- TS_Terminate( SS_Timer );
- outp( SS_Port, 0x80 );
- outp( SS_Port + 2, SS_OffCommand );
- outp( SS_Port + 2, 4 );
- SS_SoundPlaying = FALSE;
- SS_BufferStart = NULL;
- }
- }
- /*---------------------------------------------------------------------
- Function: SS_GetCurrentPos
- Returns the offset within the current sound being played.
- ---------------------------------------------------------------------*/
- int SS_GetCurrentPos
- (
- void
- )
- {
- int offset;
- if ( !SS_SoundPlaying )
- {
- SS_SetErrorCode( SS_NoSoundPlaying );
- return( SS_Warning );
- }
- offset = ( int )( ( ( unsigned long )SS_SoundPtr ) -
- ( ( unsigned long )SS_CurrentBuffer ) );
- return( offset );
- }
- /*---------------------------------------------------------------------
- Function: SS_LockEnd
- Used for determining the length of the functions to lock in memory.
- ---------------------------------------------------------------------*/
- static void SS_LockEnd
- (
- void
- )
- {
- }
- /*---------------------------------------------------------------------
- Function: SS_BeginBufferedPlayback
- Begins multibuffered playback of digitized sound on the Sound Source.
- ---------------------------------------------------------------------*/
- int SS_BeginBufferedPlayback
- (
- char *BufferStart,
- int BufferSize,
- int NumDivisions,
- void ( *CallBackFunc )( void )
- )
- {
- if ( SS_SoundPlaying )
- {
- SS_StopPlayback();
- }
- SS_SetCallBack( CallBackFunc );
- SS_BufferStart = BufferStart;
- SS_CurrentBuffer = BufferStart;
- SS_SoundPtr = BufferStart;
- SS_TotalBufferSize = BufferSize;
- SS_BufferEnd = BufferStart + BufferSize;
- SS_TransferLength = BufferSize / NumDivisions;
- SS_CurrentLength = SS_TransferLength;
- SS_BufferNum = 0;
- SS_NumBuffers = NumDivisions;
- SS_SoundPlaying = TRUE;
- // SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 438, 1, NULL );
- SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 510, 1, NULL );
- TS_Dispatch();
- return( SS_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SS_GetPlaybackRate
- Returns the rate at which the digitized sound will be played in
- hertz.
- ---------------------------------------------------------------------*/
- int SS_GetPlaybackRate
- (
- void
- )
- {
- return( SS_SampleRate );
- }
- /*---------------------------------------------------------------------
- Function: SS_SetMixMode
- Sets the sound card to play samples in mono or stereo.
- ---------------------------------------------------------------------*/
- int SS_SetMixMode
- (
- int mode
- )
- {
- mode = MONO_8BIT;
- return( mode );
- }
- /*---------------------------------------------------------------------
- Function: SS_SetPort
- Selects which port to use to write to the Sound Source.
- ---------------------------------------------------------------------*/
- int SS_SetPort
- (
- int port
- )
- {
- if ( SS_Installed )
- {
- SS_Shutdown();
- }
- SS_Port = port;
- return( SS_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SS_SetCallBack
- Specifies the user function to call at the end of a sound transfer.
- ---------------------------------------------------------------------*/
- void SS_SetCallBack
- (
- void ( *func )( void )
- )
- {
- SS_CallBack = func;
- }
- /*---------------------------------------------------------------------
- Function: SS_TestTimer
- Used as a delay in SS_TestSoundSource.
- ---------------------------------------------------------------------*/
- void SS_TestTimer
- (
- task *Task
- )
- {
- ( *( int * )( Task->data ) )++;
- }
- /*---------------------------------------------------------------------
- Function: SS_TestSoundSource
- Detect if the Sound Source is located at the specified port.
- ---------------------------------------------------------------------*/
- int SS_TestSoundSource
- (
- int port
- )
- {
- int present;
- task *timer;
- volatile int ticks;
- int i;
- present = FALSE;
- timer = TS_ScheduleTask( SS_TestTimer, 140, 1, &ticks );
- TS_Dispatch();
- outp( port + 2, 4 );
- ticks = 0;
- while( ticks < 4 )
- {
- // Do nothing for a while
- }
- TS_Terminate( timer );
- if ( ( inp( port + 1 ) & 0x40 ) == 0 )
- {
- for( i = 32; i > 0; i-- )
- {
- outp( port, 0x80 );
- outp( port + 2, SS_OffCommand );
- outp( port + 2, 4 );
- }
- if ( inp( port + 1 ) & 0x40 )
- {
- present = TRUE;
- }
- }
- outp( port + 2, SS_OffCommand );
- return( present );
- }
- /*---------------------------------------------------------------------
- Function: SS_DetectSoundSource
- Detects which port the Sound Source is located.
- ---------------------------------------------------------------------*/
- int SS_DetectSoundSource
- (
- void
- )
- {
- if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT1 ) )
- {
- SS_Port = SS_Port1;
- return( TRUE );
- }
- if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT2 ) )
- {
- SS_Port = SS_Port2;
- return( TRUE );
- }
- if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT3 ) )
- {
- SS_Port = SS_Port3;
- return( TRUE );
- }
- if ( SS_TestSoundSource( SS_Port1 ) )
- {
- SS_Port = SS_Port1;
- return( TRUE );
- }
- if ( SS_TestSoundSource( SS_Port2 ) )
- {
- SS_Port = SS_Port2;
- return( TRUE );
- }
- if ( SS_TestSoundSource( SS_Port3 ) )
- {
- SS_Port = SS_Port3;
- return( TRUE );
- }
- return( FALSE );
- }
- /*---------------------------------------------------------------------
- Function: SS_Init
- Initializes the Sound Source prepares the module to play digitized
- sounds.
- ---------------------------------------------------------------------*/
- int SS_Init
- (
- int soundcard
- )
- {
- int status;
- if ( SS_Installed )
- {
- SS_Shutdown();
- }
- if ( ( soundcard == TandySoundSource ) ||
- ( USER_CheckParameter( SELECT_TANDY_SOUNDSOURCE ) ) )
- {
- // Tandy
- SS_OffCommand = 0x0e;
- }
- else
- {
- // Disney
- SS_OffCommand = 0x0c;
- }
- status = SS_DetectSoundSource();
- if ( !status )
- {
- SS_SetErrorCode( SS_NotFound );
- return( SS_Warning );
- }
- status = SS_LockMemory();
- if ( status != SS_Ok )
- {
- SS_UnlockMemory();
- return( status );
- }
- status = SS_Ok;
- outp( SS_Port + 2, 4 );
- SS_SoundPlaying = FALSE;
- SS_SetCallBack( NULL );
- SS_BufferStart = NULL;
- SS_Installed = TRUE;
- SS_SetErrorCode( status );
- return( status );
- }
- /*---------------------------------------------------------------------
- Function: SS_Shutdown
- Ends transfer of sound data to the Sound Source.
- ---------------------------------------------------------------------*/
- void SS_Shutdown
- (
- void
- )
- {
- // Halt the transfer
- SS_StopPlayback();
- outp( SS_Port + 2, SS_OffCommand );
- SS_SoundPlaying = FALSE;
- SS_BufferStart = NULL;
- SS_SetCallBack( NULL );
- SS_UnlockMemory();
- SS_Installed = FALSE;
- }
- /*---------------------------------------------------------------------
- Function: SS_UnlockMemory
- Unlocks all neccessary data.
- ---------------------------------------------------------------------*/
- void SS_UnlockMemory
- (
- void
- )
- {
- DPMI_UnlockMemoryRegion( SS_LockStart, SS_LockEnd );
- DPMI_Unlock( SS_Installed );
- DPMI_Unlock( SS_Port );
- DPMI_Unlock( SS_OffCommand );
- DPMI_Unlock( SS_BufferStart );
- DPMI_Unlock( SS_BufferEnd );
- DPMI_Unlock( SS_CurrentBuffer );
- DPMI_Unlock( SS_BufferNum );
- DPMI_Unlock( SS_NumBuffers );
- DPMI_Unlock( SS_TotalBufferSize );
- DPMI_Unlock( SS_TransferLength );
- DPMI_Unlock( SS_CurrentLength );
- DPMI_Unlock( SS_SoundPtr );
- DPMI_Unlock( SS_SoundPlaying );
- DPMI_Unlock( SS_Timer );
- DPMI_Unlock( SS_CallBack );
- DPMI_Unlock( SS_ErrorCode );
- }
- /*---------------------------------------------------------------------
- Function: SS_LockMemory
- Locks all neccessary data.
- ---------------------------------------------------------------------*/
- int SS_LockMemory
- (
- void
- )
- {
- int status;
- status = DPMI_LockMemoryRegion( SS_LockStart, SS_LockEnd );
- status |= DPMI_Lock( SS_Installed );
- status |= DPMI_Lock( SS_Port );
- status |= DPMI_Lock( SS_OffCommand );
- status |= DPMI_Lock( SS_BufferStart );
- status |= DPMI_Lock( SS_BufferEnd );
- status |= DPMI_Lock( SS_CurrentBuffer );
- status |= DPMI_Lock( SS_BufferNum );
- status |= DPMI_Lock( SS_NumBuffers );
- status |= DPMI_Lock( SS_TotalBufferSize );
- status |= DPMI_Lock( SS_TransferLength );
- status |= DPMI_Lock( SS_CurrentLength );
- status |= DPMI_Lock( SS_SoundPtr );
- status |= DPMI_Lock( SS_SoundPlaying );
- status |= DPMI_Lock( SS_Timer );
- status |= DPMI_Lock( SS_CallBack );
- status |= DPMI_Lock( SS_ErrorCode );
- if ( status != DPMI_Ok )
- {
- SS_UnlockMemory();
- SS_SetErrorCode( SS_DPMI_Error );
- return( SS_Error );
- }
- return( SS_Ok );
- }
|