BLASTOLD.C 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416
  1. /*
  2. Copyright (C) 1994-1995 Apogee Software, Ltd.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /**********************************************************************
  16. module: BLASTER.C
  17. author: James R. Dose
  18. date: February 4, 1994
  19. Low level routines to support Sound Blaster, Sound Blaster Pro,
  20. Sound Blaster 16, and compatible sound cards.
  21. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  22. **********************************************************************/
  23. #include <dos.h>
  24. #include <conio.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include "dpmi.h"
  30. #include "dma.h"
  31. #include "irq.h"
  32. #include "blaster.h"
  33. #include "_blaster.h"
  34. #define USESTACK
  35. const int BLASTER_Interrupts[ BLASTER_MaxIrq + 1 ] =
  36. {
  37. INVALID, INVALID, 0xa, 0xb,
  38. INVALID, 0xd, INVALID, 0xf,
  39. INVALID, INVALID, 0x72, 0x73,
  40. 0x74, INVALID, INVALID, 0x77
  41. };
  42. const int BLASTER_SampleSize[ BLASTER_MaxMixMode + 1 ] =
  43. {
  44. MONO_8BIT_SAMPLE_SIZE, STEREO_8BIT_SAMPLE_SIZE,
  45. MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
  46. };
  47. const CARD_CAPABILITY BLASTER_CardConfig[ BLASTER_MaxCardType + 1 ] =
  48. {
  49. { FALSE, INVALID, INVALID, INVALID, INVALID }, // Unsupported
  50. { TRUE, NO, MONO_8BIT, 4000, 23000 }, // SB 1.0
  51. { TRUE, YES, STEREO_8BIT, 4000, 44100 }, // SBPro
  52. { TRUE, NO, MONO_8BIT, 4000, 23000 }, // SB 2.xx
  53. { TRUE, YES, STEREO_8BIT, 4000, 44100 }, // SBPro 2
  54. { FALSE, INVALID, INVALID, INVALID, INVALID }, // Unsupported
  55. { TRUE, YES, STEREO_16BIT, 5000, 44100 }, // SB16
  56. };
  57. static void ( __interrupt __far *BLASTER_OldInt )( void );
  58. BLASTER_CONFIG BLASTER_Config =
  59. {
  60. UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED
  61. };
  62. static int BLASTER_Installed = FALSE;
  63. static int BLASTER_Version;
  64. static char *BLASTER_DMABuffer;
  65. static char *BLASTER_DMABufferEnd;
  66. static char *BLASTER_CurrentDMABuffer;
  67. static int BLASTER_TotalDMABufferSize;
  68. static int BLASTER_TransferLength = 0;
  69. static int BLASTER_MixMode = BLASTER_DefaultMixMode;
  70. static int BLASTER_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
  71. static unsigned BLASTER_SampleRate = BLASTER_DefaultSampleRate;
  72. static unsigned BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  73. volatile int BLASTER_SoundPlaying;
  74. volatile int BLASTER_SoundRecording;
  75. void ( *BLASTER_CallBack )( void );
  76. static int BLASTER_IntController1Mask;
  77. static int BLASTER_IntController2Mask;
  78. static int BLASTER_MixerAddress = UNDEFINED;
  79. static int BLASTER_MixerType = 0;
  80. static int BLASTER_OriginalMidiVolumeLeft = 255;
  81. static int BLASTER_OriginalMidiVolumeRight = 255;
  82. static int BLASTER_OriginalVoiceVolumeLeft = 255;
  83. static int BLASTER_OriginalVoiceVolumeRight = 255;
  84. static int BLASTER_WaveBlasterPort = UNDEFINED;
  85. static int BLASTER_WaveBlasterState = 0x0F;
  86. // adequate stack size
  87. #define kStackSize 2048
  88. static unsigned short StackSelector = NULL;
  89. static unsigned long StackPointer;
  90. static unsigned short oldStackSelector;
  91. static unsigned long oldStackPointer;
  92. // This is defined because we can't create local variables in a
  93. // function that switches stacks.
  94. static int GlobalStatus;
  95. // These declarations are necessary to use the inline assembly pragmas.
  96. extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
  97. extern void SetStack(unsigned short selector,unsigned long stackptr);
  98. // This function will get the current stack selector and pointer and save
  99. // them off.
  100. #pragma aux GetStack = \
  101. "mov [edi],esp" \
  102. "mov ax,ss" \
  103. "mov [esi],ax" \
  104. parm [esi] [edi] \
  105. modify [eax esi edi];
  106. // This function will set the stack selector and pointer to the specified
  107. // values.
  108. #pragma aux SetStack = \
  109. "mov ss,ax" \
  110. "mov esp,edx" \
  111. parm [ax] [edx] \
  112. modify [eax edx];
  113. int BLASTER_DMAChannel;
  114. int BLASTER_ErrorCode = BLASTER_Ok;
  115. #define BLASTER_SetErrorCode( status ) \
  116. BLASTER_ErrorCode = ( status );
  117. /*---------------------------------------------------------------------
  118. Function: BLASTER_ErrorString
  119. Returns a pointer to the error message associated with an error
  120. number. A -1 returns a pointer the current error.
  121. ---------------------------------------------------------------------*/
  122. char *BLASTER_ErrorString
  123. (
  124. int ErrorNumber
  125. )
  126. {
  127. char *ErrorString;
  128. switch( ErrorNumber )
  129. {
  130. case BLASTER_Warning :
  131. case BLASTER_Error :
  132. ErrorString = BLASTER_ErrorString( BLASTER_ErrorCode );
  133. break;
  134. case BLASTER_Ok :
  135. ErrorString = "Sound Blaster ok.";
  136. break;
  137. case BLASTER_EnvNotFound :
  138. ErrorString = "BLASTER environment variable not set.";
  139. break;
  140. case BLASTER_AddrNotSet :
  141. ErrorString = "Missing Sound Blaster address in BLASTER environment variable.";
  142. break;
  143. case BLASTER_IntNotSet :
  144. ErrorString = "Missing Sound Blaster interrupt in BLASTER environment variable.";
  145. break;
  146. case BLASTER_DMANotSet :
  147. ErrorString = "Missing Sound Blaster DMA channel in BLASTER environment variable.";
  148. break;
  149. case BLASTER_DMA16NotSet :
  150. ErrorString = "Missing Sound Blaster 16-bit DMA channel in BLASTER environment variable.";
  151. break;
  152. case BLASTER_MIDINotSet :
  153. ErrorString = "Missing WaveBlaster MIDI port in BLASTER environment variable.";
  154. break;
  155. case BLASTER_CardTypeNotSet :
  156. ErrorString = "Missing Sound Blaster card Type parameter in BLASTER environment variable.";
  157. break;
  158. case BLASTER_InvalidParameter :
  159. ErrorString = "Invalid parameter in BLASTER environment variable.";
  160. break;
  161. case BLASTER_UnsupportedCardType :
  162. ErrorString = "Unsupported card selected in BLASTER environment variable T parameter.";
  163. break;
  164. case BLASTER_CardNotReady :
  165. ErrorString = "Sound Blaster not responding on selected port.";
  166. break;
  167. case BLASTER_NoSoundPlaying :
  168. ErrorString = "No sound playing on Sound Blaster.";
  169. break;
  170. case BLASTER_InvalidIrq :
  171. ErrorString = "Invalid Sound Blaster Irq.";
  172. break;
  173. case BLASTER_UnableToSetIrq :
  174. ErrorString = "Unable to set Sound Blaster IRQ. Try selecting an IRQ of 7 or below.";
  175. break;
  176. case BLASTER_DmaError :
  177. ErrorString = DMA_ErrorString( DMA_Error );
  178. break;
  179. case BLASTER_NoMixer :
  180. ErrorString = "Mixer not available on selected Sound Blaster card.";
  181. break;
  182. case BLASTER_DPMI_Error :
  183. ErrorString = "DPMI Error in Blaster.";
  184. break;
  185. case BLASTER_OutOfMemory :
  186. ErrorString = "Out of conventional memory in Blaster.";
  187. break;
  188. default :
  189. ErrorString = "Unknown Sound Blaster error code.";
  190. break;
  191. }
  192. return( ErrorString );
  193. }
  194. /**********************************************************************
  195. Memory locked functions:
  196. **********************************************************************/
  197. #define BLASTER_LockStart BLASTER_EnableInterrupt
  198. /*---------------------------------------------------------------------
  199. Function: BLASTER_EnableInterrupt
  200. Enables the triggering of the sound card interrupt.
  201. ---------------------------------------------------------------------*/
  202. void BLASTER_EnableInterrupt
  203. (
  204. void
  205. )
  206. {
  207. int Irq;
  208. int mask;
  209. // Unmask system interrupt
  210. Irq = BLASTER_Config.Interrupt;
  211. if ( Irq < 8 )
  212. {
  213. mask = inp( 0x21 ) & ~( 1 << Irq );
  214. outp( 0x21, mask );
  215. }
  216. else
  217. {
  218. mask = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
  219. outp( 0xA1, mask );
  220. mask = inp( 0x21 ) & ~( 1 << 2 );
  221. outp( 0x21, mask );
  222. }
  223. }
  224. /*---------------------------------------------------------------------
  225. Function: BLASTER_DisableInterrupt
  226. Disables the triggering of the sound card interrupt.
  227. ---------------------------------------------------------------------*/
  228. void BLASTER_DisableInterrupt
  229. (
  230. void
  231. )
  232. {
  233. int Irq;
  234. int mask;
  235. // Restore interrupt mask
  236. Irq = BLASTER_Config.Interrupt;
  237. if ( Irq < 8 )
  238. {
  239. mask = inp( 0x21 ) & ~( 1 << Irq );
  240. mask |= BLASTER_IntController1Mask & ( 1 << Irq );
  241. outp( 0x21, mask );
  242. }
  243. else
  244. {
  245. mask = inp( 0x21 ) & ~( 1 << 2 );
  246. mask |= BLASTER_IntController1Mask & ( 1 << 2 );
  247. outp( 0x21, mask );
  248. mask = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
  249. mask |= BLASTER_IntController2Mask & ( 1 << ( Irq - 8 ) );
  250. outp( 0xA1, mask );
  251. }
  252. }
  253. /*---------------------------------------------------------------------
  254. Function: BLASTER_ServiceInterrupt
  255. Handles interrupt generated by sound card at the end of a voice
  256. transfer. Calls the user supplied callback function.
  257. ---------------------------------------------------------------------*/
  258. void __interrupt __far BLASTER_ServiceInterrupt
  259. (
  260. void
  261. )
  262. {
  263. #ifdef USESTACK
  264. // save stack
  265. GetStack( &oldStackSelector, &oldStackPointer );
  266. // set our stack
  267. SetStack( StackSelector, StackPointer );
  268. #endif
  269. // Acknowledge interrupt
  270. // Check if this is this an SB16 or newer
  271. if ( BLASTER_Version >= DSP_Version4xx )
  272. {
  273. outp( BLASTER_Config.Address + BLASTER_MixerAddressPort,
  274. MIXER_DSP4xxISR_Ack );
  275. GlobalStatus = inp( BLASTER_Config.Address + BLASTER_MixerDataPort );
  276. // Check if a 16-bit DMA interrupt occurred
  277. if ( GlobalStatus & MIXER_16BITDMA_INT )
  278. {
  279. // Acknowledge 16-bit transfer interrupt
  280. inp( BLASTER_Config.Address + BLASTER_16BitDMAAck );
  281. }
  282. else if ( GlobalStatus & MIXER_8BITDMA_INT )
  283. {
  284. inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
  285. }
  286. else
  287. {
  288. #ifdef USESTACK
  289. // restore stack
  290. SetStack( oldStackSelector, oldStackPointer );
  291. #endif
  292. // Wasn't our interrupt. Call the old one.
  293. _chain_intr( BLASTER_OldInt );
  294. }
  295. }
  296. else
  297. {
  298. // Older card - can't detect if an interrupt occurred.
  299. inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
  300. }
  301. // Keep track of current buffer
  302. BLASTER_CurrentDMABuffer += BLASTER_TransferLength;
  303. if ( BLASTER_CurrentDMABuffer >= BLASTER_DMABufferEnd )
  304. {
  305. BLASTER_CurrentDMABuffer = BLASTER_DMABuffer;
  306. }
  307. // Continue playback on cards without autoinit mode
  308. if ( BLASTER_Version < DSP_Version2xx )
  309. {
  310. if ( BLASTER_SoundPlaying )
  311. {
  312. BLASTER_DSP1xx_BeginPlayback( BLASTER_TransferLength );
  313. }
  314. if ( BLASTER_SoundRecording )
  315. {
  316. BLASTER_DSP1xx_BeginRecord( BLASTER_TransferLength );
  317. }
  318. }
  319. // Call the caller's callback function
  320. if ( BLASTER_CallBack != NULL )
  321. {
  322. BLASTER_CallBack();
  323. }
  324. #ifdef USESTACK
  325. // restore stack
  326. SetStack( oldStackSelector, oldStackPointer );
  327. #endif
  328. // send EOI to Interrupt Controller
  329. if ( BLASTER_Config.Interrupt > 7 )
  330. {
  331. outp( 0xA0, 0x20 );
  332. }
  333. outp( 0x20, 0x20 );
  334. }
  335. /*---------------------------------------------------------------------
  336. Function: BLASTER_WriteDSP
  337. Writes a byte of data to the sound card's DSP.
  338. ---------------------------------------------------------------------*/
  339. int BLASTER_WriteDSP
  340. (
  341. unsigned data
  342. )
  343. {
  344. int port;
  345. unsigned count;
  346. int status;
  347. port = BLASTER_Config.Address + BLASTER_WritePort;
  348. status = BLASTER_Error;
  349. count = 0xFFFF;
  350. do
  351. {
  352. if ( ( inp( port ) & 0x80 ) == 0 )
  353. {
  354. outp( port, data );
  355. status = BLASTER_Ok;
  356. break;
  357. }
  358. count--;
  359. }
  360. while( count > 0 );
  361. if ( status != BLASTER_Ok )
  362. {
  363. BLASTER_SetErrorCode( BLASTER_CardNotReady );
  364. }
  365. return( status );
  366. }
  367. /*---------------------------------------------------------------------
  368. Function: BLASTER_ReadDSP
  369. Reads a byte of data from the sound card's DSP.
  370. ---------------------------------------------------------------------*/
  371. int BLASTER_ReadDSP
  372. (
  373. void
  374. )
  375. {
  376. int port;
  377. unsigned count;
  378. int status;
  379. port = BLASTER_Config.Address + BLASTER_DataAvailablePort;
  380. status = BLASTER_Error;
  381. count = 0xFFFF;
  382. do
  383. {
  384. if ( inp( port ) & 0x80 )
  385. {
  386. status = inp( BLASTER_Config.Address + BLASTER_ReadPort );
  387. break;
  388. }
  389. count--;
  390. }
  391. while( count > 0 );
  392. if ( status == BLASTER_Error )
  393. {
  394. BLASTER_SetErrorCode( BLASTER_CardNotReady );
  395. }
  396. return( status );
  397. }
  398. /*---------------------------------------------------------------------
  399. Function: BLASTER_ResetDSP
  400. Sends a reset command to the sound card's Digital Signal Processor
  401. (DSP), causing it to perform an initialization.
  402. ---------------------------------------------------------------------*/
  403. int BLASTER_ResetDSP
  404. (
  405. void
  406. )
  407. {
  408. volatile int count;
  409. int port;
  410. int status;
  411. port = BLASTER_Config.Address + BLASTER_ResetPort;
  412. status = BLASTER_CardNotReady;
  413. outp( port, 1 );
  414. /* What the hell am I doing here?
  415. count = 100;
  416. do
  417. {
  418. if ( inp( port ) == 255 )
  419. {
  420. break;
  421. }
  422. count--;
  423. }
  424. while( count > 0 );
  425. */
  426. count = 0x100;
  427. do
  428. {
  429. count--;
  430. }
  431. while( count > 0 );
  432. outp( port, 0 );
  433. count = 100;
  434. do
  435. {
  436. if ( BLASTER_ReadDSP() == BLASTER_Ready )
  437. {
  438. status = BLASTER_Ok;
  439. break;
  440. }
  441. count--;
  442. }
  443. while( count > 0 );
  444. return( status );
  445. }
  446. /*---------------------------------------------------------------------
  447. Function: BLASTER_GetDSPVersion
  448. Returns the version number of the sound card's DSP.
  449. ---------------------------------------------------------------------*/
  450. int BLASTER_GetDSPVersion
  451. (
  452. void
  453. )
  454. {
  455. int MajorVersion;
  456. int MinorVersion;
  457. int version;
  458. BLASTER_WriteDSP( DSP_GetVersion );
  459. MajorVersion = BLASTER_ReadDSP();
  460. MinorVersion = BLASTER_ReadDSP();
  461. if ( ( MajorVersion == BLASTER_Error ) ||
  462. ( MinorVersion == BLASTER_Error ) )
  463. {
  464. BLASTER_SetErrorCode( BLASTER_CardNotReady );
  465. return( BLASTER_Error );
  466. }
  467. version = ( MajorVersion << 8 ) + MinorVersion;
  468. return( version );
  469. }
  470. /*---------------------------------------------------------------------
  471. Function: BLASTER_SpeakerOn
  472. Enables output from the DAC.
  473. ---------------------------------------------------------------------*/
  474. void BLASTER_SpeakerOn
  475. (
  476. void
  477. )
  478. {
  479. BLASTER_WriteDSP( DSP_SpeakerOn );
  480. }
  481. /*---------------------------------------------------------------------
  482. Function: BLASTER_SpeakerOff
  483. Disables output from the DAC.
  484. ---------------------------------------------------------------------*/
  485. void BLASTER_SpeakerOff
  486. (
  487. void
  488. )
  489. {
  490. BLASTER_WriteDSP( DSP_SpeakerOff );
  491. }
  492. /*---------------------------------------------------------------------
  493. Function: BLASTER_SetPlaybackRate
  494. Sets the rate at which the digitized sound will be played in
  495. hertz.
  496. ---------------------------------------------------------------------*/
  497. void BLASTER_SetPlaybackRate
  498. (
  499. unsigned rate
  500. )
  501. {
  502. int LoByte;
  503. int HiByte;
  504. CARD_CAPABILITY const *card;
  505. card = &BLASTER_CardConfig[ BLASTER_Config.Type ];
  506. if ( BLASTER_Version < DSP_Version4xx )
  507. {
  508. int timeconstant;
  509. long ActualRate;
  510. // Send sampling rate as time constant for older Sound
  511. // Blaster compatible cards.
  512. ActualRate = rate * BLASTER_SamplePacketSize;
  513. if ( ActualRate < card->MinSamplingRate )
  514. {
  515. rate = card->MinSamplingRate / BLASTER_SamplePacketSize;
  516. }
  517. if ( ActualRate > card->MaxSamplingRate )
  518. {
  519. rate = card->MaxSamplingRate / BLASTER_SamplePacketSize;
  520. }
  521. timeconstant = ( int )CalcTimeConstant( rate, BLASTER_SamplePacketSize );
  522. // Keep track of what the actual rate is
  523. BLASTER_SampleRate = ( unsigned )CalcSamplingRate( timeconstant );
  524. BLASTER_SampleRate /= BLASTER_SamplePacketSize;
  525. BLASTER_WriteDSP( DSP_SetTimeConstant );
  526. BLASTER_WriteDSP( timeconstant );
  527. }
  528. else
  529. {
  530. // Send literal sampling rate for cards with DSP version
  531. // 4.xx (Sound Blaster 16)
  532. BLASTER_SampleRate = rate;
  533. if ( BLASTER_SampleRate < card->MinSamplingRate )
  534. {
  535. BLASTER_SampleRate = card->MinSamplingRate;
  536. }
  537. if ( BLASTER_SampleRate > card->MaxSamplingRate )
  538. {
  539. BLASTER_SampleRate = card->MaxSamplingRate;
  540. }
  541. HiByte = hibyte( BLASTER_SampleRate );
  542. LoByte = lobyte( BLASTER_SampleRate );
  543. // Set playback rate
  544. BLASTER_WriteDSP( DSP_Set_DA_Rate );
  545. BLASTER_WriteDSP( HiByte );
  546. BLASTER_WriteDSP( LoByte );
  547. // Set recording rate
  548. BLASTER_WriteDSP( DSP_Set_AD_Rate );
  549. BLASTER_WriteDSP( HiByte );
  550. BLASTER_WriteDSP( LoByte );
  551. }
  552. }
  553. /*---------------------------------------------------------------------
  554. Function: BLASTER_GetPlaybackRate
  555. Returns the rate at which the digitized sound will be played in
  556. hertz.
  557. ---------------------------------------------------------------------*/
  558. unsigned BLASTER_GetPlaybackRate
  559. (
  560. void
  561. )
  562. {
  563. return( BLASTER_SampleRate );
  564. }
  565. /*---------------------------------------------------------------------
  566. Function: BLASTER_SetMixMode
  567. Sets the sound card to play samples in mono or stereo.
  568. ---------------------------------------------------------------------*/
  569. int BLASTER_SetMixMode
  570. (
  571. int mode
  572. )
  573. {
  574. int port;
  575. int data;
  576. int CardType;
  577. CardType = BLASTER_Config.Type;
  578. mode &= BLASTER_MaxMixMode;
  579. if ( !( BLASTER_CardConfig[ CardType ].MaxMixMode & STEREO ) )
  580. {
  581. mode &= ~STEREO;
  582. }
  583. if ( !( BLASTER_CardConfig[ CardType ].MaxMixMode & SIXTEEN_BIT ) )
  584. {
  585. mode &= ~SIXTEEN_BIT;
  586. }
  587. BLASTER_MixMode = mode;
  588. BLASTER_SamplePacketSize = BLASTER_SampleSize[ mode ];
  589. // For the Sound Blaster Pro, we have to set the mixer chip
  590. // to play mono or stereo samples.
  591. if ( ( CardType == SBPro ) || ( CardType == SBPro2 ) )
  592. {
  593. port = BLASTER_Config.Address + BLASTER_MixerAddressPort;
  594. outp( port, MIXER_SBProOutputSetting );
  595. port = BLASTER_Config.Address + BLASTER_MixerDataPort;
  596. // Get current mode
  597. data = inp( port );
  598. // set stereo mode bit
  599. if ( mode & STEREO )
  600. {
  601. data |= MIXER_SBProStereoFlag;
  602. }
  603. else
  604. {
  605. data &= ~MIXER_SBProStereoFlag;
  606. }
  607. // set the mode
  608. outp( port, data );
  609. BLASTER_SetPlaybackRate( BLASTER_SampleRate );
  610. }
  611. return( mode );
  612. }
  613. /*---------------------------------------------------------------------
  614. Function: BLASTER_StopPlayback
  615. Ends the DMA transfer of digitized sound to the sound card.
  616. ---------------------------------------------------------------------*/
  617. void BLASTER_StopPlayback
  618. (
  619. void
  620. )
  621. {
  622. int DmaChannel;
  623. // Don't allow anymore interrupts
  624. BLASTER_DisableInterrupt();
  625. if ( BLASTER_HaltTransferCommand == DSP_Reset )
  626. {
  627. BLASTER_ResetDSP();
  628. }
  629. else
  630. {
  631. BLASTER_WriteDSP( BLASTER_HaltTransferCommand );
  632. }
  633. // Disable the DMA channel
  634. if ( BLASTER_MixMode & SIXTEEN_BIT )
  635. {
  636. DmaChannel = BLASTER_Config.Dma16;
  637. }
  638. else
  639. {
  640. DmaChannel = BLASTER_Config.Dma8;
  641. }
  642. DMA_EndTransfer( DmaChannel );
  643. // Turn off speaker
  644. BLASTER_SpeakerOff();
  645. BLASTER_SoundPlaying = FALSE;
  646. BLASTER_SoundRecording = FALSE;
  647. BLASTER_DMABuffer = NULL;
  648. }
  649. /*---------------------------------------------------------------------
  650. Function: BLASTER_SetupDMABuffer
  651. Programs the DMAC for sound transfer.
  652. ---------------------------------------------------------------------*/
  653. int BLASTER_SetupDMABuffer
  654. (
  655. char *BufferPtr,
  656. int BufferSize,
  657. int mode
  658. )
  659. {
  660. int DmaChannel;
  661. int DmaStatus;
  662. int errorcode;
  663. if ( BLASTER_MixMode & SIXTEEN_BIT )
  664. {
  665. DmaChannel = BLASTER_Config.Dma16;
  666. errorcode = BLASTER_DMA16NotSet;
  667. }
  668. else
  669. {
  670. DmaChannel = BLASTER_Config.Dma8;
  671. errorcode = BLASTER_DMANotSet;
  672. }
  673. if ( DmaChannel == UNDEFINED )
  674. {
  675. BLASTER_SetErrorCode( errorcode );
  676. return( BLASTER_Error );
  677. }
  678. DmaStatus = DMA_SetupTransfer( DmaChannel, BufferPtr, BufferSize, mode );
  679. if ( DmaStatus == DMA_Error )
  680. {
  681. BLASTER_SetErrorCode( BLASTER_DmaError );
  682. return( BLASTER_Error );
  683. }
  684. BLASTER_DMAChannel = DmaChannel;
  685. BLASTER_DMABuffer = BufferPtr;
  686. BLASTER_CurrentDMABuffer = BufferPtr;
  687. BLASTER_TotalDMABufferSize = BufferSize;
  688. BLASTER_DMABufferEnd = BufferPtr + BufferSize;
  689. return( BLASTER_Ok );
  690. }
  691. /*---------------------------------------------------------------------
  692. Function: BLASTER_GetCurrentPos
  693. Returns the offset within the current sound being played.
  694. ---------------------------------------------------------------------*/
  695. int BLASTER_GetCurrentPos
  696. (
  697. void
  698. )
  699. {
  700. char *CurrentAddr;
  701. int DmaChannel;
  702. int offset;
  703. if ( !BLASTER_SoundPlaying )
  704. {
  705. BLASTER_SetErrorCode( BLASTER_NoSoundPlaying );
  706. return( BLASTER_Error );
  707. }
  708. if ( BLASTER_MixMode & SIXTEEN_BIT )
  709. {
  710. DmaChannel = BLASTER_Config.Dma16;
  711. }
  712. else
  713. {
  714. DmaChannel = BLASTER_Config.Dma8;
  715. }
  716. if ( DmaChannel == UNDEFINED )
  717. {
  718. BLASTER_SetErrorCode( BLASTER_DMANotSet );
  719. return( BLASTER_Error );
  720. }
  721. CurrentAddr = DMA_GetCurrentPos( DmaChannel );
  722. offset = ( int )( ( ( unsigned long )CurrentAddr ) -
  723. ( ( unsigned long )BLASTER_CurrentDMABuffer ) );
  724. if ( BLASTER_MixMode & SIXTEEN_BIT )
  725. {
  726. offset >>= 1;
  727. }
  728. if ( BLASTER_MixMode & STEREO )
  729. {
  730. offset >>= 1;
  731. }
  732. return( offset );
  733. }
  734. /*---------------------------------------------------------------------
  735. Function: BLASTER_DSP1xx_BeginPlayback
  736. Starts playback of digitized sound on cards compatible with DSP
  737. version 1.xx.
  738. ---------------------------------------------------------------------*/
  739. int BLASTER_DSP1xx_BeginPlayback
  740. (
  741. int length
  742. )
  743. {
  744. int SampleLength;
  745. int LoByte;
  746. int HiByte;
  747. SampleLength = length - 1;
  748. HiByte = hibyte( SampleLength );
  749. LoByte = lobyte( SampleLength );
  750. // Program DSP to play sound
  751. BLASTER_WriteDSP( DSP_Old8BitDAC );
  752. BLASTER_WriteDSP( LoByte );
  753. BLASTER_WriteDSP( HiByte );
  754. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  755. BLASTER_SoundPlaying = TRUE;
  756. return( BLASTER_Ok );
  757. }
  758. /*---------------------------------------------------------------------
  759. Function: BLASTER_DSP2xx_BeginPlayback
  760. Starts playback of digitized sound on cards compatible with DSP
  761. version 2.xx.
  762. ---------------------------------------------------------------------*/
  763. int BLASTER_DSP2xx_BeginPlayback
  764. (
  765. int length
  766. )
  767. {
  768. int SampleLength;
  769. int LoByte;
  770. int HiByte;
  771. SampleLength = length - 1;
  772. HiByte = hibyte( SampleLength );
  773. LoByte = lobyte( SampleLength );
  774. BLASTER_WriteDSP( DSP_SetBlockLength );
  775. BLASTER_WriteDSP( LoByte );
  776. BLASTER_WriteDSP( HiByte );
  777. if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
  778. ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
  779. {
  780. BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitMode );
  781. BLASTER_HaltTransferCommand = DSP_Reset;
  782. }
  783. else
  784. {
  785. BLASTER_WriteDSP( DSP_8BitAutoInitMode );
  786. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  787. }
  788. BLASTER_SoundPlaying = TRUE;
  789. return( BLASTER_Ok );
  790. }
  791. /*---------------------------------------------------------------------
  792. Function: BLASTER_DSP4xx_BeginPlayback
  793. Starts playback of digitized sound on cards compatible with DSP
  794. version 4.xx, such as the Sound Blaster 16.
  795. ---------------------------------------------------------------------*/
  796. int BLASTER_DSP4xx_BeginPlayback
  797. (
  798. int length
  799. )
  800. {
  801. int TransferCommand;
  802. int TransferMode;
  803. int SampleLength;
  804. int LoByte;
  805. int HiByte;
  806. if ( BLASTER_MixMode & SIXTEEN_BIT )
  807. {
  808. TransferCommand = DSP_16BitDAC;
  809. SampleLength = ( length / 2 ) - 1;
  810. BLASTER_HaltTransferCommand = DSP_Halt16bitTransfer;
  811. if ( BLASTER_MixMode & STEREO )
  812. {
  813. TransferMode = DSP_SignedStereoData;
  814. }
  815. else
  816. {
  817. TransferMode = DSP_SignedMonoData;
  818. }
  819. }
  820. else
  821. {
  822. TransferCommand = DSP_8BitDAC;
  823. SampleLength = length - 1;
  824. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  825. if ( BLASTER_MixMode & STEREO )
  826. {
  827. TransferMode = DSP_UnsignedStereoData;
  828. }
  829. else
  830. {
  831. TransferMode = DSP_UnsignedMonoData;
  832. }
  833. }
  834. HiByte = hibyte( SampleLength );
  835. LoByte = lobyte( SampleLength );
  836. // Program DSP to play sound
  837. BLASTER_WriteDSP( TransferCommand );
  838. BLASTER_WriteDSP( TransferMode );
  839. BLASTER_WriteDSP( LoByte );
  840. BLASTER_WriteDSP( HiByte );
  841. BLASTER_SoundPlaying = TRUE;
  842. return( BLASTER_Ok );
  843. }
  844. /*---------------------------------------------------------------------
  845. Function: BLASTER_BeginBufferedPlayback
  846. Begins multibuffered playback of digitized sound on the sound card.
  847. ---------------------------------------------------------------------*/
  848. int BLASTER_BeginBufferedPlayback
  849. (
  850. char *BufferStart,
  851. int BufferSize,
  852. int NumDivisions,
  853. unsigned SampleRate,
  854. int MixMode,
  855. void ( *CallBackFunc )( void )
  856. )
  857. {
  858. int DmaStatus;
  859. int TransferLength;
  860. //JIM
  861. // if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
  862. {
  863. BLASTER_StopPlayback();
  864. }
  865. BLASTER_SetMixMode( MixMode );
  866. DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitRead );
  867. if ( DmaStatus == BLASTER_Error )
  868. {
  869. return( BLASTER_Error );
  870. }
  871. BLASTER_SetPlaybackRate( SampleRate );
  872. BLASTER_SetCallBack( CallBackFunc );
  873. BLASTER_EnableInterrupt();
  874. // Turn on speaker
  875. BLASTER_SpeakerOn();
  876. TransferLength = BufferSize / NumDivisions;
  877. BLASTER_TransferLength = TransferLength;
  878. // Program the sound card to start the transfer.
  879. if ( BLASTER_Version < DSP_Version2xx )
  880. {
  881. BLASTER_DSP1xx_BeginPlayback( TransferLength );
  882. }
  883. else if ( BLASTER_Version < DSP_Version4xx )
  884. {
  885. BLASTER_DSP2xx_BeginPlayback( TransferLength );
  886. }
  887. else
  888. {
  889. BLASTER_DSP4xx_BeginPlayback( TransferLength );
  890. }
  891. return( BLASTER_Ok );
  892. }
  893. /*---------------------------------------------------------------------
  894. Function: BLASTER_DSP4xx_BeginRecord
  895. Starts recording of digitized sound on cards compatible with DSP
  896. version 4.xx, such as the Sound Blaster 16.
  897. ---------------------------------------------------------------------*/
  898. int BLASTER_DSP4xx_BeginRecord
  899. (
  900. int length
  901. )
  902. {
  903. int TransferCommand;
  904. int TransferMode;
  905. int SampleLength;
  906. int LoByte;
  907. int HiByte;
  908. TransferCommand = DSP_8BitADC;
  909. SampleLength = length - 1;
  910. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  911. TransferMode = DSP_UnsignedMonoData;
  912. HiByte = hibyte( SampleLength );
  913. LoByte = lobyte( SampleLength );
  914. // Program DSP to play sound
  915. BLASTER_WriteDSP( TransferCommand );
  916. BLASTER_WriteDSP( TransferMode );
  917. BLASTER_WriteDSP( LoByte );
  918. BLASTER_WriteDSP( HiByte );
  919. BLASTER_SoundRecording = TRUE;
  920. return( BLASTER_Ok );
  921. }
  922. /*---------------------------------------------------------------------
  923. Function: BLASTER_DSP2xx_BeginRecord
  924. Starts recording of digitized sound on cards compatible with DSP
  925. version 2.xx.
  926. ---------------------------------------------------------------------*/
  927. int BLASTER_DSP2xx_BeginRecord
  928. (
  929. int length
  930. )
  931. {
  932. int SampleLength;
  933. int LoByte;
  934. int HiByte;
  935. SampleLength = length - 1;
  936. HiByte = hibyte( SampleLength );
  937. LoByte = lobyte( SampleLength );
  938. BLASTER_WriteDSP( DSP_SetBlockLength );
  939. BLASTER_WriteDSP( LoByte );
  940. BLASTER_WriteDSP( HiByte );
  941. if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
  942. ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
  943. {
  944. BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitRecord );
  945. BLASTER_HaltTransferCommand = DSP_Reset;
  946. }
  947. else
  948. {
  949. BLASTER_WriteDSP( DSP_8BitAutoInitRecord );
  950. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  951. }
  952. BLASTER_SoundRecording = TRUE;
  953. return( BLASTER_Ok );
  954. }
  955. /*---------------------------------------------------------------------
  956. Function: BLASTER_DSP1xx_BeginRecord
  957. Starts recording of digitized sound on cards compatible with DSP
  958. version 1.xx.
  959. ---------------------------------------------------------------------*/
  960. int BLASTER_DSP1xx_BeginRecord
  961. (
  962. int length
  963. )
  964. {
  965. int SampleLength;
  966. int LoByte;
  967. int HiByte;
  968. SampleLength = length - 1;
  969. HiByte = hibyte( SampleLength );
  970. LoByte = lobyte( SampleLength );
  971. // Program DSP to play sound
  972. BLASTER_WriteDSP( DSP_Old8BitADC );
  973. BLASTER_WriteDSP( LoByte );
  974. BLASTER_WriteDSP( HiByte );
  975. BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
  976. BLASTER_SoundRecording = TRUE;
  977. return( BLASTER_Ok );
  978. }
  979. /*---------------------------------------------------------------------
  980. Function: BLASTER_BeginBufferedRecord
  981. Begins multibuffered recording of digitized sound on the sound card.
  982. ---------------------------------------------------------------------*/
  983. int BLASTER_BeginBufferedRecord
  984. (
  985. char *BufferStart,
  986. int BufferSize,
  987. int NumDivisions,
  988. unsigned SampleRate,
  989. int MixMode,
  990. void ( *CallBackFunc )( void )
  991. )
  992. {
  993. int DmaStatus;
  994. int TransferLength;
  995. //JIM
  996. // if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
  997. {
  998. BLASTER_StopPlayback();
  999. }
  1000. BLASTER_SetMixMode( MixMode );
  1001. DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitWrite );
  1002. if ( DmaStatus == BLASTER_Error )
  1003. {
  1004. return( BLASTER_Error );
  1005. }
  1006. BLASTER_SetPlaybackRate( SampleRate );
  1007. BLASTER_SetCallBack( CallBackFunc );
  1008. BLASTER_EnableInterrupt();
  1009. // Turn off speaker
  1010. BLASTER_SpeakerOff();
  1011. TransferLength = BufferSize / NumDivisions;
  1012. BLASTER_TransferLength = TransferLength;
  1013. // Program the sound card to start the transfer.
  1014. if ( BLASTER_Version < DSP_Version2xx )
  1015. {
  1016. BLASTER_DSP1xx_BeginRecord( TransferLength );
  1017. }
  1018. else if ( BLASTER_Version < DSP_Version4xx )
  1019. {
  1020. BLASTER_DSP2xx_BeginRecord( TransferLength );
  1021. }
  1022. else
  1023. {
  1024. BLASTER_DSP4xx_BeginRecord( TransferLength );
  1025. }
  1026. return( BLASTER_Ok );
  1027. }
  1028. /*---------------------------------------------------------------------
  1029. Function: BLASTER_WriteMixer
  1030. Writes a byte of data to the Sound Blaster's mixer chip.
  1031. ---------------------------------------------------------------------*/
  1032. void BLASTER_WriteMixer
  1033. (
  1034. int reg,
  1035. int data
  1036. )
  1037. {
  1038. outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
  1039. outp( BLASTER_MixerAddress + BLASTER_MixerDataPort, data );
  1040. }
  1041. /*---------------------------------------------------------------------
  1042. Function: BLASTER_ReadMixer
  1043. Reads a byte of data from the Sound Blaster's mixer chip.
  1044. ---------------------------------------------------------------------*/
  1045. int BLASTER_ReadMixer
  1046. (
  1047. int reg
  1048. )
  1049. {
  1050. int data;
  1051. outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
  1052. data = inp( BLASTER_MixerAddress + BLASTER_MixerDataPort );
  1053. return( data );
  1054. }
  1055. /*---------------------------------------------------------------------
  1056. Function: BLASTER_GetVoiceVolume
  1057. Reads the average volume of the digitized sound channel from the
  1058. Sound Blaster's mixer chip.
  1059. ---------------------------------------------------------------------*/
  1060. int BLASTER_GetVoiceVolume
  1061. (
  1062. void
  1063. )
  1064. {
  1065. int volume;
  1066. int left;
  1067. int right;
  1068. switch( BLASTER_MixerType )
  1069. {
  1070. case SBPro :
  1071. case SBPro2 :
  1072. left = BLASTER_ReadMixer( MIXER_SBProVoice );
  1073. right = ( left & 0x0f ) << 4;
  1074. left &= 0xf0;
  1075. volume = ( left + right ) / 2;
  1076. break;
  1077. case SB16 :
  1078. left = BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
  1079. right = BLASTER_ReadMixer( MIXER_SB16VoiceRight );
  1080. volume = ( left + right ) / 2;
  1081. break;
  1082. default :
  1083. BLASTER_SetErrorCode( BLASTER_NoMixer );
  1084. volume = BLASTER_Error;
  1085. }
  1086. return( volume );
  1087. }
  1088. /*---------------------------------------------------------------------
  1089. Function: BLASTER_SetVoiceVolume
  1090. Sets the volume of the digitized sound channel on the Sound
  1091. Blaster's mixer chip.
  1092. ---------------------------------------------------------------------*/
  1093. int BLASTER_SetVoiceVolume
  1094. (
  1095. int volume
  1096. )
  1097. {
  1098. int data;
  1099. int status;
  1100. volume = min( 255, volume );
  1101. volume = max( 0, volume );
  1102. status = BLASTER_Ok;
  1103. switch( BLASTER_MixerType )
  1104. {
  1105. case SBPro :
  1106. case SBPro2 :
  1107. data = ( volume & 0xf0 ) + ( volume >> 4 );
  1108. BLASTER_WriteMixer( MIXER_SBProVoice, data );
  1109. break;
  1110. case SB16 :
  1111. BLASTER_WriteMixer( MIXER_SB16VoiceLeft, volume & 0xf8 );
  1112. BLASTER_WriteMixer( MIXER_SB16VoiceRight, volume & 0xf8 );
  1113. break;
  1114. default :
  1115. BLASTER_SetErrorCode( BLASTER_NoMixer );
  1116. status = BLASTER_Error;
  1117. }
  1118. return( status );
  1119. }
  1120. /*---------------------------------------------------------------------
  1121. Function: BLASTER_GetMidiVolume
  1122. Reads the average volume of the Midi sound channel from the
  1123. Sound Blaster's mixer chip.
  1124. ---------------------------------------------------------------------*/
  1125. int BLASTER_GetMidiVolume
  1126. (
  1127. void
  1128. )
  1129. {
  1130. int volume;
  1131. int left;
  1132. int right;
  1133. switch( BLASTER_MixerType )
  1134. {
  1135. case SBPro :
  1136. case SBPro2 :
  1137. left = BLASTER_ReadMixer( MIXER_SBProMidi );
  1138. right = ( left & 0x0f ) << 4;
  1139. left &= 0xf0;
  1140. volume = ( left + right ) / 2;
  1141. break;
  1142. case SB16 :
  1143. left = BLASTER_ReadMixer( MIXER_SB16MidiLeft );
  1144. right = BLASTER_ReadMixer( MIXER_SB16MidiRight );
  1145. volume = ( left + right ) / 2;
  1146. break;
  1147. default :
  1148. BLASTER_SetErrorCode( BLASTER_NoMixer );
  1149. volume = BLASTER_Error;
  1150. }
  1151. return( volume );
  1152. }
  1153. /*---------------------------------------------------------------------
  1154. Function: BLASTER_SetMidiVolume
  1155. Sets the volume of the Midi sound channel on the Sound
  1156. Blaster's mixer chip.
  1157. ---------------------------------------------------------------------*/
  1158. int BLASTER_SetMidiVolume
  1159. (
  1160. int volume
  1161. )
  1162. {
  1163. int data;
  1164. int status;
  1165. volume = min( 255, volume );
  1166. volume = max( 0, volume );
  1167. status = BLASTER_Ok;
  1168. switch( BLASTER_MixerType )
  1169. {
  1170. case SBPro :
  1171. case SBPro2 :
  1172. data = ( volume & 0xf0 ) + ( volume >> 4 );
  1173. BLASTER_WriteMixer( MIXER_SBProMidi, data );
  1174. break;
  1175. case SB16 :
  1176. BLASTER_WriteMixer( MIXER_SB16MidiLeft, volume & 0xf8 );
  1177. BLASTER_WriteMixer( MIXER_SB16MidiRight, volume & 0xf8 );
  1178. break;
  1179. default :
  1180. BLASTER_SetErrorCode( BLASTER_NoMixer );
  1181. status = BLASTER_Error;
  1182. }
  1183. return( status );
  1184. }
  1185. /*---------------------------------------------------------------------
  1186. Function: BLASTER_CardHasMixer
  1187. Checks if the selected Sound Blaster card has a mixer.
  1188. ---------------------------------------------------------------------*/
  1189. int BLASTER_CardHasMixer
  1190. (
  1191. void
  1192. )
  1193. {
  1194. BLASTER_CONFIG Blaster;
  1195. int status;
  1196. if ( BLASTER_MixerAddress == UNDEFINED )
  1197. {
  1198. status = BLASTER_GetEnv( &Blaster );
  1199. if ( status == BLASTER_Ok )
  1200. {
  1201. BLASTER_MixerAddress = Blaster.Address;
  1202. BLASTER_MixerType = 0;
  1203. if ( ( Blaster.Type < BLASTER_MinCardType ) ||
  1204. ( Blaster.Type > BLASTER_MaxCardType ) )
  1205. {
  1206. BLASTER_MixerType = Blaster.Type;
  1207. }
  1208. }
  1209. }
  1210. if ( BLASTER_MixerAddress != UNDEFINED )
  1211. {
  1212. return( BLASTER_CardConfig[ BLASTER_MixerType ].HasMixer );
  1213. }
  1214. return( FALSE );
  1215. }
  1216. /*---------------------------------------------------------------------
  1217. Function: BLASTER_SaveVoiceVolume
  1218. Saves the user's voice mixer settings.
  1219. ---------------------------------------------------------------------*/
  1220. void BLASTER_SaveVoiceVolume
  1221. (
  1222. void
  1223. )
  1224. {
  1225. if ( BLASTER_CardHasMixer() )
  1226. {
  1227. switch( BLASTER_MixerType )
  1228. {
  1229. case SBPro :
  1230. case SBPro2 :
  1231. BLASTER_OriginalVoiceVolumeLeft =
  1232. BLASTER_ReadMixer( MIXER_SBProVoice );
  1233. break;
  1234. case SB16 :
  1235. BLASTER_OriginalVoiceVolumeLeft =
  1236. BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
  1237. BLASTER_OriginalVoiceVolumeRight =
  1238. BLASTER_ReadMixer( MIXER_SB16VoiceRight );
  1239. break;
  1240. }
  1241. }
  1242. }
  1243. /*---------------------------------------------------------------------
  1244. Function: BLASTER_RestoreVoiceVolume
  1245. Restores the user's voice mixer settings.
  1246. ---------------------------------------------------------------------*/
  1247. void BLASTER_RestoreVoiceVolume
  1248. (
  1249. void
  1250. )
  1251. {
  1252. if ( BLASTER_CardHasMixer() )
  1253. {
  1254. switch( BLASTER_MixerType )
  1255. {
  1256. case SBPro :
  1257. case SBPro2 :
  1258. BLASTER_WriteMixer( MIXER_SBProVoice,
  1259. BLASTER_OriginalVoiceVolumeLeft );
  1260. break;
  1261. case SB16 :
  1262. BLASTER_WriteMixer( MIXER_SB16VoiceLeft,
  1263. BLASTER_OriginalVoiceVolumeLeft );
  1264. BLASTER_WriteMixer( MIXER_SB16VoiceRight,
  1265. BLASTER_OriginalVoiceVolumeRight );
  1266. break;
  1267. }
  1268. }
  1269. }
  1270. /*---------------------------------------------------------------------
  1271. Function: BLASTER_SaveMidiVolume
  1272. Saves the user's FM mixer settings.
  1273. ---------------------------------------------------------------------*/
  1274. void BLASTER_SaveMidiVolume
  1275. (
  1276. void
  1277. )
  1278. {
  1279. if ( BLASTER_CardHasMixer() )
  1280. {
  1281. switch( BLASTER_MixerType )
  1282. {
  1283. case SBPro :
  1284. case SBPro2 :
  1285. BLASTER_OriginalMidiVolumeLeft =
  1286. BLASTER_ReadMixer( MIXER_SBProMidi );
  1287. break;
  1288. case SB16 :
  1289. BLASTER_OriginalMidiVolumeLeft =
  1290. BLASTER_ReadMixer( MIXER_SB16MidiLeft );
  1291. BLASTER_OriginalMidiVolumeRight =
  1292. BLASTER_ReadMixer( MIXER_SB16MidiRight );
  1293. break;
  1294. }
  1295. }
  1296. }
  1297. /*---------------------------------------------------------------------
  1298. Function: BLASTER_RestoreMidiVolume
  1299. Restores the user's FM mixer settings.
  1300. ---------------------------------------------------------------------*/
  1301. void BLASTER_RestoreMidiVolume
  1302. (
  1303. void
  1304. )
  1305. {
  1306. if ( BLASTER_CardHasMixer() )
  1307. {
  1308. switch( BLASTER_MixerType )
  1309. {
  1310. case SBPro :
  1311. case SBPro2 :
  1312. BLASTER_WriteMixer( MIXER_SBProMidi,
  1313. BLASTER_OriginalMidiVolumeLeft );
  1314. break;
  1315. case SB16 :
  1316. BLASTER_WriteMixer( MIXER_SB16MidiLeft,
  1317. BLASTER_OriginalMidiVolumeLeft );
  1318. BLASTER_WriteMixer( MIXER_SB16MidiRight,
  1319. BLASTER_OriginalMidiVolumeRight );
  1320. break;
  1321. }
  1322. }
  1323. }
  1324. /*---------------------------------------------------------------------
  1325. Function: BLASTER_GetEnv
  1326. Retrieves the BLASTER environment settings and returns them to
  1327. the caller.
  1328. ---------------------------------------------------------------------*/
  1329. int BLASTER_GetEnv
  1330. (
  1331. BLASTER_CONFIG *Config
  1332. )
  1333. {
  1334. char *Blaster;
  1335. char parameter;
  1336. int status;
  1337. int errorcode;
  1338. Config->Address = UNDEFINED;
  1339. Config->Type = UNDEFINED;
  1340. Config->Interrupt = UNDEFINED;
  1341. Config->Dma8 = UNDEFINED;
  1342. Config->Dma16 = UNDEFINED;
  1343. Config->Midi = UNDEFINED;
  1344. Config->Emu = UNDEFINED;
  1345. Blaster = getenv( "BLASTER" );
  1346. if ( Blaster == NULL )
  1347. {
  1348. BLASTER_SetErrorCode( BLASTER_EnvNotFound );
  1349. return( BLASTER_Error );
  1350. }
  1351. while( *Blaster != 0 )
  1352. {
  1353. if ( *Blaster == ' ' )
  1354. {
  1355. Blaster++;
  1356. continue;
  1357. }
  1358. parameter = toupper( *Blaster );
  1359. Blaster++;
  1360. if ( !isxdigit( *Blaster ) )
  1361. {
  1362. BLASTER_SetErrorCode( BLASTER_InvalidParameter );
  1363. return( BLASTER_Error );
  1364. }
  1365. switch( parameter )
  1366. {
  1367. case BlasterEnv_Address :
  1368. sscanf( Blaster, "%x", &Config->Address );
  1369. break;
  1370. case BlasterEnv_Interrupt :
  1371. sscanf( Blaster, "%d", &Config->Interrupt );
  1372. break;
  1373. case BlasterEnv_8bitDma :
  1374. sscanf( Blaster, "%d", &Config->Dma8 );
  1375. break;
  1376. case BlasterEnv_Type :
  1377. sscanf( Blaster, "%d", &Config->Type );
  1378. break;
  1379. case BlasterEnv_16bitDma :
  1380. sscanf( Blaster, "%d", &Config->Dma16 );
  1381. break;
  1382. case BlasterEnv_Midi :
  1383. sscanf( Blaster, "%x", &Config->Midi );
  1384. break;
  1385. case BlasterEnv_EmuAddress :
  1386. sscanf( Blaster, "%x", &Config->Emu );
  1387. break;
  1388. default :
  1389. // Skip the offending data
  1390. // sscanf( Blaster, "%*s" );
  1391. break;
  1392. }
  1393. while( isxdigit( *Blaster ) )
  1394. {
  1395. Blaster++;
  1396. }
  1397. }
  1398. status = BLASTER_Ok;
  1399. errorcode = BLASTER_Ok;
  1400. if ( Config->Type == UNDEFINED )
  1401. {
  1402. errorcode = BLASTER_CardTypeNotSet;
  1403. }
  1404. else if ( ( Config->Type < BLASTER_MinCardType ) ||
  1405. ( Config->Type > BLASTER_MaxCardType ) ||
  1406. ( !BLASTER_CardConfig[ Config->Type ].IsSupported ) )
  1407. {
  1408. errorcode = BLASTER_UnsupportedCardType;
  1409. }
  1410. if ( Config->Dma8 == UNDEFINED )
  1411. {
  1412. errorcode = BLASTER_DMANotSet;
  1413. }
  1414. if ( Config->Interrupt == UNDEFINED )
  1415. {
  1416. errorcode = BLASTER_IntNotSet;
  1417. }
  1418. if ( Config->Address == UNDEFINED )
  1419. {
  1420. errorcode = BLASTER_AddrNotSet;
  1421. }
  1422. if ( errorcode != BLASTER_Ok )
  1423. {
  1424. status = BLASTER_Error;
  1425. BLASTER_SetErrorCode( errorcode );
  1426. }
  1427. return( status );
  1428. }
  1429. /*---------------------------------------------------------------------
  1430. Function: BLASTER_SetCardSettings
  1431. Sets up the sound card's parameters.
  1432. ---------------------------------------------------------------------*/
  1433. int BLASTER_SetCardSettings
  1434. (
  1435. BLASTER_CONFIG Config
  1436. )
  1437. {
  1438. if ( BLASTER_Installed )
  1439. {
  1440. BLASTER_Shutdown();
  1441. }
  1442. if ( ( Config.Type < BLASTER_MinCardType ) ||
  1443. ( Config.Type > BLASTER_MaxCardType ) ||
  1444. ( !BLASTER_CardConfig[ Config.Type ].IsSupported ) )
  1445. {
  1446. BLASTER_SetErrorCode( BLASTER_UnsupportedCardType );
  1447. return( BLASTER_Error );
  1448. }
  1449. BLASTER_Config.Address = Config.Address;
  1450. BLASTER_Config.Type = Config.Type;
  1451. BLASTER_Config.Interrupt = Config.Interrupt;
  1452. BLASTER_Config.Dma8 = Config.Dma8;
  1453. BLASTER_Config.Dma16 = Config.Dma16;
  1454. BLASTER_Config.Midi = Config.Midi;
  1455. BLASTER_Config.Emu = Config.Emu;
  1456. BLASTER_MixerAddress = Config.Address;
  1457. BLASTER_MixerType = 0;
  1458. BLASTER_MixerType = Config.Type;
  1459. return( BLASTER_Ok );
  1460. }
  1461. /*---------------------------------------------------------------------
  1462. Function: BLASTER_GetCardSettings
  1463. Sets up the sound card's parameters.
  1464. ---------------------------------------------------------------------*/
  1465. int BLASTER_GetCardSettings
  1466. (
  1467. BLASTER_CONFIG *Config
  1468. )
  1469. {
  1470. if ( BLASTER_Config.Address == UNDEFINED )
  1471. {
  1472. return( BLASTER_Warning );
  1473. }
  1474. else
  1475. {
  1476. Config->Address = BLASTER_Config.Address;
  1477. Config->Type = BLASTER_Config.Type;
  1478. Config->Interrupt = BLASTER_Config.Interrupt;
  1479. Config->Dma8 = BLASTER_Config.Dma8;
  1480. Config->Dma16 = BLASTER_Config.Dma16;
  1481. Config->Midi = BLASTER_Config.Midi;
  1482. Config->Emu = BLASTER_Config.Emu;
  1483. }
  1484. return( BLASTER_Ok );
  1485. }
  1486. /*---------------------------------------------------------------------
  1487. Function: BLASTER_GetCardInfo
  1488. Returns the maximum number of bits that can represent a sample
  1489. (8 or 16) and the number of channels (1 for mono, 2 for stereo).
  1490. ---------------------------------------------------------------------*/
  1491. int BLASTER_GetCardInfo
  1492. (
  1493. int *MaxSampleBits,
  1494. int *MaxChannels
  1495. )
  1496. {
  1497. int CardType;
  1498. CardType = BLASTER_Config.Type;
  1499. if ( CardType == UNDEFINED )
  1500. {
  1501. BLASTER_SetErrorCode( BLASTER_CardTypeNotSet );
  1502. return( BLASTER_Error );
  1503. }
  1504. if ( BLASTER_CardConfig[ CardType ].MaxMixMode & STEREO )
  1505. {
  1506. *MaxChannels = 2;
  1507. }
  1508. else
  1509. {
  1510. *MaxChannels = 1;
  1511. }
  1512. if ( BLASTER_CardConfig[ CardType ].MaxMixMode & SIXTEEN_BIT )
  1513. {
  1514. *MaxSampleBits = 16;
  1515. }
  1516. else
  1517. {
  1518. *MaxSampleBits = 8;
  1519. }
  1520. return( BLASTER_Ok );
  1521. }
  1522. /*---------------------------------------------------------------------
  1523. Function: BLASTER_SetCallBack
  1524. Specifies the user function to call at the end of a sound transfer.
  1525. ---------------------------------------------------------------------*/
  1526. void BLASTER_SetCallBack
  1527. (
  1528. void ( *func )( void )
  1529. )
  1530. {
  1531. BLASTER_CallBack = func;
  1532. }
  1533. /*---------------------------------------------------------------------
  1534. Function: BLASTER_LockEnd
  1535. Used for determining the length of the functions to lock in memory.
  1536. ---------------------------------------------------------------------*/
  1537. static void BLASTER_LockEnd
  1538. (
  1539. void
  1540. )
  1541. {
  1542. }
  1543. /*---------------------------------------------------------------------
  1544. Function: BLASTER_UnlockMemory
  1545. Unlocks all neccessary data.
  1546. ---------------------------------------------------------------------*/
  1547. void BLASTER_UnlockMemory
  1548. (
  1549. void
  1550. )
  1551. {
  1552. DPMI_UnlockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
  1553. DPMI_Unlock( BLASTER_Interrupts );
  1554. DPMI_Unlock( BLASTER_SampleSize );
  1555. DPMI_Unlock( BLASTER_CardConfig );
  1556. DPMI_Unlock( BLASTER_OldInt );
  1557. DPMI_Unlock( BLASTER_Config );
  1558. DPMI_Unlock( BLASTER_Installed );
  1559. DPMI_Unlock( BLASTER_Version );
  1560. DPMI_Unlock( BLASTER_DMABuffer );
  1561. DPMI_Unlock( BLASTER_DMABufferEnd );
  1562. DPMI_Unlock( BLASTER_CurrentDMABuffer );
  1563. DPMI_Unlock( BLASTER_TotalDMABufferSize );
  1564. DPMI_Unlock( BLASTER_TransferLength );
  1565. DPMI_Unlock( BLASTER_MixMode );
  1566. DPMI_Unlock( BLASTER_SamplePacketSize );
  1567. DPMI_Unlock( BLASTER_SampleRate );
  1568. DPMI_Unlock( BLASTER_HaltTransferCommand );
  1569. DPMI_Unlock( BLASTER_SoundPlaying );
  1570. DPMI_Unlock( BLASTER_SoundRecording );
  1571. DPMI_Unlock( BLASTER_CallBack );
  1572. DPMI_Unlock( BLASTER_IntController1Mask );
  1573. DPMI_Unlock( BLASTER_IntController2Mask );
  1574. DPMI_Unlock( BLASTER_MixerAddress );
  1575. DPMI_Unlock( BLASTER_MixerType );
  1576. DPMI_Unlock( BLASTER_OriginalMidiVolumeLeft );
  1577. DPMI_Unlock( BLASTER_OriginalMidiVolumeRight );
  1578. DPMI_Unlock( BLASTER_OriginalVoiceVolumeLeft );
  1579. DPMI_Unlock( BLASTER_OriginalVoiceVolumeRight );
  1580. DPMI_Unlock( GlobalStatus );
  1581. }
  1582. /*---------------------------------------------------------------------
  1583. Function: BLASTER_LockMemory
  1584. Locks all neccessary data.
  1585. ---------------------------------------------------------------------*/
  1586. int BLASTER_LockMemory
  1587. (
  1588. void
  1589. )
  1590. {
  1591. int status;
  1592. status = DPMI_LockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
  1593. status |= DPMI_Lock( BLASTER_Interrupts );
  1594. status |= DPMI_Lock( BLASTER_SampleSize );
  1595. status |= DPMI_Lock( BLASTER_CardConfig );
  1596. status |= DPMI_Lock( BLASTER_OldInt );
  1597. status |= DPMI_Lock( BLASTER_Config );
  1598. status |= DPMI_Lock( BLASTER_Installed );
  1599. status |= DPMI_Lock( BLASTER_Version );
  1600. status |= DPMI_Lock( BLASTER_DMABuffer );
  1601. status |= DPMI_Lock( BLASTER_DMABufferEnd );
  1602. status |= DPMI_Lock( BLASTER_CurrentDMABuffer );
  1603. status |= DPMI_Lock( BLASTER_TotalDMABufferSize );
  1604. status |= DPMI_Lock( BLASTER_TransferLength );
  1605. status |= DPMI_Lock( BLASTER_MixMode );
  1606. status |= DPMI_Lock( BLASTER_SamplePacketSize );
  1607. status |= DPMI_Lock( BLASTER_SampleRate );
  1608. status |= DPMI_Lock( BLASTER_HaltTransferCommand );
  1609. status |= DPMI_Lock( BLASTER_SoundPlaying );
  1610. status |= DPMI_Lock( BLASTER_SoundRecording );
  1611. status |= DPMI_Lock( BLASTER_CallBack );
  1612. status |= DPMI_Lock( BLASTER_IntController1Mask );
  1613. status |= DPMI_Lock( BLASTER_IntController2Mask );
  1614. status |= DPMI_Lock( BLASTER_MixerAddress );
  1615. status |= DPMI_Lock( BLASTER_MixerType );
  1616. status |= DPMI_Lock( BLASTER_OriginalMidiVolumeLeft );
  1617. status |= DPMI_Lock( BLASTER_OriginalMidiVolumeRight );
  1618. status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeLeft );
  1619. status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeRight );
  1620. status |= DPMI_Lock( GlobalStatus );
  1621. if ( status != DPMI_Ok )
  1622. {
  1623. BLASTER_UnlockMemory();
  1624. BLASTER_SetErrorCode( BLASTER_DPMI_Error );
  1625. return( BLASTER_Error );
  1626. }
  1627. return( BLASTER_Ok );
  1628. }
  1629. /*---------------------------------------------------------------------
  1630. Function: allocateTimerStack
  1631. Allocate a block of memory from conventional (low) memory and return
  1632. the selector (which can go directly into a segment register) of the
  1633. memory block or 0 if an error occured.
  1634. ---------------------------------------------------------------------*/
  1635. static unsigned short allocateTimerStack
  1636. (
  1637. unsigned short size
  1638. )
  1639. {
  1640. union REGS regs;
  1641. // clear all registers
  1642. memset( &regs, 0, sizeof( regs ) );
  1643. // DPMI allocate conventional memory
  1644. regs.w.ax = 0x100;
  1645. // size in paragraphs
  1646. regs.w.bx = ( size + 15 ) / 16;
  1647. int386( 0x31, &regs, &regs );
  1648. if (!regs.w.cflag)
  1649. {
  1650. // DPMI call returns selector in dx
  1651. // (ax contains real mode segment
  1652. // which is ignored here)
  1653. return( regs.w.dx );
  1654. }
  1655. // Couldn't allocate memory.
  1656. return( NULL );
  1657. }
  1658. /*---------------------------------------------------------------------
  1659. Function: deallocateTimerStack
  1660. Deallocate a block of conventional (low) memory given a selector to
  1661. it. Assumes the block was allocated with DPMI function 0x100.
  1662. ---------------------------------------------------------------------*/
  1663. static void deallocateTimerStack
  1664. (
  1665. unsigned short selector
  1666. )
  1667. {
  1668. union REGS regs;
  1669. if ( selector != NULL )
  1670. {
  1671. // clear all registers
  1672. memset( &regs, 0, sizeof( regs ) );
  1673. regs.w.ax = 0x101;
  1674. regs.w.dx = selector;
  1675. int386( 0x31, &regs, &regs );
  1676. }
  1677. }
  1678. /*---------------------------------------------------------------------
  1679. Function: BLASTER_SetupWaveBlaster
  1680. Allows the WaveBlaster to play music while the Sound Blaster 16
  1681. plays digital sound.
  1682. ---------------------------------------------------------------------*/
  1683. int BLASTER_SetupWaveBlaster
  1684. (
  1685. int address
  1686. )
  1687. {
  1688. BLASTER_CONFIG Blaster;
  1689. int status;
  1690. if ( address != UNDEFINED )
  1691. {
  1692. BLASTER_WaveBlasterPort = address;
  1693. }
  1694. else
  1695. {
  1696. if ( BLASTER_Config.Midi == UNDEFINED )
  1697. {
  1698. status = BLASTER_GetEnv( &Blaster );
  1699. if ( status == BLASTER_Ok )
  1700. {
  1701. if ( Blaster.Midi == UNDEFINED )
  1702. {
  1703. BLASTER_SetErrorCode( BLASTER_MIDINotSet );
  1704. return( BLASTER_Error );
  1705. }
  1706. BLASTER_WaveBlasterPort = Blaster.Midi;
  1707. }
  1708. else
  1709. {
  1710. return( status );
  1711. }
  1712. }
  1713. }
  1714. if ( BLASTER_CardHasMixer() )
  1715. {
  1716. // Disable MPU401 interrupts. If they are not disabled,
  1717. // the SB16 will not produce sound or music.
  1718. BLASTER_WaveBlasterState = BLASTER_ReadMixer( MIXER_DSP4xxISR_Enable );
  1719. BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, MIXER_DisableMPU401Interrupts );
  1720. }
  1721. return( BLASTER_WaveBlasterPort );
  1722. }
  1723. /*---------------------------------------------------------------------
  1724. Function: BLASTER_ShutdownWaveBlaster
  1725. Restores WaveBlaster mixer to original state.
  1726. ---------------------------------------------------------------------*/
  1727. void BLASTER_ShutdownWaveBlaster
  1728. (
  1729. void
  1730. )
  1731. {
  1732. if ( BLASTER_CardHasMixer() )
  1733. {
  1734. // Restore the state of MPU401 interrupts. If they are not disabled,
  1735. // the SB16 will not produce sound or music.
  1736. BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, BLASTER_WaveBlasterState );
  1737. }
  1738. }
  1739. /*---------------------------------------------------------------------
  1740. Function: BLASTER_Init
  1741. Initializes the sound card and prepares the module to play
  1742. digitized sounds.
  1743. ---------------------------------------------------------------------*/
  1744. int BLASTER_Init
  1745. (
  1746. void
  1747. )
  1748. {
  1749. int Irq;
  1750. int Interrupt;
  1751. int status;
  1752. if ( BLASTER_Installed )
  1753. {
  1754. BLASTER_Shutdown();
  1755. }
  1756. // Save the interrupt masks
  1757. BLASTER_IntController1Mask = inp( 0x21 );
  1758. BLASTER_IntController2Mask = inp( 0xA1 );
  1759. status = BLASTER_ResetDSP();
  1760. if ( status == BLASTER_Ok )
  1761. {
  1762. BLASTER_SaveVoiceVolume();
  1763. BLASTER_SoundPlaying = FALSE;
  1764. BLASTER_SetCallBack( NULL );
  1765. BLASTER_DMABuffer = NULL;
  1766. BLASTER_Version = BLASTER_GetDSPVersion();
  1767. BLASTER_SetPlaybackRate( BLASTER_DefaultSampleRate );
  1768. BLASTER_SetMixMode( BLASTER_DefaultMixMode );
  1769. if ( BLASTER_Config.Dma16 != UNDEFINED )
  1770. {
  1771. status = DMA_VerifyChannel( BLASTER_Config.Dma16 );
  1772. if ( status == DMA_Error )
  1773. {
  1774. BLASTER_SetErrorCode( BLASTER_DmaError );
  1775. return( BLASTER_Error );
  1776. }
  1777. }
  1778. if ( BLASTER_Config.Dma8 != UNDEFINED )
  1779. {
  1780. status = DMA_VerifyChannel( BLASTER_Config.Dma8 );
  1781. if ( status == DMA_Error )
  1782. {
  1783. BLASTER_SetErrorCode( BLASTER_DmaError );
  1784. return( BLASTER_Error );
  1785. }
  1786. }
  1787. // Install our interrupt handler
  1788. Irq = BLASTER_Config.Interrupt;
  1789. if ( !VALID_IRQ( Irq ) )
  1790. {
  1791. BLASTER_SetErrorCode( BLASTER_InvalidIrq );
  1792. return( BLASTER_Error );
  1793. }
  1794. Interrupt = BLASTER_Interrupts[ Irq ];
  1795. if ( Interrupt == INVALID )
  1796. {
  1797. BLASTER_SetErrorCode( BLASTER_InvalidIrq );
  1798. return( BLASTER_Error );
  1799. }
  1800. status = BLASTER_LockMemory();
  1801. if ( status != BLASTER_Ok )
  1802. {
  1803. BLASTER_UnlockMemory();
  1804. return( status );
  1805. }
  1806. StackSelector = allocateTimerStack( kStackSize );
  1807. if ( StackSelector == NULL )
  1808. {
  1809. BLASTER_UnlockMemory();
  1810. BLASTER_SetErrorCode( BLASTER_OutOfMemory );
  1811. return( BLASTER_Error );
  1812. }
  1813. // Leave a little room at top of stack just for the hell of it...
  1814. StackPointer = kStackSize - sizeof( long );
  1815. BLASTER_OldInt = _dos_getvect( Interrupt );
  1816. if ( Irq < 8 )
  1817. {
  1818. _dos_setvect( Interrupt, BLASTER_ServiceInterrupt );
  1819. }
  1820. else
  1821. {
  1822. status = IRQ_SetVector( Interrupt, BLASTER_ServiceInterrupt );
  1823. if ( status != IRQ_Ok )
  1824. {
  1825. BLASTER_UnlockMemory();
  1826. deallocateTimerStack( StackSelector );
  1827. StackSelector = NULL;
  1828. BLASTER_SetErrorCode( BLASTER_UnableToSetIrq );
  1829. return( BLASTER_Error );
  1830. }
  1831. }
  1832. BLASTER_Installed = TRUE;
  1833. status = BLASTER_Ok;
  1834. }
  1835. BLASTER_SetErrorCode( status );
  1836. return( status );
  1837. }
  1838. /*---------------------------------------------------------------------
  1839. Function: BLASTER_Shutdown
  1840. Ends transfer of sound data to the sound card and restores the
  1841. system resources used by the card.
  1842. ---------------------------------------------------------------------*/
  1843. void BLASTER_Shutdown
  1844. (
  1845. void
  1846. )
  1847. {
  1848. int Irq;
  1849. int Interrupt;
  1850. // Halt the DMA transfer
  1851. BLASTER_StopPlayback();
  1852. BLASTER_RestoreVoiceVolume();
  1853. // Reset the DSP
  1854. BLASTER_ResetDSP();
  1855. // Restore the original interrupt
  1856. Irq = BLASTER_Config.Interrupt;
  1857. Interrupt = BLASTER_Interrupts[ Irq ];
  1858. if ( Irq >= 8 )
  1859. {
  1860. IRQ_RestoreVector( Interrupt );
  1861. }
  1862. _dos_setvect( Interrupt, BLASTER_OldInt );
  1863. BLASTER_SoundPlaying = FALSE;
  1864. BLASTER_DMABuffer = NULL;
  1865. BLASTER_SetCallBack( NULL );
  1866. BLASTER_UnlockMemory();
  1867. deallocateTimerStack( StackSelector );
  1868. StackSelector = NULL;
  1869. BLASTER_Installed = FALSE;
  1870. }