123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662 |
- /*
- 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: SNDSCAPE.C
- author: James R. Dose
- date: October 25, 1994
- Low level routines to support the Ensoniq Soundscape.
- (c) Copyright 1994 James R. Dose. All Rights Reserved.
- **********************************************************************/
- #include <dos.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include "interrup.h"
- #include "dpmi.h"
- #include "dma.h"
- #include "irq.h"
- #include "sndscape.h"
- #include "_sndscap.h"
- const int SOUNDSCAPE_Interrupts[ SOUNDSCAPE_MaxIrq + 1 ] =
- {
- INVALID, INVALID, 0xa, INVALID,
- INVALID, 0xd, INVALID, 0xf,
- INVALID, INVALID, 0x72, INVALID,
- INVALID, INVALID, INVALID, INVALID
- };
- const int SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MaxMixMode + 1 ] =
- {
- MONO_8BIT_SAMPLE_SIZE, STEREO_8BIT_SAMPLE_SIZE,
- MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
- };
- static void ( __interrupt __far *SOUNDSCAPE_OldInt )( void );
- static int SOUNDSCAPE_Installed = FALSE;
- static int SOUNDSCAPE_FoundCard = FALSE;
- static char *SOUNDSCAPE_DMABuffer;
- static char *SOUNDSCAPE_DMABufferEnd;
- static char *SOUNDSCAPE_CurrentDMABuffer;
- static int SOUNDSCAPE_TotalDMABufferSize;
- static int SOUNDSCAPE_TransferLength = 0;
- static int SOUNDSCAPE_MixMode = SOUNDSCAPE_DefaultMixMode;
- static int SOUNDSCAPE_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
- static unsigned SOUNDSCAPE_SampleRate = SOUNDSCAPE_DefaultSampleRate;
- volatile int SOUNDSCAPE_SoundPlaying;
- void ( *SOUNDSCAPE_CallBack )( void );
- static int SOUNDSCAPE_IntController1Mask;
- static int SOUNDSCAPE_IntController2Mask;
- // some globals for chip type, ports, DMA, IRQs ... and stuff
- static struct
- {
- int BasePort; // base address of the Ensoniq gate-array chip
- int WavePort; // the AD-1848 base address
- int DMAChan; // the DMA channel used for PCM
- int WaveIRQ; // the PCM IRQ
- int MIDIIRQ; // the MPU-401 IRQ
- int ChipID; // the Ensoniq chip type
- int SBEmul; // SoundBlaster emulation flag
- int CDROM; // CD-ROM flag
- int IRQIndx; // the Wave IRQ index - for hardware regs
- int OldIRQs; // Old IRQs flag to support older HW
- } SOUNDSCAPE_Config;
- // adequate stack size
- #define kStackSize 2048
- static unsigned short StackSelector = NULL;
- static unsigned long StackPointer;
- static unsigned short oldStackSelector;
- static unsigned long oldStackPointer;
- // These declarations are necessary to use the inline assembly pragmas.
- extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
- extern void SetStack(unsigned short selector,unsigned long stackptr);
- // This function will get the current stack selector and pointer and save
- // them off.
- #pragma aux GetStack = \
- "mov [edi],esp" \
- "mov ax,ss" \
- "mov [esi],ax" \
- parm [esi] [edi] \
- modify [eax esi edi];
- // This function will set the stack selector and pointer to the specified
- // values.
- #pragma aux SetStack = \
- "mov ss,ax" \
- "mov esp,edx" \
- parm [ax] [edx] \
- modify [eax edx];
- int SOUNDSCAPE_DMAChannel = -1;
- int SOUNDSCAPE_ErrorCode = SOUNDSCAPE_Ok;
- #define SOUNDSCAPE_SetErrorCode( status ) \
- SOUNDSCAPE_ErrorCode = ( status );
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_ErrorString
- Returns a pointer to the error message associated with an error
- number. A -1 returns a pointer the current error.
- ---------------------------------------------------------------------*/
- char *SOUNDSCAPE_ErrorString
- (
- int ErrorNumber
- )
- {
- char *ErrorString;
- switch( ErrorNumber )
- {
- case SOUNDSCAPE_Warning :
- case SOUNDSCAPE_Error :
- ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_ErrorCode );
- break;
- case SOUNDSCAPE_Ok :
- ErrorString = "SoundScape ok.";
- break;
- case SOUNDSCAPE_EnvNotFound :
- ErrorString = "SNDSCAPE environment variable not set. This is used to locate \n"
- "SNDSCAPE.INI which is used to describe your sound card setup.";
- break;
- case SOUNDSCAPE_InitFileNotFound :
- ErrorString = "Missing SNDSCAPE.INI file for SoundScape. This file should be \n"
- "located in the directory indicated by the SNDSCAPE environment \n"
- "variable or in 'C:\SNDSCAPE' if SNDSCAPE is not set.";
- break;
- case SOUNDSCAPE_MissingProductInfo :
- ErrorString = "Missing 'Product' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingPortInfo :
- ErrorString = "Missing 'Port' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingDMAInfo :
- ErrorString = "Missing 'DMA' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingIRQInfo :
- ErrorString = "Missing 'IRQ' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingSBIRQInfo :
- ErrorString = "Missing 'SBIRQ' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingSBENABLEInfo :
- ErrorString = "Missing 'SBEnable' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_MissingWavePortInfo :
- ErrorString = "Missing 'WavePort' field in SNDSCAPE.INI file for SoundScape.";
- break;
- case SOUNDSCAPE_HardwareError :
- ErrorString = "Could not detect SoundScape. Make sure your SNDSCAPE.INI file \n"
- "contains correct information about your hardware setup.";
- break;
- case SOUNDSCAPE_NoSoundPlaying :
- ErrorString = "No sound playing on SoundScape.";
- break;
- case SOUNDSCAPE_InvalidSBIrq :
- ErrorString = "Invalid SoundScape Irq in SBIRQ field of SNDSCAPE.INI.";
- break;
- case SOUNDSCAPE_UnableToSetIrq :
- ErrorString = "Unable to set SoundScape IRQ. Try selecting an IRQ of 7 or below.";
- break;
- case SOUNDSCAPE_DmaError :
- ErrorString = DMA_ErrorString( DMA_Error );
- break;
- case SOUNDSCAPE_DPMI_Error :
- ErrorString = "DPMI Error in SoundScape.";
- break;
- case SOUNDSCAPE_OutOfMemory :
- ErrorString = "Out of conventional memory in SoundScape.";
- break;
- default :
- ErrorString = "Unknown SoundScape error code.";
- break;
- }
- return( ErrorString );
- }
- /**********************************************************************
- Memory locked functions:
- **********************************************************************/
- #define SOUNDSCAPE_LockStart SOUNDSCAPE_EnableInterrupt
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_EnableInterrupt
- Enables the triggering of the sound card interrupt.
- ---------------------------------------------------------------------*/
- static void SOUNDSCAPE_EnableInterrupt
- (
- void
- )
- {
- int mask;
- // Unmask system interrupt
- if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
- {
- mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
- outp( 0x21, mask );
- }
- else
- {
- mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
- outp( 0xA1, mask );
- mask = inp( 0x21 ) & ~( 1 << 2 );
- outp( 0x21, mask );
- }
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_DisableInterrupt
- Disables the triggering of the sound card interrupt.
- ---------------------------------------------------------------------*/
- static void SOUNDSCAPE_DisableInterrupt
- (
- void
- )
- {
- int mask;
- // Restore interrupt mask
- if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
- {
- mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
- mask |= SOUNDSCAPE_IntController1Mask & ( 1 << SOUNDSCAPE_Config.WaveIRQ );
- outp( 0x21, mask );
- }
- else
- {
- mask = inp( 0x21 ) & ~( 1 << 2 );
- mask |= SOUNDSCAPE_IntController1Mask & ( 1 << 2 );
- outp( 0x21, mask );
- mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
- mask |= SOUNDSCAPE_IntController2Mask & ( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
- outp( 0xA1, mask );
- }
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_ServiceInterrupt
- Handles interrupt generated by sound card at the end of a voice
- transfer. Calls the user supplied callback function.
- ---------------------------------------------------------------------*/
- static void __interrupt __far SOUNDSCAPE_ServiceInterrupt
- (
- void
- )
- {
- // save stack
- GetStack( &oldStackSelector, &oldStackPointer );
- // set our stack
- SetStack( StackSelector, StackPointer );
- if ( !( inp( SOUNDSCAPE_Config.WavePort + AD_STATUS ) & 0x01 ) )
- {
- // restore stack
- SetStack( oldStackSelector, oldStackPointer );
- // Wasn't our interrupt. Call the old one.
- _chain_intr( SOUNDSCAPE_OldInt );
- }
- // clear the AD-1848 interrupt
- outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
- // Keep track of current buffer
- SOUNDSCAPE_CurrentDMABuffer += SOUNDSCAPE_TransferLength;
- if ( SOUNDSCAPE_CurrentDMABuffer >= SOUNDSCAPE_DMABufferEnd )
- {
- SOUNDSCAPE_CurrentDMABuffer = SOUNDSCAPE_DMABuffer;
- }
- // Call the caller's callback function
- if ( SOUNDSCAPE_CallBack != NULL )
- {
- SOUNDSCAPE_CallBack();
- }
- // restore stack
- SetStack( oldStackSelector, oldStackPointer );
- // send EOI to Interrupt Controller
- if ( SOUNDSCAPE_Config.WaveIRQ > 7 )
- {
- outp( 0xA0, 0x20 );
- }
- outp( 0x20, 0x20 );
- }
- /*---------------------------------------------------------------------
- Function: ga_read
- Reads Ensoniq indirect registers.
- ---------------------------------------------------------------------*/
- static int ga_read
- (
- int rnum
- )
- {
- int data;
- outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
- data = inp( SOUNDSCAPE_Config.BasePort + GA_REGDATA );
- return( data );
- }
- /*---------------------------------------------------------------------
- Function: ga_write
- Writes to Ensoniq indirect registers.
- ---------------------------------------------------------------------*/
- static void ga_write
- (
- int rnum,
- int value
- )
- {
- outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
- outp( SOUNDSCAPE_Config.BasePort + GA_REGDATA, value );
- }
- /*---------------------------------------------------------------------
- Function: ad_read
- Reads the AD-1848 indirect registers. This function should not be
- used while the AD-1848 mode change is enabled
- ---------------------------------------------------------------------*/
- static int ad_read
- (
- int rnum
- )
- {
- int data;
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
- data = inp( SOUNDSCAPE_Config.WavePort + AD_REGDATA );
- return( data );
- }
- /*---------------------------------------------------------------------
- Function: ad_write
- Writes to the AD-1848 indirect registers. This function should
- not be used while the AD-1848 mode change is enabled.
- ---------------------------------------------------------------------*/
- static void ad_write
- (
- int rnum,
- int value
- )
- {
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
- outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, value );
- }
- /*---------------------------------------------------------------------
- Function: tdelay
- Delay function - 250ms - for AD-1848 re-synch and autocalibration.
- ---------------------------------------------------------------------*/
- static void tdelay
- (
- void
- )
- {
- long time;
- unsigned flags;
- flags = DisableInterrupts();
- _enable();
- time = clock() + CLOCKS_PER_SEC/4;
- while(clock() < time)
- ;
- RestoreInterrupts( flags );
- }
- /*---------------------------------------------------------------------
- Function: pcm_format
- Sets the PCM data format.
- ---------------------------------------------------------------------*/
- static void pcm_format
- (
- void
- )
- {
- int format;
- // build the register value based on format
- format = 0;
- switch( SOUNDSCAPE_SampleRate )
- {
- case 11025:
- format = 0x03;
- break;
- case 22050:
- format = 0x07;
- break;
- case 44100:
- format = 0x0b;
- break;
- default:
- // Set it to 11025 hz
- format = 0x03;
- break;
- }
- // set other format bits and format globals
- if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
- {
- format |= 0x40;
- }
- if ( SOUNDSCAPE_MixMode & STEREO )
- {
- format |= 0x10;
- }
- // enable mode change, point to format reg
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_FORMAT );
- // write the format
- outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, format );
- // delay for internal re-synch
- tdelay();
- // exit mode change state
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
- // delay for autocalibration
- tdelay();
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_SetPlaybackRate
- Sets the rate at which the digitized sound will be played in
- hertz.
- ---------------------------------------------------------------------*/
- void SOUNDSCAPE_SetPlaybackRate
- (
- unsigned rate
- )
- {
- if ( rate < 20000 )
- {
- rate = 11025;
- }
- else if ( rate < 30000 )
- {
- rate = 22050;
- }
- else
- {
- rate = 44100;
- }
- SOUNDSCAPE_SampleRate = rate;
- // Set the rate
- pcm_format();
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_GetPlaybackRate
- Returns the rate at which the digitized sound will be played in
- hertz.
- ---------------------------------------------------------------------*/
- unsigned SOUNDSCAPE_GetPlaybackRate
- (
- void
- )
- {
- return( SOUNDSCAPE_SampleRate );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_SetMixMode
- Sets the sound card to play samples in mono or stereo.
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_SetMixMode
- (
- int mode
- )
- {
- SOUNDSCAPE_MixMode = mode & SOUNDSCAPE_MaxMixMode;
- SOUNDSCAPE_SamplePacketSize = SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MixMode ];
- // Set the mixmode
- pcm_format();
- return( mode );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_StopPlayback
- Ends the DMA transfer of digitized sound to the sound card.
- ---------------------------------------------------------------------*/
- void SOUNDSCAPE_StopPlayback
- (
- void
- )
- {
- // Don't allow anymore interrupts
- SOUNDSCAPE_DisableInterrupt();
- /* stop the AD-1848 */
- ad_write( AD_CONFIG, 0x00 );
- /* let it finish it's cycles */
- tdelay();
- // Disable the DMA channel
- DMA_EndTransfer( SOUNDSCAPE_Config.DMAChan );
- SOUNDSCAPE_SoundPlaying = FALSE;
- SOUNDSCAPE_DMABuffer = NULL;
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_SetupDMABuffer
- Programs the DMAC for sound transfer.
- ---------------------------------------------------------------------*/
- static int SOUNDSCAPE_SetupDMABuffer
- (
- char *BufferPtr,
- int BufferSize,
- int mode
- )
- {
- int DmaStatus;
- DmaStatus = DMA_SetupTransfer( SOUNDSCAPE_Config.DMAChan, BufferPtr, BufferSize, mode );
- if ( DmaStatus == DMA_Error )
- {
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_DMAChannel = SOUNDSCAPE_Config.DMAChan;
- SOUNDSCAPE_DMABuffer = BufferPtr;
- SOUNDSCAPE_CurrentDMABuffer = BufferPtr;
- SOUNDSCAPE_TotalDMABufferSize = BufferSize;
- SOUNDSCAPE_DMABufferEnd = BufferPtr + BufferSize;
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_GetCurrentPos
- Returns the offset within the current sound being played.
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_GetCurrentPos
- (
- void
- )
- {
- char *CurrentAddr;
- int offset;
- if ( !SOUNDSCAPE_SoundPlaying )
- {
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_NoSoundPlaying );
- return( SOUNDSCAPE_Error );
- }
- CurrentAddr = DMA_GetCurrentPos( SOUNDSCAPE_Config.DMAChan );
- offset = ( int )( ( ( unsigned long )CurrentAddr ) -
- ( ( unsigned long )SOUNDSCAPE_CurrentDMABuffer ) );
- if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
- {
- offset >>= 1;
- }
- if ( SOUNDSCAPE_MixMode & STEREO )
- {
- offset >>= 1;
- }
- return( offset );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_BeginPlayback
- Starts playback of digitized sound.
- ---------------------------------------------------------------------*/
- static int SOUNDSCAPE_BeginPlayback
- (
- int length
- )
- {
- int SampleLength;
- int LoByte;
- int HiByte;
- if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
- {
- SampleLength = length / 2;
- }
- else
- {
- SampleLength = length;
- }
- if ( SOUNDSCAPE_MixMode & STEREO )
- {
- SampleLength >>= 1;
- }
- SampleLength--;
- // setup the AD-1848 interrupt count
- // set the interrupt count value based on the format.
- // count will decrement every sample period and generate
- // an interrupt when in rolls over. we want this always
- // to be at every 1/2 buffer, regardless of the data format,
- // so the count must be adjusted accordingly.
- HiByte = hibyte( SampleLength );
- LoByte = lobyte( SampleLength );
- ad_write( AD_LCOUNT, LoByte );
- ad_write( AD_UCOUNT, HiByte );
- /* unmask the host DMA controller */
- SOUNDSCAPE_EnableInterrupt();
- /* start the AD-1848 */
- ad_write(AD_CONFIG, 0x01);
- SOUNDSCAPE_SoundPlaying = TRUE;
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_BeginBufferedPlayback
- Begins multibuffered playback of digitized sound on the sound card.
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_BeginBufferedPlayback
- (
- char *BufferStart,
- int BufferSize,
- int NumDivisions,
- unsigned SampleRate,
- int MixMode,
- void ( *CallBackFunc )( void )
- )
- {
- int DmaStatus;
- int TransferLength;
- if ( SOUNDSCAPE_SoundPlaying )
- {
- SOUNDSCAPE_StopPlayback();
- }
- SOUNDSCAPE_SetMixMode( MixMode );
- DmaStatus = SOUNDSCAPE_SetupDMABuffer( BufferStart, BufferSize,
- DMA_AutoInitRead );
- if ( DmaStatus == SOUNDSCAPE_Error )
- {
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_SetPlaybackRate( SampleRate );
- SOUNDSCAPE_SetCallBack( CallBackFunc );
- SOUNDSCAPE_EnableInterrupt();
- TransferLength = BufferSize / NumDivisions;
- SOUNDSCAPE_TransferLength = TransferLength;
- SOUNDSCAPE_BeginPlayback( TransferLength );
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_GetCardInfo
- Returns the maximum number of bits that can represent a sample
- (8 or 16) and the number of channels (1 for mono, 2 for stereo).
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_GetCardInfo
- (
- int *MaxSampleBits,
- int *MaxChannels
- )
- {
- int status;
- status = SOUNDSCAPE_FindCard();
- if ( status == SOUNDSCAPE_Ok )
- {
- *MaxChannels = 2;
- *MaxSampleBits = 16;
- return( SOUNDSCAPE_Ok );
- }
- return( status );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_SetCallBack
- Specifies the user function to call at the end of a sound transfer.
- ---------------------------------------------------------------------*/
- void SOUNDSCAPE_SetCallBack
- (
- void ( *func )( void )
- )
- {
- SOUNDSCAPE_CallBack = func;
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_LockEnd
- Used for determining the length of the functions to lock in memory.
- ---------------------------------------------------------------------*/
- static void SOUNDSCAPE_LockEnd
- (
- void
- )
- {
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_UnlockMemory
- Unlocks all neccessary data.
- ---------------------------------------------------------------------*/
- static void SOUNDSCAPE_UnlockMemory
- (
- void
- )
- {
- DPMI_UnlockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
- DPMI_Unlock( SOUNDSCAPE_Config );
- DPMI_Unlock( SOUNDSCAPE_OldInt );
- DPMI_Unlock( SOUNDSCAPE_Installed );
- DPMI_Unlock( SOUNDSCAPE_DMABuffer );
- DPMI_Unlock( SOUNDSCAPE_DMABufferEnd );
- DPMI_Unlock( SOUNDSCAPE_CurrentDMABuffer );
- DPMI_Unlock( SOUNDSCAPE_TotalDMABufferSize );
- DPMI_Unlock( SOUNDSCAPE_TransferLength );
- DPMI_Unlock( SOUNDSCAPE_MixMode );
- DPMI_Unlock( SOUNDSCAPE_SamplePacketSize );
- DPMI_Unlock( SOUNDSCAPE_SampleRate );
- DPMI_Unlock( SOUNDSCAPE_SoundPlaying );
- DPMI_Unlock( SOUNDSCAPE_CallBack );
- DPMI_Unlock( SOUNDSCAPE_IntController1Mask );
- DPMI_Unlock( SOUNDSCAPE_IntController2Mask );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_LockMemory
- Locks all neccessary data.
- ---------------------------------------------------------------------*/
- static int SOUNDSCAPE_LockMemory
- (
- void
- )
- {
- int status;
- status = DPMI_LockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
- status |= DPMI_Lock( SOUNDSCAPE_Config );
- status |= DPMI_Lock( SOUNDSCAPE_OldInt );
- status |= DPMI_Lock( SOUNDSCAPE_Installed );
- status |= DPMI_Lock( SOUNDSCAPE_DMABuffer );
- status |= DPMI_Lock( SOUNDSCAPE_DMABufferEnd );
- status |= DPMI_Lock( SOUNDSCAPE_CurrentDMABuffer );
- status |= DPMI_Lock( SOUNDSCAPE_TotalDMABufferSize );
- status |= DPMI_Lock( SOUNDSCAPE_TransferLength );
- status |= DPMI_Lock( SOUNDSCAPE_MixMode );
- status |= DPMI_Lock( SOUNDSCAPE_SamplePacketSize );
- status |= DPMI_Lock( SOUNDSCAPE_SampleRate );
- status |= DPMI_Lock( SOUNDSCAPE_SoundPlaying );
- status |= DPMI_Lock( SOUNDSCAPE_CallBack );
- status |= DPMI_Lock( SOUNDSCAPE_IntController1Mask );
- status |= DPMI_Lock( SOUNDSCAPE_IntController2Mask );
- if ( status != DPMI_Ok )
- {
- SOUNDSCAPE_UnlockMemory();
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DPMI_Error );
- return( SOUNDSCAPE_Error );
- }
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: allocateTimerStack
- Allocate a block of memory from conventional (low) memory and return
- the selector (which can go directly into a segment register) of the
- memory block or 0 if an error occured.
- ---------------------------------------------------------------------*/
- static unsigned short allocateTimerStack
- (
- unsigned short size
- )
- {
- union REGS regs;
- // clear all registers
- memset( ®s, 0, sizeof( regs ) );
- // DPMI allocate conventional memory
- regs.w.ax = 0x100;
- // size in paragraphs
- regs.w.bx = ( size + 15 ) / 16;
- int386( 0x31, ®s, ®s );
- if (!regs.w.cflag)
- {
- // DPMI call returns selector in dx
- // (ax contains real mode segment
- // which is ignored here)
- return( regs.w.dx );
- }
- // Couldn't allocate memory.
- return( NULL );
- }
- /*---------------------------------------------------------------------
- Function: deallocateTimerStack
- Deallocate a block of conventional (low) memory given a selector to
- it. Assumes the block was allocated with DPMI function 0x100.
- ---------------------------------------------------------------------*/
- static void deallocateTimerStack
- (
- unsigned short selector
- )
- {
- union REGS regs;
- if ( selector != NULL )
- {
- // clear all registers
- memset( ®s, 0, sizeof( regs ) );
- regs.w.ax = 0x101;
- regs.w.dx = selector;
- int386( 0x31, ®s, ®s );
- }
- }
- /*---------------------------------------------------------------------
- Function: parse
- Parses for the right hand string of an .INI file equate.
- ---------------------------------------------------------------------*/
- static int parse
- (
- char *val,
- char *str,
- FILE *p1
- )
- {
- int i;
- int j;
- char tmpstr[ 81 ];
- rewind( p1 );
- while( !feof( p1 ) )
- {
- // get a new string
- fgets( tmpstr, 81, p1 );
- if( ( tmpstr[ 0 ] == '[' ) || ( tmpstr[ 0 ] == ';' ) ||
- ( tmpstr[ 0 ] == '\n' ) )
- {
- continue;
- }
- // parse up to the '='
- i = 0;
- while( ( tmpstr[ i ] != '=' ) && ( tmpstr[ i ] != '\n' ) )
- {
- i++;
- }
- if( tmpstr[ i ] != '=' )
- {
- continue;
- }
- tmpstr[ i ] = '\0';
- // see if it's the one we want
- if ( strcmp( tmpstr, str ) )
- {
- continue;
- }
- // copy the right hand value to the destination string
- i++;
- for( j = 0; j < 32; j++ )
- {
- if ( ( tmpstr[ i ] == ' ' ) || ( tmpstr[ i ] == '\t' ) ||
- ( tmpstr[ i ] == ',' ) || ( tmpstr[ i ] == '\n' ) )
- {
- break;
- }
- val[ j ] = tmpstr[ i ];
- i++;
- }
- val[j] = '\0';
- return( TRUE );
- }
- return( FALSE );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_FindCard
- Determines if a SoundScape is present and where it is located.
- ---------------------------------------------------------------------*/
- static int SOUNDSCAPE_FindCard
- (
- void
- )
- {
- int found;
- int status;
- int tmp;
- char *cp;
- char str[ 33 ];
- FILE *fp;
- if ( SOUNDSCAPE_FoundCard )
- {
- return( SOUNDSCAPE_Ok );
- }
- cp = getenv( "SNDSCAPE" );
- if ( cp == NULL )
- {
- strcpy( str, "C:\\SNDSCAPE" );
- }
- else
- {
- strcpy( str, cp );
- }
- strcat(str, "\\SNDSCAPE.INI");
- fp = fopen( str, "r" );
- if ( fp == NULL )
- {
- if ( cp == NULL )
- {
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_EnvNotFound );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InitFileNotFound );
- return( SOUNDSCAPE_Error );
- }
- found = parse( str, "Product", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingProductInfo );
- return( SOUNDSCAPE_Error );
- }
- if( strstr( str, "SoundFX" ) == NULL )
- {
- SOUNDSCAPE_Config.OldIRQs = FALSE;
- }
- else
- {
- SOUNDSCAPE_Config.OldIRQs = TRUE;
- }
- found = parse( str, "Port", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingPortInfo );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_Config.BasePort = strtol( str, ( char ** )0, 16);
- found = parse( str, "DMA", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingDMAInfo );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_Config.DMAChan = ( int )strtol( str, ( char ** )0, 10 );
- status = DMA_VerifyChannel( SOUNDSCAPE_Config.DMAChan );
- if ( status == DMA_Error )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
- return( SOUNDSCAPE_Error );
- }
- found = parse( str, "IRQ", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingIRQInfo );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_Config.MIDIIRQ = ( int )strtol( str, ( char ** )0, 10 );
- if ( SOUNDSCAPE_Config.MIDIIRQ == 2 )
- {
- SOUNDSCAPE_Config.MIDIIRQ = 9;
- }
- found = parse( str, "SBIRQ", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBIRQInfo );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_Config.WaveIRQ = ( int )strtol( str, ( char ** )0, 10 );
- if ( SOUNDSCAPE_Config.WaveIRQ == 2 )
- {
- SOUNDSCAPE_Config.WaveIRQ = 9;
- }
- if ( !VALID_IRQ( SOUNDSCAPE_Config.WaveIRQ ) )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
- return( SOUNDSCAPE_Error );
- }
- if ( SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ] == INVALID )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
- return( SOUNDSCAPE_Error );
- }
- found = parse( str, "SBEnable", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBENABLEInfo );
- return( SOUNDSCAPE_Error );
- }
- if( !strcmp( str, "false" ) )
- {
- SOUNDSCAPE_Config.SBEmul = FALSE;
- }
- else
- {
- SOUNDSCAPE_Config.SBEmul = TRUE;
- }
- // do a hardware test
- outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, 0x00f5 );
- tmp = inp( SOUNDSCAPE_Config.BasePort + GA_REGADDR );
- if ( ( tmp & 0x000f ) != 0x0005 )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
- return( SOUNDSCAPE_Error );
- }
- if( ( tmp & 0x00f0 ) == 0x00f0 )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
- return( SOUNDSCAPE_Error );
- }
- // formulate the chip ID
- tmp >>= 4;
- if( tmp == 0 )
- {
- SOUNDSCAPE_Config.ChipID = ODIE;
- }
- else if ( !( tmp & 0x0008 ) )
- {
- SOUNDSCAPE_Config.ChipID = OPUS;
- }
- else
- {
- SOUNDSCAPE_Config.ChipID = MMIC;
- }
- // parse for the AD-1848 address if necessary
- if( SOUNDSCAPE_Config.ChipID == ODIE )
- {
- found = parse( str, "WavePort", fp );
- if ( !found )
- {
- fclose( fp );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingWavePortInfo );
- return( SOUNDSCAPE_Error );
- }
- SOUNDSCAPE_Config.WavePort = strtol( str, ( char ** )0, 16 );
- }
- else
- {
- // otherwise, the base address is fixed
- SOUNDSCAPE_Config.WavePort = SOUNDSCAPE_Config.BasePort + AD_OFFSET;
- }
- // we're done with the file
- fclose( fp );
- // if it's an ODIE board, note CD-ROM decode enable
- if ( SOUNDSCAPE_Config.ChipID == ODIE )
- {
- SOUNDSCAPE_Config.CDROM = ga_read( GA_CDCFG ) & 0x80;
- }
- // build the Wave IRQ index value
- if( !SOUNDSCAPE_Config.OldIRQs )
- {
- switch( SOUNDSCAPE_Config.WaveIRQ )
- {
- case 9 :
- SOUNDSCAPE_Config.IRQIndx = 0;
- break;
- case 5 :
- SOUNDSCAPE_Config.IRQIndx = 1;
- break;
- case 7 :
- SOUNDSCAPE_Config.IRQIndx = 2;
- break;
- default :
- SOUNDSCAPE_Config.IRQIndx = 3;
- break;
- }
- }
- else
- {
- switch( SOUNDSCAPE_Config.WaveIRQ )
- {
- case 9 :
- SOUNDSCAPE_Config.IRQIndx = 0;
- break;
- case 5 :
- SOUNDSCAPE_Config.IRQIndx = 2;
- break;
- case 7 :
- SOUNDSCAPE_Config.IRQIndx = 1;
- break;
- default :
- SOUNDSCAPE_Config.IRQIndx = 3;
- break;
- }
- }
- SOUNDSCAPE_FoundCard = TRUE;
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_Setup
- Setup the Soundscape card for native mode PCM.
- ---------------------------------------------------------------------*/
- static int SOUNDSCAPE_Setup
- (
- void
- )
- {
- int tmp;
- int Interrupt;
- int status;
- // if necessary, clear any pending SB ints
- if ( SOUNDSCAPE_Config.SBEmul )
- {
- inp( SB_IACK );
- }
- SOUNDSCAPE_DisableInterrupt();
- // make sure the AD-1848 is not running
- if ( ad_read( AD_CONFIG ) & 0x01 )
- {
- SOUNDSCAPE_StopPlayback();
- }
- // if necessary, do some signal re-routing
- if( SOUNDSCAPE_Config.ChipID != MMIC )
- {
- // get the gate-array off of the DMA channel
- ga_write( GA_DMACHB, 0x20 );
- if ( !SOUNDSCAPE_Config.OldIRQs )
- {
- switch( SOUNDSCAPE_Config.MIDIIRQ )
- {
- case 5 :
- tmp = 1;
- break;
- case 7 :
- tmp = 2;
- break;
- case 9 :
- tmp = 0;
- break;
- default :
- tmp = 3;
- break;
- }
- }
- else
- {
- switch( SOUNDSCAPE_Config.MIDIIRQ )
- {
- case 5 :
- tmp = 2;
- break;
- case 7 :
- tmp = 1;
- break;
- case 9 :
- tmp = 0;
- break;
- default :
- tmp = 3;
- break;
- }
- }
- // set HostIRQ to MIDIIRQ for now
- ga_write( GA_INTCFG, 0xf0 | ( tmp << 2 ) | tmp );
- // now, route the AD-1848 stuff ...
- if ( SOUNDSCAPE_Config.ChipID == OPUS )
- {
- // set the AD-1848 chip decode
- ga_write( GA_HMCTL, ( ga_read( GA_HMCTL ) & 0xcf ) | 0x10 );
- }
- // setup the DMA polarity
- ga_write( GA_DMACFG, 0x50 );
- // init the CD-ROM (AD-1848) config register
- ga_write( GA_CDCFG, 0x89 | ( SOUNDSCAPE_Config.DMAChan << 4 ) | ( SOUNDSCAPE_Config.IRQIndx << 1 ) );
- // enable mode change, point to config reg
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_CONFIG );
- // set interf cnfg reg for DMA mode, single chan, autocal on
- outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, 0x0c );
- // exit mode change state
- outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
- // delay for autocalibration
- tdelay();
- }
- // Install our interrupt handler
- Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
- SOUNDSCAPE_OldInt = _dos_getvect( Interrupt );
- if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
- {
- _dos_setvect( Interrupt, SOUNDSCAPE_ServiceInterrupt );
- }
- else
- {
- status = IRQ_SetVector( Interrupt, SOUNDSCAPE_ServiceInterrupt );
- if ( status != IRQ_Ok )
- {
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_UnableToSetIrq );
- return( SOUNDSCAPE_Error );
- }
- }
- // max left and right volumes
- ad_write( AD_LEFTOUT, 0 );
- ad_write( AD_RIGHTOUT, 0 );
- // clear any pending interrupt condition
- outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
- // enable the interrupt pin
- ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) | 0x02 );
- SOUNDSCAPE_EnableInterrupt();
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_GetMIDIPort
- Gets the address of the SoundScape MIDI port.
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_GetMIDIPort
- (
- void
- )
- {
- int status;
- status = SOUNDSCAPE_FindCard();
- if ( status != SOUNDSCAPE_Ok )
- {
- return( status );
- }
- return( SOUNDSCAPE_Config.BasePort );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_Init
- Initializes the sound card and prepares the module to play
- digitized sounds.
- ---------------------------------------------------------------------*/
- int SOUNDSCAPE_Init
- (
- void
- )
- {
- int status;
- if ( SOUNDSCAPE_Installed )
- {
- SOUNDSCAPE_Shutdown();
- }
- // Save the interrupt masks
- SOUNDSCAPE_IntController1Mask = inp( 0x21 );
- SOUNDSCAPE_IntController2Mask = inp( 0xA1 );
- SOUNDSCAPE_SoundPlaying = FALSE;
- SOUNDSCAPE_SetCallBack( NULL );
- SOUNDSCAPE_DMABuffer = NULL;
- status = SOUNDSCAPE_FindCard();
- if ( status != SOUNDSCAPE_Ok )
- {
- return( status );
- }
- status = SOUNDSCAPE_LockMemory();
- if ( status != SOUNDSCAPE_Ok )
- {
- SOUNDSCAPE_UnlockMemory();
- return( status );
- }
- StackSelector = allocateTimerStack( kStackSize );
- if ( StackSelector == NULL )
- {
- SOUNDSCAPE_UnlockMemory();
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_OutOfMemory );
- return( SOUNDSCAPE_Error );
- }
- // Leave a little room at top of stack just for the hell of it...
- StackPointer = kStackSize - sizeof( long );
- SOUNDSCAPE_Installed = TRUE;
- status = SOUNDSCAPE_Setup();
- if ( status != SOUNDSCAPE_Ok )
- {
- SOUNDSCAPE_Shutdown();
- return( status );
- }
- // printf("Testing DMA and IRQ ...\n");
- // if( test_dma_irq() )
- // {
- // printf("\t\007Hardware Not Responding\n\n");
- // close_soundscape();
- // return( SOUNDSCAPE_Error );
- // }
- SOUNDSCAPE_SetPlaybackRate( SOUNDSCAPE_DefaultSampleRate );
- SOUNDSCAPE_SetMixMode( SOUNDSCAPE_DefaultMixMode );
- SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
- return( SOUNDSCAPE_Ok );
- }
- /*---------------------------------------------------------------------
- Function: SOUNDSCAPE_Shutdown
- Ends transfer of sound data to the sound card and restores the
- system resources used by the card.
- ---------------------------------------------------------------------*/
- void SOUNDSCAPE_Shutdown
- (
- void
- )
- {
- int Interrupt;
- // Halt the DMA transfer
- SOUNDSCAPE_StopPlayback();
- // disable the AD-1848 interrupt pin
- ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) & 0xfd );
- // if necessary, do some signal re-routing
- if ( SOUNDSCAPE_Config.ChipID != MMIC )
- {
- // re-init the CD-ROM (AD-1848) config register as needed.
- // this will disable the AD-1848 interface.
- if ( SOUNDSCAPE_Config.ChipID == ODIE )
- {
- ga_write( GA_CDCFG, SOUNDSCAPE_Config.CDROM );
- }
- else
- {
- ga_write( GA_CDCFG, ga_read( GA_CDCFG ) & 0x7f);
- }
- // if necessary, reset the SoundBlaster IRQ
- if ( SOUNDSCAPE_Config.SBEmul )
- {
- ga_write( GA_INTCFG, ( ga_read( GA_INTCFG ) & 0xf3 ) |
- ( SOUNDSCAPE_Config.IRQIndx << 2 ) );
- }
- // re-assign the gate-array DMA channel
- ga_write( GA_DMACHB, 0x80 | ( SOUNDSCAPE_Config.DMAChan << 4 ) );
- }
- // Restore the original interrupt
- Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
- if ( SOUNDSCAPE_Config.WaveIRQ >= 8 )
- {
- IRQ_RestoreVector( Interrupt );
- }
- _dos_setvect( Interrupt, SOUNDSCAPE_OldInt );
- SOUNDSCAPE_SoundPlaying = FALSE;
- SOUNDSCAPE_DMABuffer = NULL;
- SOUNDSCAPE_SetCallBack( NULL );
- SOUNDSCAPE_UnlockMemory();
- if ( StackSelector != NULL )
- {
- deallocateTimerStack( StackSelector );
- StackSelector = NULL;
- }
- SOUNDSCAPE_Installed = FALSE;
- }
|