/* MikMod sound library (c) 1998-2014 Miodrag Vallat and others -
* see AUTHORS file for a complete list.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* Driver for output to native Amiga AHI device:
* Written by Szilárd Biró
, loosely based
* on an old AOS4 version by Fredrik Wikstrom
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mikmod_internals.h"
#ifdef DRV_AHI
#ifdef __amigaos4__
#define SHAREDMEMFLAG MEMF_SHARED
#define __USE_INLINE__
#else
#define SHAREDMEMFLAG MEMF_PUBLIC
#endif
#include
#include
#define BUFFERSIZE (4 << 10)
static struct MsgPort *AHImp = NULL;
static struct AHIRequest *AHIReq[2] = { NULL, NULL };
static int active = 0;
static SBYTE *AHIBuf[2] = { NULL, NULL };
static BOOL signed8 = 0;
static void closeLibs(void) { /* close ahi */
if (AHIReq[1]) {
AHIReq[0]->ahir_Link = NULL; /* in case we are linked to req[0] */
if (!CheckIO((struct IORequest *) AHIReq[1])) {
AbortIO((struct IORequest *) AHIReq[1]);
WaitIO((struct IORequest *) AHIReq[1]);
}
FreeVec(AHIReq[1]);
AHIReq[1] = NULL;
}
if (AHIReq[0])
{
if (!CheckIO((struct IORequest *) AHIReq[0])) {
AbortIO((struct IORequest *) AHIReq[0]);
WaitIO((struct IORequest *) AHIReq[0]);
}
if (AHIReq[0]->ahir_Std.io_Device) {
CloseDevice((struct IORequest *) AHIReq[0]);
AHIReq[0]->ahir_Std.io_Device = NULL;
}
DeleteIORequest((struct IORequest *) AHIReq[0]);
AHIReq[0] = NULL;
}
if (AHImp) {
DeleteMsgPort(AHImp);
AHImp = NULL;
}
if (AHIBuf[0]) {
FreeVec(AHIBuf[0]);
AHIBuf[0] = NULL;
}
if (AHIBuf[1]) {
FreeVec(AHIBuf[1]);
AHIBuf[1] = NULL;
}
}
static BOOL AHI_IsThere(void) {
return 1;
}
static int AHI_Init(void) {
AHImp = CreateMsgPort();
if (AHImp) {
AHIReq[0] = (struct AHIRequest *)CreateIORequest(AHImp, sizeof(struct AHIRequest));
if (AHIReq[0]) {
AHIReq[0]->ahir_Version = 4;
AHIReq[1] = AllocVec(sizeof(struct AHIRequest), SHAREDMEMFLAG);
if (AHIReq[1]) {
if (!OpenDevice(AHINAME, AHI_DEFAULT_UNIT, (struct IORequest *)AHIReq[0], 0)) {
/*AHIReq[0]->ahir_Std.io_Message.mn_Node.ln_Pri = 0;*/
AHIReq[0]->ahir_Std.io_Command = CMD_WRITE;
AHIReq[0]->ahir_Std.io_Data = NULL;
AHIReq[0]->ahir_Std.io_Offset = 0;
AHIReq[0]->ahir_Frequency = md_mixfreq;
AHIReq[0]->ahir_Type = (md_mode & DMODE_16BITS)?
((md_mode & DMODE_STEREO)? AHIST_S16S : AHIST_M16S) :
((md_mode & DMODE_STEREO)? AHIST_S8S : AHIST_M8S );
AHIReq[0]->ahir_Volume = 0x10000;
AHIReq[0]->ahir_Position = 0x8000;
CopyMem(AHIReq[0], AHIReq[1], sizeof(struct AHIRequest));
AHIBuf[0] = AllocVec(BUFFERSIZE, SHAREDMEMFLAG | MEMF_CLEAR);
if (AHIBuf[0]) {
AHIBuf[1] = AllocVec(BUFFERSIZE, SHAREDMEMFLAG | MEMF_CLEAR);
if (AHIBuf[1]) {
signed8 = (md_mode & DMODE_16BITS)? 0 : 1;
return VC_Init();
}
}
}
}
}
}
closeLibs();
_mm_errno = MMERR_OPENING_AUDIO;
return 1;
}
static void AHI_Exit(void) {
VC_Exit();
closeLibs();
}
static void AHI_Update(void) {
ULONG numBytes;
if (AHIReq[active]->ahir_Std.io_Data) {
WaitIO((struct IORequest *) AHIReq[active]);
AHIReq[active]->ahir_Std.io_Data = NULL;
}
numBytes = VC_WriteBytes(AHIBuf[active], BUFFERSIZE);
if (signed8) { /* convert u8 data to s8 */
ULONG i = 0;
for (; i < numBytes; ++i)
AHIBuf[active][i] -= 128;
}
AHIReq[active]->ahir_Std.io_Data = AHIBuf[active];
AHIReq[active]->ahir_Std.io_Length = numBytes;
AHIReq[active]->ahir_Link = !CheckIO((struct IORequest *) AHIReq[active ^ 1]) ? AHIReq[active ^ 1] : NULL;
SendIO((struct IORequest *)AHIReq[active]);
active ^= 1;
}
MIKMODAPI MDRIVER drv_ahi = {
NULL,
"AHI",
"Native AHI Amiga Output driver",
0,255,
"AHI",
NULL,
NULL,
AHI_IsThere,
VC_SampleLoad,
VC_SampleUnload,
VC_SampleSpace,
VC_SampleLength,
AHI_Init,
AHI_Exit,
NULL,
VC_SetNumVoices,
VC_PlayStart,
VC_PlayStop,
AHI_Update,
NULL,
VC_VoiceSetVolume,
VC_VoiceGetVolume,
VC_VoiceSetFrequency,
VC_VoiceGetFrequency,
VC_VoiceSetPanning,
VC_VoiceGetPanning,
VC_VoicePlay,
VC_VoiceStop,
VC_VoiceStopped,
VC_VoiceGetPosition,
VC_VoiceRealVolume
};
#else
MISSING(drv_ahi);
#endif
/* ex:set ts=8: */