A bit of apple sound chip support.
This commit is contained in:
parent
8a02128473
commit
eedf6880db
|
@ -191,20 +191,22 @@ OSStatus AudioBackEnd::SetupBuffers() {
|
|||
|
||||
|
||||
asbd.mFormatID = 0x6c70636d; // 'lpcm'
|
||||
asbd.mFormatFlags = (kAudioFormatFlagIsSignedInteger |
|
||||
kAudioFormatFlagIsBigEndian |
|
||||
kAudioFormatFlagIsPacked);
|
||||
asbd.mChannelsPerFrame = mNumChannels;
|
||||
asbd.mSampleRate = mSampleRate;
|
||||
|
||||
if(asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) {
|
||||
asbd.mBitsPerChannel = mBitsPerSample;
|
||||
} else if(asbd.mFormatFlags & kAudioFormatFlagIsFloat) {
|
||||
asbd.mBitsPerChannel = 32;
|
||||
if(mBitsPerSample == 16) {
|
||||
asbd.mFormatFlags = (kAudioFormatFlagIsSignedInteger |
|
||||
kAudioFormatFlagIsBigEndian |
|
||||
kAudioFormatFlagIsPacked);
|
||||
} else if(mBitsPerSample == 8) {
|
||||
asbd.mFormatFlags = kAudioFormatFlagIsPacked;
|
||||
} else {
|
||||
asbd.mBitsPerChannel = 0;
|
||||
asbd.mFormatFlags = kAudioFormatFlagsAreAllClear;
|
||||
}
|
||||
|
||||
asbd.mChannelsPerFrame = mNumChannels;
|
||||
|
||||
asbd.mSampleRate = mSampleRate;
|
||||
|
||||
asbd.mBitsPerChannel = mBitsPerSample;
|
||||
|
||||
asbd.mFramesPerPacket = 1;
|
||||
asbd.mBytesPerFrame = (asbd.mBitsPerChannel / 8) * asbd.mChannelsPerFrame;
|
||||
asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket;
|
||||
|
@ -269,7 +271,6 @@ OSStatus AudioBackEnd::OutputProc(void *inRefCon,
|
|||
This->mAudioBufferReadIndex += bytesToCopy;
|
||||
}
|
||||
|
||||
|
||||
while(This->mFramesProcessed >= This->mBufferSizeFrames) {
|
||||
This->mFramesProcessed -= This->mBufferSizeFrames;
|
||||
if(This->mCallback != NULL) {
|
||||
|
@ -289,19 +290,28 @@ UInt32 AudioBackEnd::BufferSizeFrames() {
|
|||
return mBufferSizeFrames;
|
||||
}
|
||||
|
||||
int AudioBackEnd::sendAudioBuffer(void *buffer, int numFrames) {
|
||||
int AudioBackEnd::sendAudioBuffer(const void *buffer, int numFrames) {
|
||||
UInt8 *dstBuffer;
|
||||
int totalBytes;
|
||||
|
||||
int framesWritten;
|
||||
|
||||
if(numFrames > mBufferSizeFrames) {
|
||||
framesWritten = mBufferSizeFrames;
|
||||
} else {
|
||||
framesWritten = numFrames;
|
||||
}
|
||||
|
||||
mAudioBufferWriteIndex += (mAudioBufferSize / 2);
|
||||
mAudioBufferWriteIndex &= (mAudioBufferSize - 1);
|
||||
|
||||
dstBuffer = &mAudioBuffer[mAudioBufferWriteIndex];
|
||||
totalBytes = mBytesPerFrame * numFrames;
|
||||
totalBytes = mBytesPerFrame * framesWritten;
|
||||
memcpy(dstBuffer, buffer, totalBytes);
|
||||
|
||||
dstBuffer += totalBytes;
|
||||
bzero(dstBuffer, (mBufferSizeFrames * mBytesPerFrame) - totalBytes);
|
||||
if(framesWritten < mBufferSizeFrames) {
|
||||
dstBuffer += totalBytes;
|
||||
bzero(dstBuffer, (mBufferSizeFrames * mBytesPerFrame) - totalBytes);
|
||||
}
|
||||
|
||||
return numFrames;
|
||||
return framesWritten;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class AudioBackEnd {
|
|||
Boolean IsRunning();
|
||||
void setCallback(playthruCallback func, void *arg);
|
||||
UInt32 BufferSizeFrames();
|
||||
int sendAudioBuffer(void *buffer, int numFrames);
|
||||
int sendAudioBuffer(const void *buffer, int numFrames);
|
||||
private:
|
||||
OSStatus SetupGraph();
|
||||
OSStatus CallbackSetup();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "AudioBackEnd.h"
|
||||
#include "MacOSX_sound_if.h"
|
||||
|
||||
|
@ -77,7 +78,7 @@ unsigned int OSXsoundOutput::bufferSizeFrames() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int OSXsoundOutput::sendAudioBuffer(void *buffer, int numFrames) {
|
||||
int OSXsoundOutput::sendAudioBuffer(const void *buffer, int numFrames) {
|
||||
if(player != NULL) {
|
||||
return player->sendAudioBuffer(buffer, numFrames);
|
||||
}
|
||||
|
|
|
@ -37,5 +37,5 @@ class OSXsoundOutput {
|
|||
int putBuffer(void *buffer, int numSamples);
|
||||
void setCallback(audioCallback fn);
|
||||
unsigned int bufferSizeFrames();
|
||||
int sendAudioBuffer(void *buffer, int numFrames);
|
||||
int sendAudioBuffer(const void *buffer, int numFrames);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,9 @@ AC_ARG_ENABLE(macosx-gui, [ --enable-macosx-gui enable Mac OS X GUI [def
|
|||
dnl Mac OS X Sound
|
||||
AC_ARG_ENABLE(macosx-sound, [ --enable-macosx-sound enable Mac OS X Sound [default=no]], [WANT_MACOSX_SOUND=$enableval], [WANT_MACOSX_SOUND=no])
|
||||
|
||||
dnl Apple Sound Chip Emulation
|
||||
AC_ARG_ENABLE(asc-emu, [ --enable-asc-emu enable Apple Sound Chip emulation [default=no]], [WANT_ASC_EMU=$enableval], [WANT_ASC_EMU=no])
|
||||
|
||||
dnl Mac OS X etherhelper support
|
||||
AC_ARG_ENABLE(macosx-etherhelper, [ --enable-macosx-etherhelper enable Mac OS X Sound [default=no]], [WANT_MACOSX_ETHERHELPER=$enableval], [WANT_MACOSX_ETHERHELPER=no])
|
||||
|
||||
|
@ -741,6 +744,11 @@ if [[ "x$WANT_MACOSX_ETHERHELPER" = "xyes" ]]; then
|
|||
AC_DEFINE(ENABLE_MACOSX_ETHERHELPER, 1, [Define if supporting "etherhelper" network device.])
|
||||
fi
|
||||
|
||||
if [[ "x$WANT_ASC_EMU" = "xyes" ]]; then
|
||||
AC_DEFINE(ENABLE_ASC_EMU, 1, [Define if supporting Apple Sound Chip Emulation.])
|
||||
AUDIOSRC+=" ../MacOSX/asc.cpp"
|
||||
fi
|
||||
|
||||
AC_SUBST(MACOSX_ETHERHELPER, $WANT_MACOSX_ETHERHELPER)
|
||||
|
||||
dnl SDL overrides
|
||||
|
|
|
@ -251,12 +251,34 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||
|
||||
// Setup fake ASC registers
|
||||
if (ROMVersion == ROM_VERSION_32) {
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
uae_u32 paramBlk;
|
||||
uae_u32 ioNamePtr;
|
||||
uae_u32 namePtr;
|
||||
|
||||
r.d[0] = 100;
|
||||
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
|
||||
|
||||
paramBlk = r.a[0]; // pointer to a ParamBlockRec
|
||||
ioNamePtr = paramBlk + 18; // Pointer to ioNamePtr field
|
||||
namePtr = r.a[0] + 80; // Storage for ".sound" string
|
||||
|
||||
memcpy(Mac2HostAddr(namePtr), "\006.sound", 7);
|
||||
*((uae_u32*)Mac2HostAddr(ioNamePtr)) = ntohl(namePtr);
|
||||
|
||||
Execute68kTrap(0xa000, &r); // PBOpenSync()
|
||||
|
||||
r.a[0] = paramBlk;
|
||||
Execute68kTrap(0x101f, &r); // DisposePtr();
|
||||
|
||||
#else
|
||||
r.d[0] = 0x1000;
|
||||
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
|
||||
uint32 asc_regs = r.a[0];
|
||||
D(bug("ASC registers at %08lx\n", asc_regs));
|
||||
WriteMacInt8(asc_regs + 0x800, 0x0f); // Set ASC version number
|
||||
WriteMacInt32(0xcc0, asc_regs); // Set ASCBase
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -264,3 +264,211 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
|
|||
r->a[i] = m68k_areg(regs, i);
|
||||
quit_program = false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
#include <asc.h>
|
||||
|
||||
static uae_u8 ASCRegs[0x2000] = {0};
|
||||
static const int fifoCapacity = 2048;
|
||||
static uint32 fifoInA = 0;
|
||||
static uint32 fifoInB = 0;
|
||||
static uint32 fifoWriteA = 0;
|
||||
static uint32 fifoWriteB = 0;
|
||||
static uint32 fifoOutA = 0;
|
||||
static uint32 fifoOutB = 0;
|
||||
static uae_u8 fifoA[fifoCapacity];
|
||||
static uae_u8 fifoB[fifoCapacity];
|
||||
static int32 ascBufferSize = -1;
|
||||
static int soundRunning = 0;
|
||||
static int soundStop = 0;
|
||||
static uae_u8 zeros[1024] = {0};
|
||||
|
||||
extern uae_u32 io_read(uaecptr addr, int width_bits) {
|
||||
if((addr & 0x00ff000) == 0x0014000) {
|
||||
// Apple Sound Chip
|
||||
|
||||
uaecptr offset = addr & 0x00000fff;
|
||||
uae_u32 val;
|
||||
|
||||
if(offset < 0x400) {
|
||||
/* Read of FIFO A. */
|
||||
} else if(offset < 0x800) {
|
||||
/* Read of Fifo B */
|
||||
} else {
|
||||
if(width_bits > 8) {
|
||||
fprintf(stderr,
|
||||
"Unexpected ASC read width %d\n", width_bits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(offset) {
|
||||
case 0x800:
|
||||
// VERSION
|
||||
return 0;
|
||||
|
||||
case 0x804:
|
||||
// FIFO IRQ STATUS
|
||||
val = 0;
|
||||
if((fifoInA - fifoWriteA) >= 0x200) {
|
||||
val = 0x1;
|
||||
}
|
||||
if((fifoInA - fifoWriteA) >= 0x400) {
|
||||
val = 0x2;
|
||||
}
|
||||
|
||||
val |= (val << 2);
|
||||
return val;
|
||||
|
||||
default:
|
||||
return ASCRegs[offset];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
extern void io_write(uaecptr addr, uae_u32 b, int width_bits) {
|
||||
static int downsample = 0;
|
||||
|
||||
if((addr & 0x00ff000) == 0x0014000) {
|
||||
if(soundStop) {
|
||||
asc_stop();
|
||||
soundRunning = 0;
|
||||
soundStop = 0;
|
||||
}
|
||||
|
||||
// Apple Sound Chip
|
||||
if(width_bits > 8) {
|
||||
fprintf(stderr,
|
||||
"Unexpected ASC read width %d, addr 0x%08x\n",
|
||||
width_bits, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
uaecptr offset = addr & 0x00000fff;
|
||||
uae_u32 val;
|
||||
|
||||
if(offset < 0x400) {
|
||||
if(ASCRegs[0x801] != 2) {
|
||||
static int counter = 0;
|
||||
static int32 depthA = fifoInA - fifoWriteA;
|
||||
|
||||
// FIFO Mode
|
||||
if(depthA == fifoCapacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(ASCRegs[0x807] == 0) {
|
||||
downsample += 22050;
|
||||
if(downsample >= 22257) {
|
||||
downsample -= 22257;
|
||||
fifoA[(fifoInA++) % fifoCapacity] = b;
|
||||
}
|
||||
} else {
|
||||
fifoA[(fifoInA++) % fifoCapacity] = b;
|
||||
}
|
||||
|
||||
if(soundRunning == 0) {
|
||||
depthA = fifoInA - fifoWriteA;
|
||||
|
||||
if(depthA >= 1024) {
|
||||
if(ASCRegs[0x807] == 3) {
|
||||
asc_init(44100);
|
||||
} else {
|
||||
asc_init(22050);
|
||||
}
|
||||
ascBufferSize = asc_get_buffer_size();
|
||||
soundRunning = 1;
|
||||
|
||||
while(((fifoWriteA - fifoOutA) < (ascBufferSize*2)) &&
|
||||
((fifoInA - fifoWriteA) > ascBufferSize) ){
|
||||
asc_process_samples(&fifoA[fifoWriteA % fifoCapacity],
|
||||
ascBufferSize);
|
||||
fifoWriteA += ascBufferSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Non fifo mode write
|
||||
}
|
||||
} else if(offset < 0x800) {
|
||||
} else {
|
||||
switch(offset) {
|
||||
case 0x801:
|
||||
// MODE
|
||||
// 1 = FIFO mode, 2 = wavetable mode
|
||||
ASCRegs[0x801] = b & 0x03;
|
||||
asc_stop();
|
||||
soundRunning = 0;
|
||||
break;
|
||||
|
||||
case 0x802:
|
||||
// CONTROL
|
||||
// bit 0: analog or PWM output
|
||||
// bit 1: stereo/mono
|
||||
// bit 7: processing time exceeded
|
||||
ASCRegs[0x802] = b;
|
||||
break;
|
||||
|
||||
case 0x803:
|
||||
// FIFO Mode
|
||||
if(b & 0x80) {
|
||||
downsample = 0;
|
||||
asc_stop();
|
||||
soundRunning = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x804:
|
||||
// fifo status
|
||||
break;
|
||||
|
||||
case 0x805:
|
||||
// wavetable control
|
||||
break;
|
||||
|
||||
case 0x806:
|
||||
// Volume
|
||||
break;
|
||||
|
||||
case 0x807:
|
||||
// Clock rate 0 = 22257, 2 = 22050, 3 = 44100
|
||||
downsample = 0;
|
||||
ASCRegs[0x807] = b;
|
||||
break;
|
||||
|
||||
case 0x80f:
|
||||
printf("ASC Test\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void asc_callback() {
|
||||
if(zeros[0] == 0) {
|
||||
memset(zeros, 128, sizeof(zeros));
|
||||
}
|
||||
if(soundRunning == 0) {
|
||||
asc_process_samples(zeros, ascBufferSize);
|
||||
return;
|
||||
}
|
||||
|
||||
fifoOutA += ascBufferSize;
|
||||
|
||||
if((fifoInA - fifoWriteA) >= ascBufferSize) {
|
||||
asc_process_samples(&fifoA[fifoWriteA % fifoCapacity], ascBufferSize);
|
||||
fifoWriteA += ascBufferSize;
|
||||
} else {
|
||||
static int ucount = 0;
|
||||
asc_process_samples(zeros, ascBufferSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#ifndef UAE_MEMORY_H
|
||||
#define UAE_MEMORY_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
|
||||
|
||||
/* Enabling this adds one additional native memory reference per 68k memory
|
||||
|
@ -124,6 +128,9 @@ extern uintptr MEMBaseDiff;
|
|||
#endif
|
||||
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
extern uae_u32 io_read(uaecptr addr, int width_bits);
|
||||
extern void io_write(uaecptr addr, uae_u32 b, int width_bits);
|
||||
|
||||
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)MEMBaseDiff + addr;
|
||||
|
@ -134,31 +141,63 @@ static __inline__ uae_u32 do_get_virtual_address(uae_u8 *addr)
|
|||
}
|
||||
static __inline__ uae_u32 get_long(uaecptr addr)
|
||||
{
|
||||
if(addr & 0x40000000) {
|
||||
return io_read(addr, 32);
|
||||
}
|
||||
|
||||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||
{
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
if(addr & 0x40000000) {
|
||||
return io_read(addr, 16);
|
||||
}
|
||||
#endif
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||
{
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
if(addr & 0x40000000) {
|
||||
return io_read(addr, 8);
|
||||
}
|
||||
#endif
|
||||
return do_get_mem_byte(m);
|
||||
}
|
||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
if(addr & 0x40000000) {
|
||||
io_write(addr, l, 32);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
if(addr & 0x40000000) {
|
||||
io_write(addr, w, 16);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
#ifdef ENABLE_ASC_EMU
|
||||
if(addr & 0x40000000) {
|
||||
io_write(addr, b, 8);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
do_put_mem_byte(m, b);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue