A bit of apple sound chip support.

This commit is contained in:
Dan Sumorok 2013-06-09 16:27:24 -04:00
parent 8a02128473
commit eedf6880db
8 changed files with 309 additions and 21 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}