2002-04-04 12:54:27 +00:00
|
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
|
* Copyright (C) 2002 R<EFBFBD>diger Hanke
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* MorphOS sound support
|
2002-04-04 14:05:54 +00:00
|
|
|
|
*
|
|
|
|
|
* $Header$
|
|
|
|
|
*
|
2002-04-04 12:54:27 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "scumm.h"
|
|
|
|
|
|
|
|
|
|
#include <dos/dos.h>
|
|
|
|
|
#include <exec/memory.h>
|
|
|
|
|
#include <devices/ahi.h>
|
|
|
|
|
#include <devices/amidi.h>
|
|
|
|
|
|
|
|
|
|
#include <clib/alib_protos.h>
|
|
|
|
|
#include <proto/exec.h>
|
|
|
|
|
#include <proto/dos.h>
|
|
|
|
|
#include <proto/ahi.h>
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
#include "morphos.h"
|
2002-04-04 12:54:27 +00:00
|
|
|
|
|
|
|
|
|
#define AHI_BUF_SIZE (8*1024)
|
|
|
|
|
|
|
|
|
|
struct SignalSemaphore ScummMusicThreadRunning;
|
2002-04-14 19:43:12 +00:00
|
|
|
|
struct SignalSemaphore ScummSoundThreadRunning;
|
2002-04-04 12:54:27 +00:00
|
|
|
|
|
|
|
|
|
static struct MsgPort *ahiPort = NULL;
|
|
|
|
|
static struct AHIRequest *ahiReq[ 2 ] = { NULL, NULL };
|
|
|
|
|
static UWORD ahiCurBuf = 0;
|
2002-04-14 19:43:12 +00:00
|
|
|
|
static bool ahiReqSent[ 2 ] = { false, false };
|
2002-04-04 12:54:27 +00:00
|
|
|
|
static BYTE ahiDevice = -1;
|
|
|
|
|
UBYTE ahiUnit = AHI_DEFAULT_UNIT;
|
|
|
|
|
static char *ahiBuf[ 2 ] = { NULL, NULL };
|
|
|
|
|
|
|
|
|
|
static struct MsgPort *ScummMidiPort = NULL;
|
|
|
|
|
struct IOMidiRequest *ScummMidiRequest = NULL;
|
2002-04-18 21:40:24 +00:00
|
|
|
|
static struct MsgPort *MusicTimerMsgPort = NULL;
|
|
|
|
|
struct timerequest *MusicTimerIORequest = NULL;
|
2002-04-04 12:54:27 +00:00
|
|
|
|
|
2002-04-18 21:40:24 +00:00
|
|
|
|
bool init_morphos_music( ULONG MidiUnit )
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
2002-05-26 16:37:41 +00:00
|
|
|
|
if( ScummMusicDriver && !stricmp( ScummMusicDriver, "-eamidi" ) ) // just as ugly as the line below ...
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
2002-05-26 16:37:41 +00:00
|
|
|
|
MidiUnit = ScummMidiUnit; // Ugly fix, but ...
|
|
|
|
|
ScummMidiPort = CreateMsgPort();
|
|
|
|
|
if( ScummMidiPort )
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
2002-05-26 16:37:41 +00:00
|
|
|
|
ScummMidiRequest = (struct IOMidiRequest *)CreateIORequest( ScummMidiPort, sizeof( struct IOMidiRequest ) );
|
|
|
|
|
if( ScummMidiRequest )
|
|
|
|
|
{
|
|
|
|
|
ScummMidiRequest->amr_Version = 2;
|
|
|
|
|
if( OpenDevice( "amidi.device", MidiUnit, (struct IORequest *)ScummMidiRequest, AMIDIF_MIDISERVER ) )
|
|
|
|
|
{
|
|
|
|
|
DeleteIORequest( (struct IORequest *)ScummMidiRequest );
|
|
|
|
|
DeleteMsgPort( ScummMidiPort );
|
|
|
|
|
ScummMidiRequest = NULL;
|
|
|
|
|
ScummMidiPort = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
|
|
|
|
DeleteMsgPort( ScummMidiPort );
|
|
|
|
|
ScummMidiPort = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-05-26 16:37:41 +00:00
|
|
|
|
|
|
|
|
|
if( !ScummMidiRequest )
|
2002-04-18 21:40:24 +00:00
|
|
|
|
{
|
2002-05-26 16:37:41 +00:00
|
|
|
|
warning( "Could not open AMidi - music will not play" );
|
|
|
|
|
return false;
|
2002-04-18 21:40:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-04 12:54:27 +00:00
|
|
|
|
|
2002-04-18 21:40:24 +00:00
|
|
|
|
MusicTimerMsgPort = CreateMsgPort();
|
|
|
|
|
if( MusicTimerMsgPort )
|
|
|
|
|
{
|
|
|
|
|
MusicTimerIORequest = (struct timerequest *)CreateIORequest( MusicTimerMsgPort, sizeof( struct timerequest ) );
|
|
|
|
|
if( MusicTimerIORequest )
|
2002-04-14 19:43:12 +00:00
|
|
|
|
{
|
2002-04-18 21:40:24 +00:00
|
|
|
|
if( OpenDevice( "timer.device", UNIT_MICROHZ, (struct IORequest *)MusicTimerIORequest, 0 ) )
|
|
|
|
|
{
|
|
|
|
|
DeleteIORequest( (struct IORequest *)MusicTimerIORequest );
|
|
|
|
|
DeleteMsgPort( MusicTimerMsgPort );
|
|
|
|
|
MusicTimerIORequest = NULL;
|
|
|
|
|
MusicTimerMsgPort = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DeleteMsgPort( MusicTimerMsgPort );
|
|
|
|
|
MusicTimerMsgPort = NULL;
|
2002-04-14 19:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-18 21:40:24 +00:00
|
|
|
|
if( !MusicTimerIORequest )
|
|
|
|
|
{
|
|
|
|
|
warning( "Could not open timer device - music will not play" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void exit_morphos_music()
|
|
|
|
|
{
|
|
|
|
|
if( ScummMidiRequest )
|
|
|
|
|
{
|
|
|
|
|
CloseDevice( (struct IORequest *)ScummMidiRequest );
|
|
|
|
|
DeleteIORequest( (struct IORequest *)ScummMidiRequest );
|
|
|
|
|
DeleteMsgPort( ScummMidiPort );
|
2002-04-04 12:54:27 +00:00
|
|
|
|
}
|
2002-04-18 21:40:24 +00:00
|
|
|
|
|
|
|
|
|
if( MusicTimerIORequest )
|
|
|
|
|
{
|
|
|
|
|
CloseDevice( (struct IORequest *)MusicTimerIORequest );
|
|
|
|
|
DeleteIORequest( (struct IORequest *)MusicTimerIORequest );
|
|
|
|
|
DeleteMsgPort( MusicTimerMsgPort );
|
|
|
|
|
}
|
2002-04-14 19:43:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-04 12:54:27 +00:00
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
static bool init_morphos_sound()
|
|
|
|
|
{
|
2002-04-04 12:54:27 +00:00
|
|
|
|
if( !(ahiPort = CreateMsgPort()) )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if( !(ahiReq[ 0 ] = (struct AHIRequest *)CreateIORequest( ahiPort, sizeof( struct AHIRequest ) )) )
|
|
|
|
|
{
|
|
|
|
|
DeleteMsgPort( ahiPort );
|
|
|
|
|
ahiPort = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !(ahiReq[ 1 ] = (struct AHIRequest *)AllocVec( sizeof( struct AHIRequest ), MEMF_ANY | MEMF_PUBLIC )) )
|
|
|
|
|
{
|
|
|
|
|
DeleteIORequest( ahiReq[ 0 ] );
|
|
|
|
|
DeleteMsgPort( ahiPort );
|
|
|
|
|
ahiReq[ 0 ] = NULL;
|
|
|
|
|
ahiPort = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !(ahiBuf[ 0 ] = (char *)AllocVec( 2*AHI_BUF_SIZE, MEMF_ANY | MEMF_PUBLIC )) )
|
|
|
|
|
{
|
|
|
|
|
FreeVec( ahiReq[ 1 ] );
|
|
|
|
|
DeleteIORequest( ahiReq[ 0 ] );
|
|
|
|
|
DeleteMsgPort( ahiPort );
|
|
|
|
|
ahiReq[ 0 ] = NULL;
|
|
|
|
|
ahiReq[ 1 ] = NULL;
|
|
|
|
|
ahiPort = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ahiBuf[ 1 ] = &ahiBuf[ 0 ][ AHI_BUF_SIZE ];
|
|
|
|
|
|
|
|
|
|
ahiReq[ 0 ]->ahir_Version = 4;
|
|
|
|
|
if( ahiDevice = OpenDevice( AHINAME, 0, (struct IORequest *)ahiReq[ 0 ], 0 ) )
|
|
|
|
|
{
|
|
|
|
|
FreeVec( ahiBuf[ 0 ] );
|
|
|
|
|
FreeVec( ahiReq[ 1 ] );
|
|
|
|
|
DeleteIORequest( ahiReq[ 0 ] );
|
|
|
|
|
DeleteMsgPort( ahiPort );
|
|
|
|
|
ahiBuf[ 0 ] = NULL;
|
|
|
|
|
ahiReq[ 0 ] = NULL;
|
|
|
|
|
ahiReq[ 1 ] = NULL;
|
|
|
|
|
ahiPort = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CopyMem( ahiReq[ 0 ], ahiReq[ 1 ], sizeof( struct AHIRequest ) );
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
ahiCurBuf = 0;
|
|
|
|
|
ahiReqSent[ 0 ] = FALSE;
|
|
|
|
|
ahiReqSent[ 1 ] = FALSE;
|
|
|
|
|
|
2002-04-04 12:54:27 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
static void exit_morphos_sound()
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
|
|
|
|
if( ahiReq[ 1 ] )
|
|
|
|
|
FreeVec( ahiReq[ 1 ] );
|
|
|
|
|
|
|
|
|
|
if( ahiReq[ 0 ] )
|
|
|
|
|
{
|
|
|
|
|
CloseDevice( (struct IORequest *)ahiReq[ 0 ] );
|
|
|
|
|
DeleteIORequest( ahiReq[ 0 ] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ahiBuf[ 0 ] )
|
|
|
|
|
FreeVec( (APTR)ahiBuf[ 0 ] );
|
|
|
|
|
|
|
|
|
|
if( ahiPort )
|
|
|
|
|
DeleteMsgPort( ahiPort );
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
int morphos_sound_thread( OSystem_MorphOS *syst, ULONG SampleType )
|
|
|
|
|
{
|
|
|
|
|
ULONG signals;
|
|
|
|
|
bool initialized;
|
|
|
|
|
|
|
|
|
|
ObtainSemaphore( &ScummSoundThreadRunning );
|
|
|
|
|
|
|
|
|
|
initialized = init_morphos_sound();
|
|
|
|
|
if( !initialized )
|
|
|
|
|
{
|
|
|
|
|
warning( "Sound could not be initialized. The game may hang at some point (press Ctrl-z then)." );
|
|
|
|
|
Wait( SIGBREAKF_CTRL_C );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for(;;)
|
|
|
|
|
{
|
|
|
|
|
while( !ahiReqSent[ ahiCurBuf ] || CheckIO( (struct IORequest *)ahiReq[ ahiCurBuf ] ) )
|
2002-04-04 12:54:27 +00:00
|
|
|
|
{
|
|
|
|
|
struct AHIRequest *req = ahiReq[ ahiCurBuf ];
|
|
|
|
|
UWORD ahiOtherBuf = !ahiCurBuf;
|
|
|
|
|
|
|
|
|
|
if( ahiReqSent[ ahiCurBuf ] )
|
|
|
|
|
WaitIO( (struct IORequest *)req );
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
syst->fill_sound( (byte *)ahiBuf[ ahiCurBuf ], AHI_BUF_SIZE );
|
|
|
|
|
|
2002-04-04 12:54:27 +00:00
|
|
|
|
req->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
|
|
|
|
|
req->ahir_Std.io_Command = CMD_WRITE;
|
|
|
|
|
req->ahir_Std.io_Data = ahiBuf[ ahiCurBuf ];
|
|
|
|
|
req->ahir_Std.io_Length = AHI_BUF_SIZE;
|
2002-04-14 19:43:12 +00:00
|
|
|
|
req->ahir_Type = SampleType;
|
2002-04-04 14:05:54 +00:00
|
|
|
|
req->ahir_Frequency = SAMPLES_PER_SEC;
|
2002-04-04 12:54:27 +00:00
|
|
|
|
req->ahir_Position = 0x8000;
|
|
|
|
|
req->ahir_Volume = 0x10000;
|
|
|
|
|
req->ahir_Link = (ahiReqSent[ ahiOtherBuf ] && !CheckIO( (struct IORequest *)ahiReq[ ahiOtherBuf ] )) ? ahiReq[ ahiOtherBuf ] : NULL;
|
|
|
|
|
SendIO( (struct IORequest *)req );
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
ahiReqSent[ ahiCurBuf ] = true;
|
2002-04-04 12:54:27 +00:00
|
|
|
|
ahiCurBuf = ahiOtherBuf;
|
|
|
|
|
}
|
2002-04-14 19:43:12 +00:00
|
|
|
|
|
|
|
|
|
signals = Wait( SIGBREAKF_CTRL_C | (1 << ahiPort->mp_SigBit) );
|
|
|
|
|
|
|
|
|
|
if( signals & SIGBREAKF_CTRL_C )
|
|
|
|
|
break;
|
2002-04-04 12:54:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
if( ahiReqSent[ ahiCurBuf ] )
|
|
|
|
|
{
|
|
|
|
|
AbortIO( (struct IORequest *)ahiReq[ ahiCurBuf ] );
|
|
|
|
|
WaitIO ( (struct IORequest *)ahiReq[ ahiCurBuf ] );
|
|
|
|
|
ahiReqSent[ ahiCurBuf ] = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ahiReqSent[ !ahiCurBuf ] )
|
|
|
|
|
{
|
|
|
|
|
AbortIO( (struct IORequest *)ahiReq[ !ahiCurBuf ] );
|
|
|
|
|
WaitIO ( (struct IORequest *)ahiReq[ !ahiCurBuf ] );
|
|
|
|
|
ahiReqSent[ !ahiCurBuf ] = false;
|
|
|
|
|
}
|
2002-04-04 12:54:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exit_morphos_sound();
|
|
|
|
|
|
2002-04-14 19:43:12 +00:00
|
|
|
|
ReleaseSemaphore( &ScummSoundThreadRunning );
|
|
|
|
|
RemTask( NULL );
|
2002-04-04 12:54:27 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|