AWE32.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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: AWE32.C
  17. author: James R. Dose
  18. date: August 23, 1994
  19. Cover functions for calling the AWE32 low-level library.
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. #include <conio.h>
  23. #include <string.h>
  24. #include "dpmi.h"
  25. #include "blaster.h"
  26. #include "ctaweapi.h"
  27. #include "awe32.h"
  28. #define _inp inp
  29. #define _outp outp
  30. /* DSP defines */
  31. #define MPU_ACK_OK 0xfe
  32. #define MPU_RESET_CMD 0xff
  33. #define MPU_ENTER_UART 0x3f
  34. static WORD wSBCBaseAddx; /* Sound Blaster base address */
  35. static WORD wEMUBaseAddx; /* EMU8000 subsystem base address */
  36. static WORD wMpuBaseAddx; /* MPU401 base address */
  37. static unsigned short NoteFlags[ 128 ];
  38. /* macros */
  39. #define SBCPort( x ) ( ( x ) + wSBCBaseAddx )
  40. #define MPUPort( x ) ( ( x ) + wMpuBaseAddx )
  41. static SOUND_PACKET spSound =
  42. {
  43. 0
  44. };
  45. static LONG lBankSizes[ MAXBANKS ] =
  46. {
  47. 0
  48. };
  49. unsigned SetES( void );
  50. #pragma aux SetES = \
  51. "xor eax, eax" \
  52. "mov ax, es" \
  53. "mov bx, ds" \
  54. "mov es, bx" \
  55. modify [ eax ebx ];
  56. void RestoreES( unsigned num );
  57. #pragma aux RestoreES = \
  58. "mov es, ax" \
  59. parm [ eax ];
  60. int AWE32_ErrorCode = AWE32_Ok;
  61. #define AWE32_SetErrorCode( status ) \
  62. AWE32_ErrorCode = ( status );
  63. /*---------------------------------------------------------------------
  64. Function: AWE32_ErrorString
  65. Returns a pointer to the error message associated with an error
  66. number. A -1 returns a pointer the current error.
  67. ---------------------------------------------------------------------*/
  68. char *AWE32_ErrorString
  69. (
  70. int ErrorNumber
  71. )
  72. {
  73. char *ErrorString;
  74. switch( ErrorNumber )
  75. {
  76. case AWE32_Warning :
  77. case AWE32_Error :
  78. ErrorString = AWE32_ErrorString( AWE32_ErrorCode );
  79. break;
  80. case AWE32_Ok :
  81. ErrorString = "AWE32 ok.";
  82. break;
  83. case AWE32_SoundBlasterError :
  84. ErrorString = BLASTER_ErrorString( BLASTER_Error );
  85. break;
  86. case AWE32_NotDetected :
  87. ErrorString = "Could not detect AWE32.";
  88. break;
  89. case AWE32_UnableToInitialize :
  90. ErrorString = "Unable to initialize AWE32.";
  91. case AWE32_MPU401Error :
  92. ErrorString = "MPU-401 initialization failed in AWE32.";
  93. break;
  94. case AWE32_DPMI_Error :
  95. ErrorString = "DPMI Error in AWE32.";
  96. break;
  97. default :
  98. ErrorString = "Unknown AWE32 error code.";
  99. break;
  100. }
  101. return( ErrorString );
  102. }
  103. /**********************************************************************
  104. Memory locked functions:
  105. **********************************************************************/
  106. #define AWE32_LockStart AWE32_NoteOff
  107. void AWE32_NoteOff
  108. (
  109. int channel,
  110. int key,
  111. int velocity
  112. )
  113. {
  114. unsigned temp;
  115. temp = SetES();
  116. awe32NoteOff( channel, key, velocity );
  117. RestoreES( temp );
  118. NoteFlags[ key ] ^= ( 1 << channel );
  119. }
  120. void AWE32_NoteOn
  121. (
  122. int channel,
  123. int key,
  124. int velocity
  125. )
  126. {
  127. unsigned temp;
  128. temp = SetES();
  129. awe32NoteOn( channel, key, velocity );
  130. RestoreES( temp );
  131. NoteFlags[ key ] |= ( 1 << channel );
  132. }
  133. void AWE32_PolyAftertouch
  134. (
  135. int channel,
  136. int key,
  137. int pressure
  138. )
  139. {
  140. unsigned temp;
  141. temp = SetES();
  142. awe32PolyKeyPressure( channel, key, pressure );
  143. RestoreES( temp );
  144. }
  145. void AWE32_ChannelAftertouch
  146. (
  147. int channel,
  148. int pressure
  149. )
  150. {
  151. unsigned temp;
  152. temp = SetES();
  153. awe32ChannelPressure( channel, pressure );
  154. RestoreES( temp );
  155. }
  156. void AWE32_ControlChange
  157. (
  158. int channel,
  159. int number,
  160. int value
  161. )
  162. {
  163. unsigned temp;
  164. int i;
  165. unsigned channelmask;
  166. temp = SetES();
  167. if ( number == 0x7b )
  168. {
  169. channelmask = 1 << channel;
  170. for( i = 0; i < 128; i++ )
  171. {
  172. if ( NoteFlags[ i ] & channelmask )
  173. {
  174. awe32NoteOff( channel, i, 0 );
  175. NoteFlags[ i ] ^= channelmask;
  176. }
  177. }
  178. }
  179. else
  180. {
  181. awe32Controller( channel, number, value );
  182. }
  183. RestoreES( temp );
  184. }
  185. void AWE32_ProgramChange
  186. (
  187. int channel,
  188. int program
  189. )
  190. {
  191. unsigned temp;
  192. temp = SetES();
  193. awe32ProgramChange( channel, program );
  194. RestoreES( temp );
  195. }
  196. void AWE32_PitchBend
  197. (
  198. int channel,
  199. int lsb,
  200. int msb
  201. )
  202. {
  203. unsigned temp;
  204. temp = SetES();
  205. awe32PitchBend( channel, lsb, msb );
  206. RestoreES( temp );
  207. }
  208. /*---------------------------------------------------------------------
  209. Function: AWE32_LockEnd
  210. Used for determining the length of the functions to lock in memory.
  211. ---------------------------------------------------------------------*/
  212. static void AWE32_LockEnd
  213. (
  214. void
  215. )
  216. {
  217. }
  218. /*
  219. static int InitMPU
  220. (
  221. void
  222. )
  223. {
  224. volatile DWORD dwCount;
  225. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  226. dwCount = 0x2000;
  227. while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
  228. _outp(MPUPort(1), MPU_RESET_CMD);
  229. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  230. dwCount = 0x2000;
  231. while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
  232. _inp(MPUPort(0));
  233. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  234. dwCount = 0x2000;
  235. while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
  236. _outp(MPUPort(1), MPU_RESET_CMD);
  237. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  238. dwCount = 0x2000;
  239. while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
  240. _inp(MPUPort(0));
  241. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  242. dwCount = 0x2000;
  243. while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
  244. _outp(MPUPort(1), MPU_ENTER_UART);
  245. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  246. dwCount = 0x2000;
  247. while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
  248. if (!dwCount) return TRUE;
  249. if (_inp(MPUPort(0)) != MPU_ACK_OK) return TRUE;
  250. // mask MPU-401 interrupt
  251. _outp(SBCPort(0x4), 0x83);
  252. _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04);
  253. return FALSE;
  254. }
  255. */
  256. /*ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸*/
  257. /*³ ShutdownMPU ³*/
  258. /*³ Cleans up Sound Blaster to normal state. ³*/
  259. /*ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;*/
  260. static void ShutdownMPU
  261. (
  262. void
  263. )
  264. {
  265. volatile DWORD dwCount;
  266. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  267. dwCount = 0x2000;
  268. while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
  269. _outp(MPUPort(1), MPU_RESET_CMD);
  270. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  271. _inp(MPUPort(0));
  272. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  273. dwCount = 0x2000;
  274. while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
  275. _outp(MPUPort(1), MPU_RESET_CMD);
  276. for (dwCount=0; dwCount<0x2000; dwCount++) ;
  277. _inp(MPUPort(0));
  278. }
  279. /*ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸*/
  280. /*³ LoadSBK ³*/
  281. /*ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;*/
  282. static void LoadSBK
  283. (
  284. void
  285. )
  286. {
  287. /* use embeded preset objects */
  288. spSound.bank_no = 0; /* load as Bank 0 */
  289. spSound.total_banks = 1; /* use 1 bank first */
  290. lBankSizes[ 0 ] = 0; /* ram is not needed */
  291. spSound.banksizes = lBankSizes;
  292. awe32DefineBankSizes( &spSound );
  293. awe32SoundPad.SPad1 = awe32SPad1Obj;
  294. awe32SoundPad.SPad2 = awe32SPad2Obj;
  295. awe32SoundPad.SPad3 = awe32SPad3Obj;
  296. awe32SoundPad.SPad4 = awe32SPad4Obj;
  297. awe32SoundPad.SPad5 = awe32SPad5Obj;
  298. awe32SoundPad.SPad6 = awe32SPad6Obj;
  299. awe32SoundPad.SPad7 = awe32SPad7Obj;
  300. }
  301. int AWE32_Init
  302. (
  303. void
  304. )
  305. {
  306. int status;
  307. BLASTER_CONFIG Blaster;
  308. wSBCBaseAddx = 0x220;
  309. wEMUBaseAddx = 0x620;
  310. wMpuBaseAddx = 0x330;
  311. status = BLASTER_GetCardSettings( &Blaster );
  312. if ( status != BLASTER_Ok )
  313. {
  314. status = BLASTER_GetEnv( &Blaster );
  315. if ( status != BLASTER_Ok )
  316. {
  317. AWE32_SetErrorCode( AWE32_SoundBlasterError );
  318. return( AWE32_Error );
  319. }
  320. }
  321. wSBCBaseAddx = Blaster.Address;
  322. if ( wSBCBaseAddx == UNDEFINED )
  323. {
  324. wSBCBaseAddx = 0x220;
  325. }
  326. wMpuBaseAddx = Blaster.Midi;
  327. if ( wMpuBaseAddx == UNDEFINED )
  328. {
  329. wMpuBaseAddx = 0x330;
  330. }
  331. wEMUBaseAddx = Blaster.Emu;
  332. if ( wEMUBaseAddx <= 0 )
  333. {
  334. wEMUBaseAddx = wSBCBaseAddx + 0x400;
  335. }
  336. status = awe32Detect( wEMUBaseAddx );
  337. if ( status )
  338. {
  339. AWE32_SetErrorCode( AWE32_NotDetected );
  340. return( AWE32_Error );
  341. }
  342. status = awe32InitHardware();
  343. if ( status )
  344. {
  345. AWE32_SetErrorCode( AWE32_UnableToInitialize );
  346. return( AWE32_Error );
  347. }
  348. status = awe32InitMIDI();
  349. if ( status )
  350. {
  351. AWE32_Shutdown();
  352. AWE32_SetErrorCode( AWE32_MPU401Error )
  353. return( AWE32_Error );
  354. }
  355. /*
  356. status = InitMPU();
  357. if ( status )
  358. {
  359. ShutdownMPU();
  360. status = InitMPU();
  361. if ( status )
  362. {
  363. ShutdownMPU();
  364. status = InitMPU();
  365. if ( status )
  366. {
  367. AWE32_Shutdown();
  368. AWE32_SetErrorCode( AWE32_MPU401Error )
  369. return( AWE32_Error );
  370. }
  371. }
  372. }
  373. */
  374. status = DPMI_LockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
  375. status |= DPMI_Lock( wSBCBaseAddx );
  376. status |= DPMI_Lock( wEMUBaseAddx );
  377. status |= DPMI_Lock( wMpuBaseAddx );
  378. status |= DPMI_Lock( spSound );
  379. status |= DPMI_Lock( lBankSizes );
  380. status |= DPMI_LockMemory( NoteFlags, sizeof( NoteFlags ) );
  381. // Lock awe32 library
  382. status = DPMI_LockMemoryRegion( __midieng_code, __midieng_ecode );
  383. status = DPMI_LockMemoryRegion( __midieng_code(), __midieng_ecode() );
  384. status = DPMI_LockMemoryRegion( __nrpn_code, __nrpn_ecode );
  385. status = DPMI_LockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
  386. status = DPMI_LockMemoryRegion( &__midivar_data, &__midivar_edata );
  387. status = DPMI_LockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
  388. status = DPMI_LockMemoryRegion( &__embed_data, &__embed_edata );
  389. if ( status != DPMI_Ok )
  390. {
  391. ShutdownMPU();
  392. awe32Terminate();
  393. AWE32_SetErrorCode( AWE32_DPMI_Error );
  394. return( AWE32_Error );
  395. }
  396. // Set the number of voices to use to 32
  397. awe32NumG = 32;
  398. awe32TotalPatchRam(&spSound);
  399. LoadSBK();
  400. awe32InitMIDI();
  401. awe32InitNRPN();
  402. memset( NoteFlags, 0, sizeof( NoteFlags ) );
  403. return( AWE32_Ok );
  404. }
  405. void AWE32_Shutdown
  406. (
  407. void
  408. )
  409. {
  410. ShutdownMPU();
  411. awe32Terminate();
  412. DPMI_UnlockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
  413. DPMI_Unlock( wSBCBaseAddx );
  414. DPMI_Unlock( wEMUBaseAddx );
  415. DPMI_Unlock( wMpuBaseAddx );
  416. DPMI_Unlock( spSound );
  417. DPMI_Unlock( lBankSizes );
  418. DPMI_UnlockMemory( NoteFlags, sizeof( NoteFlags ) );
  419. // Unlock awe32 library
  420. DPMI_UnlockMemoryRegion( __midieng_code, __midieng_ecode );
  421. DPMI_UnlockMemoryRegion( __midieng_code(), __midieng_ecode() );
  422. DPMI_UnlockMemoryRegion( __nrpn_code, __nrpn_ecode );
  423. DPMI_UnlockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
  424. DPMI_UnlockMemoryRegion( &__midivar_data, &__midivar_edata );
  425. DPMI_UnlockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
  426. DPMI_UnlockMemoryRegion( &__embed_data, &__embed_edata );
  427. }