duke3d/audiolib/awe32.c

541 lines
12 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**********************************************************************
module: AWE32.C
author: James R. Dose
date: August 23, 1994
Cover functions for calling the AWE32 low-level library.
(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/
#include <conio.h>
#include <string.h>
#include "dpmi.h"
#include "blaster.h"
#include "ctaweapi.h"
#include "awe32.h"
#define _inp inp
#define _outp outp
/* DSP defines */
#define MPU_ACK_OK 0xfe
#define MPU_RESET_CMD 0xff
#define MPU_ENTER_UART 0x3f
static WORD wSBCBaseAddx; /* Sound Blaster base address */
static WORD wEMUBaseAddx; /* EMU8000 subsystem base address */
static WORD wMpuBaseAddx; /* MPU401 base address */
static unsigned short NoteFlags[ 128 ];
/* macros */
#define SBCPort( x ) ( ( x ) + wSBCBaseAddx )
#define MPUPort( x ) ( ( x ) + wMpuBaseAddx )
static SOUND_PACKET spSound =
{
0
};
static LONG lBankSizes[ MAXBANKS ] =
{
0
};
unsigned SetES( void );
#pragma aux SetES = \
"xor eax, eax" \
"mov ax, es" \
"mov bx, ds" \
"mov es, bx" \
modify [ eax ebx ];
void RestoreES( unsigned num );
#pragma aux RestoreES = \
"mov es, ax" \
parm [ eax ];
int AWE32_ErrorCode = AWE32_Ok;
#define AWE32_SetErrorCode( status ) \
AWE32_ErrorCode = ( status );
/*---------------------------------------------------------------------
Function: AWE32_ErrorString
Returns a pointer to the error message associated with an error
number. A -1 returns a pointer the current error.
---------------------------------------------------------------------*/
char *AWE32_ErrorString
(
int ErrorNumber
)
{
char *ErrorString;
switch( ErrorNumber )
{
case AWE32_Warning :
case AWE32_Error :
ErrorString = AWE32_ErrorString( AWE32_ErrorCode );
break;
case AWE32_Ok :
ErrorString = "AWE32 ok.";
break;
case AWE32_SoundBlasterError :
ErrorString = BLASTER_ErrorString( BLASTER_Error );
break;
case AWE32_NotDetected :
ErrorString = "Could not detect AWE32.";
break;
case AWE32_UnableToInitialize :
ErrorString = "Unable to initialize AWE32.";
case AWE32_MPU401Error :
ErrorString = "MPU-401 initialization failed in AWE32.";
break;
case AWE32_DPMI_Error :
ErrorString = "DPMI Error in AWE32.";
break;
default :
ErrorString = "Unknown AWE32 error code.";
break;
}
return( ErrorString );
}
/**********************************************************************
Memory locked functions:
**********************************************************************/
#define AWE32_LockStart AWE32_NoteOff
void AWE32_NoteOff
(
int channel,
int key,
int velocity
)
{
unsigned temp;
temp = SetES();
awe32NoteOff( channel, key, velocity );
RestoreES( temp );
NoteFlags[ key ] ^= ( 1 << channel );
}
void AWE32_NoteOn
(
int channel,
int key,
int velocity
)
{
unsigned temp;
temp = SetES();
awe32NoteOn( channel, key, velocity );
RestoreES( temp );
NoteFlags[ key ] |= ( 1 << channel );
}
void AWE32_PolyAftertouch
(
int channel,
int key,
int pressure
)
{
unsigned temp;
temp = SetES();
awe32PolyKeyPressure( channel, key, pressure );
RestoreES( temp );
}
void AWE32_ChannelAftertouch
(
int channel,
int pressure
)
{
unsigned temp;
temp = SetES();
awe32ChannelPressure( channel, pressure );
RestoreES( temp );
}
void AWE32_ControlChange
(
int channel,
int number,
int value
)
{
unsigned temp;
int i;
unsigned channelmask;
temp = SetES();
if ( number == 0x7b )
{
channelmask = 1 << channel;
for( i = 0; i < 128; i++ )
{
if ( NoteFlags[ i ] & channelmask )
{
awe32NoteOff( channel, i, 0 );
NoteFlags[ i ] ^= channelmask;
}
}
}
else
{
awe32Controller( channel, number, value );
}
RestoreES( temp );
}
void AWE32_ProgramChange
(
int channel,
int program
)
{
unsigned temp;
temp = SetES();
awe32ProgramChange( channel, program );
RestoreES( temp );
}
void AWE32_PitchBend
(
int channel,
int lsb,
int msb
)
{
unsigned temp;
temp = SetES();
awe32PitchBend( channel, lsb, msb );
RestoreES( temp );
}
/*---------------------------------------------------------------------
Function: AWE32_LockEnd
Used for determining the length of the functions to lock in memory.
---------------------------------------------------------------------*/
static void AWE32_LockEnd
(
void
)
{
}
/*
static int InitMPU
(
void
)
{
volatile DWORD dwCount;
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
_outp(MPUPort(1), MPU_RESET_CMD);
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
_inp(MPUPort(0));
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
_outp(MPUPort(1), MPU_RESET_CMD);
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
_inp(MPUPort(0));
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
_outp(MPUPort(1), MPU_ENTER_UART);
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
if (!dwCount) return TRUE;
if (_inp(MPUPort(0)) != MPU_ACK_OK) return TRUE;
// mask MPU-401 interrupt
_outp(SBCPort(0x4), 0x83);
_outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04);
return FALSE;
}
*/
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͸*/
/*<2A> ShutdownMPU <20>*/
/*<2A> Cleans up Sound Blaster to normal state. <20>*/
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;*/
static void ShutdownMPU
(
void
)
{
volatile DWORD dwCount;
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
_outp(MPUPort(1), MPU_RESET_CMD);
for (dwCount=0; dwCount<0x2000; dwCount++) ;
_inp(MPUPort(0));
for (dwCount=0; dwCount<0x2000; dwCount++) ;
dwCount = 0x2000;
while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
_outp(MPUPort(1), MPU_RESET_CMD);
for (dwCount=0; dwCount<0x2000; dwCount++) ;
_inp(MPUPort(0));
}
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͸*/
/*<2A> LoadSBK <20>*/
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;*/
static void LoadSBK
(
void
)
{
/* use embeded preset objects */
spSound.bank_no = 0; /* load as Bank 0 */
spSound.total_banks = 1; /* use 1 bank first */
lBankSizes[ 0 ] = 0; /* ram is not needed */
spSound.banksizes = lBankSizes;
awe32DefineBankSizes( &spSound );
awe32SoundPad.SPad1 = awe32SPad1Obj;
awe32SoundPad.SPad2 = awe32SPad2Obj;
awe32SoundPad.SPad3 = awe32SPad3Obj;
awe32SoundPad.SPad4 = awe32SPad4Obj;
awe32SoundPad.SPad5 = awe32SPad5Obj;
awe32SoundPad.SPad6 = awe32SPad6Obj;
awe32SoundPad.SPad7 = awe32SPad7Obj;
}
int AWE32_Init
(
void
)
{
int status;
BLASTER_CONFIG Blaster;
wSBCBaseAddx = 0x220;
wEMUBaseAddx = 0x620;
wMpuBaseAddx = 0x330;
status = BLASTER_GetCardSettings( &Blaster );
if ( status != BLASTER_Ok )
{
status = BLASTER_GetEnv( &Blaster );
if ( status != BLASTER_Ok )
{
AWE32_SetErrorCode( AWE32_SoundBlasterError );
return( AWE32_Error );
}
}
wSBCBaseAddx = Blaster.Address;
if ( wSBCBaseAddx == UNDEFINED )
{
wSBCBaseAddx = 0x220;
}
wMpuBaseAddx = Blaster.Midi;
if ( wMpuBaseAddx == UNDEFINED )
{
wMpuBaseAddx = 0x330;
}
wEMUBaseAddx = Blaster.Emu;
if ( wEMUBaseAddx <= 0 )
{
wEMUBaseAddx = wSBCBaseAddx + 0x400;
}
status = awe32Detect( wEMUBaseAddx );
if ( status )
{
AWE32_SetErrorCode( AWE32_NotDetected );
return( AWE32_Error );
}
status = awe32InitHardware();
if ( status )
{
AWE32_SetErrorCode( AWE32_UnableToInitialize );
return( AWE32_Error );
}
status = awe32InitMIDI();
if ( status )
{
AWE32_Shutdown();
AWE32_SetErrorCode( AWE32_MPU401Error )
return( AWE32_Error );
}
/*
status = InitMPU();
if ( status )
{
ShutdownMPU();
status = InitMPU();
if ( status )
{
ShutdownMPU();
status = InitMPU();
if ( status )
{
AWE32_Shutdown();
AWE32_SetErrorCode( AWE32_MPU401Error )
return( AWE32_Error );
}
}
}
*/
status = DPMI_LockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
status |= DPMI_Lock( wSBCBaseAddx );
status |= DPMI_Lock( wEMUBaseAddx );
status |= DPMI_Lock( wMpuBaseAddx );
status |= DPMI_Lock( spSound );
status |= DPMI_Lock( lBankSizes );
status |= DPMI_LockMemory( NoteFlags, sizeof( NoteFlags ) );
// Lock awe32 library
status = DPMI_LockMemoryRegion( __midieng_code, __midieng_ecode );
status = DPMI_LockMemoryRegion( __midieng_code(), __midieng_ecode() );
status = DPMI_LockMemoryRegion( __nrpn_code, __nrpn_ecode );
status = DPMI_LockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
status = DPMI_LockMemoryRegion( &__midivar_data, &__midivar_edata );
status = DPMI_LockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
status = DPMI_LockMemoryRegion( &__embed_data, &__embed_edata );
if ( status != DPMI_Ok )
{
ShutdownMPU();
awe32Terminate();
AWE32_SetErrorCode( AWE32_DPMI_Error );
return( AWE32_Error );
}
// Set the number of voices to use to 32
awe32NumG = 32;
awe32TotalPatchRam(&spSound);
LoadSBK();
awe32InitMIDI();
awe32InitNRPN();
memset( NoteFlags, 0, sizeof( NoteFlags ) );
return( AWE32_Ok );
}
void AWE32_Shutdown
(
void
)
{
ShutdownMPU();
awe32Terminate();
DPMI_UnlockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
DPMI_Unlock( wSBCBaseAddx );
DPMI_Unlock( wEMUBaseAddx );
DPMI_Unlock( wMpuBaseAddx );
DPMI_Unlock( spSound );
DPMI_Unlock( lBankSizes );
DPMI_UnlockMemory( NoteFlags, sizeof( NoteFlags ) );
// Unlock awe32 library
DPMI_UnlockMemoryRegion( __midieng_code, __midieng_ecode );
DPMI_UnlockMemoryRegion( __midieng_code(), __midieng_ecode() );
DPMI_UnlockMemoryRegion( __nrpn_code, __nrpn_ecode );
DPMI_UnlockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
DPMI_UnlockMemoryRegion( &__midivar_data, &__midivar_edata );
DPMI_UnlockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
DPMI_UnlockMemoryRegion( &__embed_data, &__embed_edata );
}