Added Wiimote speaker support by hack patching out the IsBusyStream function using HLE. DSP LLE is required to process the speaker data. This commit works with real Wiimotes. I have added the code to decode the audio from the emulated wiimotes but have not added the code to output their audio to the PC speakers.
* Added HLE function IsBusyStream which signals that the Wiimote is ready to accept speaker data. This function is not a conversion from the real PPC code. It a simple function that returns the "ready" status after being polled. * Added code to find and patch HLE functions on boot * Added 4bit Yamaha ADPCM decoder from the ffmpeg project * Removed some test code * Added some copyright notices Fixes issue 438. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7225 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f2a086c44c
commit
d92aad4430
Binary file not shown.
|
@ -47,6 +47,7 @@
|
|||
#include "../ConfigManager.h"
|
||||
#include "VolumeCreator.h" // DiscIO
|
||||
#include "NANDContentLoader.h"
|
||||
#include "CommonPaths.h"
|
||||
|
||||
void CBoot::Load_FST(bool _bIsWii)
|
||||
{
|
||||
|
@ -217,6 +218,19 @@ bool CBoot::BootUp()
|
|||
EmulatedBS2(_StartupPara.bWii);
|
||||
}
|
||||
|
||||
// Scan for common HLE functions
|
||||
if (!_StartupPara.bEnableDebugging)
|
||||
{
|
||||
PPCAnalyst::FindFunctions(0x80000000, 0x81800000, &g_symbolDB);
|
||||
SignatureDB db;
|
||||
if (db.Load((File::GetSysDirectory() + TOTALDB).c_str()))
|
||||
{
|
||||
db.Apply(&g_symbolDB);
|
||||
}
|
||||
HLE::PatchFunctions();
|
||||
g_symbolDB.Clear();
|
||||
}
|
||||
|
||||
/* Try to load the symbol map if there is one, and then scan it for
|
||||
and eventually replace code */
|
||||
if (LoadMapFromFilename(_StartupPara.m_strFilename, gameID))
|
||||
|
|
|
@ -68,6 +68,7 @@ static const SPatch OSPatches[] =
|
|||
|
||||
// wii only
|
||||
//{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction },
|
||||
{ "IsBusyStrm_", HLE_Misc::IsBusyStream },
|
||||
|
||||
// Super Monkey Ball - no longer needed.
|
||||
//{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine },
|
||||
|
@ -91,7 +92,7 @@ static const SPatch OSPatches[] =
|
|||
// { "GXPeekARGB", HLE_Misc::GXPeekARGB},
|
||||
|
||||
// Name doesn't matter, installed in CBoot::BootUp()
|
||||
{ "HBReload", HLE_Misc::HBReload },
|
||||
{ "HBReload", HLE_Misc::HBReload },
|
||||
};
|
||||
|
||||
static const SPatch OSBreakPoints[] =
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../HW/Memmap.h"
|
||||
#include "../Host.h"
|
||||
#include "CoreTiming.h"
|
||||
|
||||
namespace HLE_Misc
|
||||
{
|
||||
|
@ -282,4 +283,28 @@ void HBReload()
|
|||
Host_Message(WM_USER_STOP);
|
||||
}
|
||||
|
||||
u8 isBusyPoll = 0;
|
||||
|
||||
// Hack: Wiimotes are never too busy to process speaker data
|
||||
void IsBusyStream()
|
||||
{
|
||||
isBusyPoll++;
|
||||
|
||||
// Signal that the wiimote is idle for a few cycles, allowing sound
|
||||
// to be processed.
|
||||
if (isBusyPoll < 5)
|
||||
{
|
||||
// Wiimote is idle
|
||||
GPR(3) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wiimote is busy
|
||||
GPR(3) = 1;
|
||||
if (isBusyPoll >= 8)
|
||||
isBusyPoll = 0;
|
||||
}
|
||||
NPC = LR;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace HLE_Misc
|
|||
void FZ_sqrt_internal();
|
||||
void FZ_rsqrt_internal();
|
||||
void HBReload();
|
||||
void IsBusyStream();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Adapted from in_cube by hcs & destop
|
||||
|
||||
#include "StreamADPCM.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Adapted from in_cube by hcs & destop
|
||||
|
||||
#ifndef _STREAMADPCM_H
|
||||
|
|
|
@ -140,9 +140,7 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
|
|||
break;
|
||||
|
||||
case WM_WRITE_SPEAKER_DATA : // 0x18
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
SpeakerData((wm_speaker_data*)sr->data);
|
||||
#endif
|
||||
Wiimote::SpeakerData((wm_speaker_data*)sr->data);
|
||||
// TODO: Does this need an ack?
|
||||
return; // no ack
|
||||
break;
|
||||
|
@ -150,11 +148,9 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
|
|||
case WM_SPEAKER_MUTE : // 0x19
|
||||
//INFO_LOG(WIIMOTE, "WM Speaker Mute: 0x%02x", sr->data[0]);
|
||||
//PanicAlert( "WM Speaker Mute: %d", sr->data[0] & 0x04 );
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// testing
|
||||
if (sr->data[0] & 0x04)
|
||||
memset(&m_channel_status, 0, sizeof(m_channel_status));
|
||||
#endif
|
||||
//if (sr->data[0] & 0x04)
|
||||
// memset(&m_channel_status, 0, sizeof(m_channel_status));
|
||||
m_speaker_mute = sr->enable;
|
||||
if (false == sr->ack)
|
||||
return;
|
||||
|
|
|
@ -1,38 +1,95 @@
|
|||
#include "WiimoteEmu.h"
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "WiimoteEmu.h"
|
||||
#include <fstream>
|
||||
|
||||
// Yamaha ADPCM decoder code based on The ffmpeg Project (Copyright (c) 2001-2003)
|
||||
|
||||
typedef struct ADPCMChannelStatus
|
||||
{
|
||||
int predictor;
|
||||
int step;
|
||||
} ADPCMChannelStatus;
|
||||
|
||||
static const int yamaha_difflookup[] = {
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9, -11, -13, -15
|
||||
};
|
||||
|
||||
static const int yamaha_indexscale[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
230, 230, 230, 230, 307, 409, 512, 614
|
||||
};
|
||||
|
||||
static u16 av_clip_int16(int a)
|
||||
{
|
||||
if ((a+32768) & ~65535) return (a>>31) ^ 32767;
|
||||
else return a;
|
||||
}
|
||||
|
||||
static int av_clip(int a, int amin, int amax)
|
||||
{
|
||||
if (a < amin) return amin;
|
||||
else if (a > amax) return amax;
|
||||
else return a;
|
||||
}
|
||||
|
||||
static s16 adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned char nibble)
|
||||
{
|
||||
if(!c->step) {
|
||||
c->predictor = 0;
|
||||
c->step = 127;
|
||||
}
|
||||
|
||||
c->predictor += (c->step * yamaha_difflookup[nibble]) / 8;
|
||||
c->predictor = av_clip_int16(c->predictor);
|
||||
c->step = (c->step * yamaha_indexscale[nibble]) >> 8;
|
||||
c->step = av_clip(c->step, 127, 24567);
|
||||
return c->predictor;
|
||||
}
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
ADPCMChannelStatus cs;
|
||||
|
||||
void Wiimote::SpeakerData(wm_speaker_data* sd)
|
||||
{
|
||||
SoundBuffer sb;
|
||||
sb.samples = new s16[sd->length * 2];
|
||||
s16 samples[40];
|
||||
u16 sampleRate = 6000000 / Common::swap16(m_reg_speaker.sample_rate);
|
||||
|
||||
s16* s = sb.samples;
|
||||
const u8* const e = sd->data + sd->length;
|
||||
for ( const u8* i = sd->data; i<e; ++i )
|
||||
if (m_reg_speaker.format == 0x40)
|
||||
{
|
||||
*s++ = NGCADPCM::ADPDecodeSample(*i & 0x0F, sd->data[0] & 0x0F, &m_channel_status.hist1p, &m_channel_status.hist2p);
|
||||
*s++ = NGCADPCM::ADPDecodeSample(*i >> 4, sd->data[0] >> 4, &m_channel_status.hist1p, &m_channel_status.hist2p);
|
||||
// 8 bit PCM
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
samples[i] = (s16)(s8)sd->data[i];
|
||||
}
|
||||
}
|
||||
else if (m_reg_speaker.format == 0x00)
|
||||
{
|
||||
// 4 bit Yamaha ADPCM
|
||||
// TODO: The first byte of the source data = length?
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
samples[i * 2] = adpcm_yamaha_expand_nibble(&cs, sd->data[i] & 0x0F);
|
||||
samples[i * 2 + 1] = adpcm_yamaha_expand_nibble(&cs, (sd->data[i] >> 4) & 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
alGenBuffers(1, &sb.buffer);
|
||||
// TODO make this not always 3000
|
||||
alBufferData(sb.buffer, AL_FORMAT_MONO16, sb.samples, (sd->length * sizeof(short) * 2), 3360);
|
||||
// testing
|
||||
//alBufferData(sb.buffer, AL_FORMAT_MONO16, sb.samples, (sd->length * sizeof(short) * 2), 48000/m_reg_speaker->sample_rate);
|
||||
alSourceQueueBuffers(m_audio_source, 1, &sb.buffer);
|
||||
|
||||
ALint state;
|
||||
alGetSourcei(m_audio_source, AL_SOURCE_STATE, &state);
|
||||
if (AL_PLAYING != state)
|
||||
alSourcePlay(m_audio_source);
|
||||
|
||||
m_audio_buffers.push(sb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Attachment/Classic.h"
|
||||
#include "Attachment/Nunchuk.h"
|
||||
|
@ -282,32 +298,6 @@ Wiimote::Wiimote( const unsigned int index )
|
|||
m_options->settings.push_back(new ControlGroup::Setting(_trans("Background Input"), false));
|
||||
m_options->settings.push_back(new ControlGroup::Setting(_trans("Sideways Wiimote"), false));
|
||||
m_options->settings.push_back(new ControlGroup::Setting(_trans("Upright Wiimote"), false));
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// set up speaker stuff
|
||||
// this doesnt belong here
|
||||
|
||||
// TODO: i never clean up any of this audio stuff
|
||||
|
||||
if (0 == m_index) // very dumb
|
||||
{
|
||||
ALCdevice* pDevice;
|
||||
ALchar DeviceName[] = "DirectSound3D";
|
||||
pDevice = alcOpenDevice(DeviceName);
|
||||
ALCcontext* pContext;
|
||||
pContext = alcCreateContext(pDevice, NULL);
|
||||
alcMakeContextCurrent(pContext);
|
||||
}
|
||||
|
||||
alListener3f(AL_POSITION, 0.0, 0.0, 0.0);
|
||||
alListener3f(AL_VELOCITY, 0.0, 0.0, 0.0);
|
||||
alListener3f(AL_DIRECTION, 0.0, 0.0, 0.0);
|
||||
|
||||
alGenSources(1, &m_audio_source);
|
||||
alSourcef(m_audio_source, AL_PITCH, 1.0);
|
||||
alSourcef(m_audio_source, AL_GAIN, 1.0);
|
||||
alSourcei(m_audio_source, AL_LOOPING, false);
|
||||
#endif
|
||||
|
||||
// --- reset eeprom/register/values to default ---
|
||||
Reset();
|
||||
|
@ -634,36 +624,6 @@ void Wiimote::Update()
|
|||
if (Step())
|
||||
return;
|
||||
|
||||
// ----speaker----
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
|
||||
ALint processed = 0;
|
||||
alGetSourcei(m_audio_source, AL_BUFFERS_PROCESSED, &processed);
|
||||
|
||||
while (processed--)
|
||||
{
|
||||
//PanicAlert("Buffer Processed");
|
||||
alSourceUnqueueBuffers(m_audio_source, 1, &m_audio_buffers.front().buffer);
|
||||
alDeleteBuffers(1, &m_audio_buffers.front().buffer);
|
||||
delete[] m_audio_buffers.front().samples;
|
||||
m_audio_buffers.pop();
|
||||
}
|
||||
|
||||
// testing speaker crap
|
||||
//m_rumble->controls[0]->control_ref->State( m_speaker_data.size() > 0 );
|
||||
//if ( m_speaker_data.size() )
|
||||
//m_speaker_data.pop();
|
||||
|
||||
//while ( m_speaker_data.size() )
|
||||
//{
|
||||
// std::ofstream file;
|
||||
// file.open( "test.pcm", std::ios::app | std::ios::out | std::ios::binary );
|
||||
// file.put(m_speaker_data.front());
|
||||
// file.close();
|
||||
// m_speaker_data.pop();
|
||||
//}
|
||||
#endif
|
||||
|
||||
u8 data[MAX_PAYLOAD];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _CONEMU_WIIMOTE_H_
|
||||
#define _CONEMU_WIIMOTE_H_
|
||||
|
||||
//#define USE_WIIMOTE_EMU_SPEAKER
|
||||
|
||||
//#include <Core.h>
|
||||
//#include <HW/StreamADPCM.h>
|
||||
// just used to get the OpenAL includes :p
|
||||
//#include <OpenALStream.h>
|
||||
|
||||
#include "../../Core.h"
|
||||
|
||||
#include "ControllerEmu.h"
|
||||
|
@ -123,10 +133,7 @@ private:
|
|||
void ReadData(const wm_read_data* const rd);
|
||||
void WriteData(const wm_write_data* const wd);
|
||||
void SendReadDataReply(ReadRequest& _request);
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
void SpeakerData(wm_speaker_data* sd);
|
||||
#endif
|
||||
|
||||
// control groups
|
||||
Buttons *m_buttons, *m_dpad, *m_shake;
|
||||
|
@ -165,21 +172,6 @@ private:
|
|||
// maybe read requests cancel any current requests
|
||||
std::queue< ReadRequest > m_read_requests;
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// speaker stuff
|
||||
struct SoundBuffer
|
||||
{
|
||||
s16* samples;
|
||||
ALuint buffer;
|
||||
};
|
||||
std::queue<SoundBuffer> m_audio_buffers;
|
||||
ALuint m_audio_source;
|
||||
struct
|
||||
{
|
||||
int hist1p, hist2p;
|
||||
} m_channel_status;
|
||||
#endif
|
||||
|
||||
wiimote_key m_ext_key;
|
||||
|
||||
u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
|
||||
|
|
Loading…
Reference in New Issue