ADLIBFX.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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: ADLIBFX.C
  17. author: James R. Dose
  18. date: April 1, 1994
  19. Low level routines to support Adlib sound effects created by Muse.
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. #include <dos.h>
  23. #include <stdlib.h>
  24. #include <conio.h>
  25. #include "dpmi.h"
  26. #include "task_man.h"
  27. #include "interrup.h"
  28. #include "al_midi.h"
  29. #include "adlibfx.h"
  30. #define TRUE ( 1 == 1 )
  31. #define FALSE ( !TRUE )
  32. static void ADLIBFX_SendOutput( int reg, int data );
  33. static void ADLIBFX_Service( task *Task );
  34. static long ADLIBFX_LengthLeft;
  35. static int ADLIBFX_Block;
  36. static ALSound *ADLIBFX_Sound = NULL;
  37. static char *ADLIBFX_SoundPtr = NULL;
  38. static int ADLIBFX_Priority;
  39. static unsigned long ADLIBFX_CallBackVal;
  40. static void ( *ADLIBFX_CallBackFunc )( unsigned long ) = NULL;
  41. static int ADLIBFX_SoundVolume;
  42. static int ADLIBFX_TotalVolume = ADLIBFX_MaxVolume;
  43. static task *ADLIBFX_ServiceTask = NULL;
  44. static int ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
  45. int ADLIBFX_Installed = FALSE;
  46. int ADLIBFX_ErrorCode = ADLIBFX_Ok;
  47. #define ADLIBFX_SetErrorCode( status ) \
  48. ADLIBFX_ErrorCode = ( status );
  49. /*---------------------------------------------------------------------
  50. Function: ADLIBFX_ErrorString
  51. Returns a pointer to the error message associated with an error
  52. number. A -1 returns a pointer the current error.
  53. ---------------------------------------------------------------------*/
  54. char *ADLIBFX_ErrorString
  55. (
  56. int ErrorNumber
  57. )
  58. {
  59. char *ErrorString;
  60. switch( ErrorNumber )
  61. {
  62. case ADLIBFX_Warning :
  63. case ADLIBFX_Error :
  64. ErrorString = ADLIBFX_ErrorString( ADLIBFX_ErrorCode );
  65. break;
  66. case ADLIBFX_Ok :
  67. ErrorString = "Adlib FX ok.";
  68. break;
  69. case ADLIBFX_NoVoices :
  70. ErrorString = "No free voices available in Adlib FX.";
  71. break;
  72. case ADLIBFX_VoiceNotFound :
  73. ErrorString = "No voice with matching handle found.";
  74. break;
  75. case ADLIBFX_DPMI_Error :
  76. ErrorString = "DPMI Error in AdlibFX.";
  77. break;
  78. default :
  79. ErrorString = "Unknown Adlib FX error code.";
  80. break;
  81. }
  82. return( ErrorString );
  83. }
  84. /**********************************************************************
  85. Memory locked functions:
  86. **********************************************************************/
  87. #define ADLIBFX_LockStart ADLIBFX_SendOutput
  88. /*---------------------------------------------------------------------
  89. Function: ADLIBFX_SendOutput
  90. Writes a byte of data to the specified register on the Adlib card.
  91. ---------------------------------------------------------------------*/
  92. static void ADLIBFX_SendOutput
  93. (
  94. int reg,
  95. int data
  96. )
  97. {
  98. int i;
  99. int adlib_port = 0x388;
  100. unsigned flags;
  101. flags = DisableInterrupts();
  102. outp( adlib_port, reg );
  103. for( i = 6; i ; i-- )
  104. {
  105. inp( adlib_port );
  106. }
  107. outp( adlib_port + 1, data );
  108. for( i = 35; i ; i-- )
  109. {
  110. inp( adlib_port );
  111. }
  112. RestoreInterrupts( flags );
  113. }
  114. /*---------------------------------------------------------------------
  115. Function: ADLIBFX_Stop
  116. Halts playback of the currently playing sound effect.
  117. ---------------------------------------------------------------------*/
  118. int ADLIBFX_Stop
  119. (
  120. int handle
  121. )
  122. {
  123. unsigned flags;
  124. if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
  125. {
  126. ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
  127. return( ADLIBFX_Warning );
  128. }
  129. flags = DisableInterrupts();
  130. ADLIBFX_SendOutput( 0xb0, 0 );
  131. ADLIBFX_Sound = NULL;
  132. ADLIBFX_SoundPtr = NULL;
  133. ADLIBFX_LengthLeft = 0;
  134. ADLIBFX_Priority = 0;
  135. RestoreInterrupts( flags );
  136. if ( ADLIBFX_CallBackFunc )
  137. {
  138. ADLIBFX_CallBackFunc( ADLIBFX_CallBackVal );
  139. }
  140. return( ADLIBFX_Ok );
  141. }
  142. /*---------------------------------------------------------------------
  143. Function: ADLIBFX_Service
  144. Task Manager routine to perform the playback of a sound effect.
  145. ---------------------------------------------------------------------*/
  146. static void ADLIBFX_Service
  147. (
  148. task *Task
  149. )
  150. {
  151. int value;
  152. if ( ADLIBFX_SoundPtr )
  153. {
  154. value = *ADLIBFX_SoundPtr++;
  155. if ( value != 0 )
  156. {
  157. ADLIBFX_SendOutput( 0xa0, value );
  158. ADLIBFX_SendOutput( 0xb0, ADLIBFX_Block );
  159. }
  160. else
  161. {
  162. ADLIBFX_SendOutput( 0xb0, 0 );
  163. }
  164. ADLIBFX_LengthLeft--;
  165. if ( ADLIBFX_LengthLeft <= 0 )
  166. {
  167. ADLIBFX_Stop( ADLIBFX_VoiceHandle );
  168. }
  169. }
  170. }
  171. /*---------------------------------------------------------------------
  172. Function: ADLIBFX_SetVolume
  173. Sets the volume of the currently playing sound effect.
  174. ---------------------------------------------------------------------*/
  175. int ADLIBFX_SetVolume
  176. (
  177. int handle,
  178. int volume
  179. )
  180. {
  181. unsigned flags;
  182. int carrierlevel;
  183. flags = DisableInterrupts();
  184. if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
  185. {
  186. RestoreInterrupts( flags );
  187. ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
  188. return( ADLIBFX_Warning );
  189. }
  190. volume = min( volume, ADLIBFX_MaxVolume );
  191. volume = max( volume, 0 );
  192. ADLIBFX_SoundVolume = volume;
  193. volume *= ADLIBFX_TotalVolume;
  194. volume /= ADLIBFX_MaxVolume;
  195. carrierlevel = ADLIBFX_Sound->cScale & 0x3f;
  196. carrierlevel ^= 0x3f;
  197. carrierlevel *= ( volume / 2 ) + 0x80;
  198. carrierlevel /= ADLIBFX_MaxVolume;
  199. carrierlevel ^= 0x3f;
  200. carrierlevel |= ADLIBFX_Sound->cScale & 0xc0;
  201. ADLIBFX_SendOutput( 0x43, carrierlevel );
  202. RestoreInterrupts( flags );
  203. return( ADLIBFX_Ok );
  204. }
  205. /*---------------------------------------------------------------------
  206. Function: ADLIBFX_SetTotalVolume
  207. Sets the total volume of the sound effect.
  208. ---------------------------------------------------------------------*/
  209. int ADLIBFX_SetTotalVolume
  210. (
  211. int volume
  212. )
  213. {
  214. volume = max( volume, 0 );
  215. volume = min( volume, ADLIBFX_MaxVolume );
  216. ADLIBFX_TotalVolume = volume;
  217. ADLIBFX_SetVolume( ADLIBFX_VoiceHandle, ADLIBFX_SoundVolume );
  218. return( ADLIBFX_Ok );
  219. }
  220. /*---------------------------------------------------------------------
  221. Function: ADLIBFX_GetTotalVolume
  222. Returns the total volume of the sound effect.
  223. ---------------------------------------------------------------------*/
  224. int ADLIBFX_GetTotalVolume
  225. (
  226. void
  227. )
  228. {
  229. return( ADLIBFX_TotalVolume );
  230. }
  231. /*---------------------------------------------------------------------
  232. Function: ADLIBFX_VoiceAvailable
  233. Checks if a voice can be play at the specified priority.
  234. ---------------------------------------------------------------------*/
  235. int ADLIBFX_VoiceAvailable
  236. (
  237. int priority
  238. )
  239. {
  240. if ( priority < ADLIBFX_Priority )
  241. {
  242. return( FALSE );
  243. }
  244. return( TRUE );
  245. }
  246. /*---------------------------------------------------------------------
  247. Function: ADLIBFX_Play
  248. Starts playback of a Muse sound effect.
  249. ---------------------------------------------------------------------*/
  250. int ADLIBFX_Play
  251. (
  252. ALSound *sound,
  253. int volume,
  254. int priority,
  255. unsigned long callbackval
  256. )
  257. {
  258. unsigned flags;
  259. int carrierlevel;
  260. if ( priority < ADLIBFX_Priority )
  261. {
  262. ADLIBFX_SetErrorCode( ADLIBFX_NoVoices );
  263. return( ADLIBFX_Warning );
  264. }
  265. ADLIBFX_Stop( ADLIBFX_VoiceHandle );
  266. ADLIBFX_VoiceHandle++;
  267. if ( ADLIBFX_VoiceHandle < ADLIBFX_MinVoiceHandle )
  268. {
  269. ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
  270. }
  271. flags = DisableInterrupts();
  272. ADLIBFX_LengthLeft = sound->length;
  273. ADLIBFX_Priority = priority;
  274. ADLIBFX_Sound = sound;
  275. ADLIBFX_SoundPtr = &sound->data;
  276. ADLIBFX_CallBackVal = callbackval;
  277. ADLIBFX_Block = ( ( sound->block & 7 ) << 2 ) | 0x20;
  278. volume = min( volume, ADLIBFX_MaxVolume );
  279. volume = max( volume, 0 );
  280. ADLIBFX_SoundVolume = volume;
  281. volume *= ADLIBFX_TotalVolume;
  282. volume /= ADLIBFX_MaxVolume;
  283. carrierlevel = sound->cScale & 0x3f;
  284. carrierlevel ^= 0x3f;
  285. carrierlevel *= ( volume / 2 ) + 0x80;
  286. carrierlevel /= ADLIBFX_MaxVolume;
  287. carrierlevel ^= 0x3f;
  288. carrierlevel |= sound->cScale & 0xc0;
  289. ADLIBFX_SendOutput( 0x20, sound->mChar );
  290. ADLIBFX_SendOutput( 0x40, sound->mScale );
  291. ADLIBFX_SendOutput( 0x60, sound->mAttack );
  292. ADLIBFX_SendOutput( 0x80, sound->mSus );
  293. ADLIBFX_SendOutput( 0xe0, sound->mWave );
  294. ADLIBFX_SendOutput( 0x23, sound->cChar );
  295. ADLIBFX_SendOutput( 0x43, carrierlevel );
  296. ADLIBFX_SendOutput( 0x63, sound->cAttack );
  297. ADLIBFX_SendOutput( 0x83, sound->cSus );
  298. ADLIBFX_SendOutput( 0xe3, sound->cWave );
  299. ADLIBFX_SendOutput( 0xc0, 0 );
  300. RestoreInterrupts( flags );
  301. return( ADLIBFX_VoiceHandle );
  302. }
  303. /*---------------------------------------------------------------------
  304. Function: ADLIBFX_SoundPlaying
  305. Checks if a sound effect is currently playing.
  306. ---------------------------------------------------------------------*/
  307. int ADLIBFX_SoundPlaying
  308. (
  309. int handle
  310. )
  311. {
  312. int status;
  313. status = FALSE;
  314. if ( ( handle == ADLIBFX_VoiceHandle ) && ( ADLIBFX_LengthLeft > 0 ) )
  315. {
  316. status = TRUE;
  317. }
  318. return( status );
  319. }
  320. /*---------------------------------------------------------------------
  321. Function: ADLIBFX_LockEnd
  322. Used for determining the length of the functions to lock in memory.
  323. ---------------------------------------------------------------------*/
  324. static void ADLIBFX_LockEnd
  325. (
  326. void
  327. )
  328. {
  329. }
  330. /*---------------------------------------------------------------------
  331. Function: ADLIBFX_SetCallBack
  332. Set the function to call when a voice stops.
  333. ---------------------------------------------------------------------*/
  334. void ADLIBFX_SetCallBack
  335. (
  336. void ( *function )( unsigned long )
  337. )
  338. {
  339. ADLIBFX_CallBackFunc = function;
  340. }
  341. /*---------------------------------------------------------------------
  342. Function: ADLIBFX_Init
  343. Initializes the sound effect engine.
  344. ---------------------------------------------------------------------*/
  345. int ADLIBFX_Init
  346. (
  347. void
  348. )
  349. {
  350. int status;
  351. if ( ADLIBFX_Installed )
  352. {
  353. ADLIBFX_Shutdown();
  354. }
  355. status = DPMI_LockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
  356. status |= DPMI_Lock( ADLIBFX_VoiceHandle );
  357. status |= DPMI_Lock( ADLIBFX_Sound );
  358. status |= DPMI_Lock( ADLIBFX_ErrorCode );
  359. status |= DPMI_Lock( ADLIBFX_SoundPtr );
  360. status |= DPMI_Lock( ADLIBFX_LengthLeft );
  361. status |= DPMI_Lock( ADLIBFX_Priority );
  362. status |= DPMI_Lock( ADLIBFX_CallBackFunc );
  363. status |= DPMI_Lock( ADLIBFX_Block );
  364. if ( status != DPMI_Ok )
  365. {
  366. ADLIBFX_SetErrorCode( ADLIBFX_DPMI_Error );
  367. return( ADLIBFX_Error );
  368. }
  369. //JIM
  370. // AL_ReserveVoice( 0 );
  371. ADLIBFX_Stop( ADLIBFX_VoiceHandle );
  372. ADLIBFX_ServiceTask = TS_ScheduleTask( &ADLIBFX_Service, 140, 2, NULL );
  373. TS_Dispatch();
  374. ADLIBFX_Installed = TRUE;
  375. ADLIBFX_CallBackFunc = NULL;
  376. ADLIBFX_SetErrorCode( ADLIBFX_Ok );
  377. return( ADLIBFX_Ok );
  378. }
  379. /*---------------------------------------------------------------------
  380. Function: ADLIBFX_Shutdown
  381. Ends the use of the sound effect engine.
  382. ---------------------------------------------------------------------*/
  383. int ADLIBFX_Shutdown
  384. (
  385. void
  386. )
  387. {
  388. if ( ADLIBFX_Installed )
  389. {
  390. ADLIBFX_Stop( ADLIBFX_VoiceHandle );
  391. TS_Terminate( ADLIBFX_ServiceTask );
  392. ADLIBFX_ServiceTask = NULL;
  393. //JIM
  394. // AL_ReleaseVoice( 0 );
  395. ADLIBFX_Installed = FALSE;
  396. DPMI_UnlockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
  397. DPMI_Unlock( ADLIBFX_VoiceHandle );
  398. DPMI_Unlock( ADLIBFX_Sound );
  399. DPMI_Unlock( ADLIBFX_ErrorCode );
  400. DPMI_Unlock( ADLIBFX_SoundPtr );
  401. DPMI_Unlock( ADLIBFX_LengthLeft );
  402. DPMI_Unlock( ADLIBFX_Priority );
  403. DPMI_Unlock( ADLIBFX_CallBackFunc );
  404. DPMI_Unlock( ADLIBFX_Block );
  405. }
  406. ADLIBFX_SetErrorCode( ADLIBFX_Ok );
  407. return( ADLIBFX_Ok );
  408. }