Attempt to fix a sound problem that could appear in SSBM, Battle Stadium DON and perhaps other games. Please report any side effects.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@785 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2008-10-06 18:40:34 +00:00
parent 037e3d0442
commit f4b9a22324
4 changed files with 227 additions and 68 deletions

View File

@ -26,6 +26,9 @@
// externals
extern int gUpdFreq;
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
// =======================================================================================
// Declare events
@ -33,6 +36,9 @@ BEGIN_EVENT_TABLE(CDebugger,wxDialog)
EVT_CLOSE(CDebugger::OnClose)
EVT_BUTTON(ID_UPD,CDebugger::OnUpdate)
EVT_CHECKBOX(IDC_CHECK2,CDebugger::ShowHideConsole)
EVT_CHECKBOX(IDC_CHECK3,CDebugger::SSBM)
EVT_CHECKBOX(IDC_CHECK4,CDebugger::SSBMremedy1)
EVT_CHECKBOX(IDC_CHECK5,CDebugger::SSBMremedy2)
EVT_RADIOBOX(IDC_RADIO1,CDebugger::ChangeFrequency)
END_EVENT_TABLE()
// =======================================================================================
@ -131,7 +137,30 @@ SetTitle(wxT("Sound Debugging"));
m_checkSizer->Add(m_Check[1], 0, 0, 5);
m_checkSizer->Add(m_Check[2], 0, 0, 5);
// ------------------------
// settings checkboxes -----------------------------------------------------
m_Label[1] = new wxStaticBox(this, IDG_LABEL2, wxT("Settings"),
wxDefaultPosition, wxDefaultSize, 0);
wxStaticBoxSizer * m_checkSizer2 = new wxStaticBoxSizer (m_Label[1], wxVERTICAL);
// checkboxes
m_Check[3] = new wxCheckBox(this, IDC_CHECK3, wxT("SSBM fix"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Check[3]->SetValue(gSSBM);
m_Check[4] = new wxCheckBox(this, IDC_CHECK4, wxT("SSBM remedy 1"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Check[4]->SetValue(gSSBMremedy1);
m_Check[5] = new wxCheckBox(this, IDC_CHECK5, wxT("SSBM remedy 2"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Check[5]->SetValue(gSSBMremedy2);
m_checkSizer2->Add(m_Check[3], 0, 0, 5);
m_checkSizer2->Add(m_Check[4], 0, 0, 5);
m_checkSizer2->Add(m_Check[5], 0, 0, 5);
// ------------------------
// radio boxes -----------------------------------------------------
int m_radioBoxNChoices[2];
@ -154,12 +183,18 @@ SetTitle(wxT("Sound Debugging"));
m_Presets = new wxButton(this, ID_PRESETS, wxT("Presets"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
sLeft = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Current Status"));
// right buttons
wxBoxSizer* sButtons2;
sButtons2 = new wxBoxSizer(wxVERTICAL);
sButtons2->AddStretchSpacer(1);
sButtons2->Add(m_checkSizer2, 0, 2, 5);
sButtons2->AddStretchSpacer(1);
// left buttons
wxBoxSizer* sButtons;
sButtons = new wxBoxSizer(wxVERTICAL);
sButtons->AddStretchSpacer(1);
sButtons->Add(m_Upd, 0, 0, 5);
@ -180,13 +215,16 @@ SetTitle(wxT("Sound Debugging"));
sButtons->AddStretchSpacer(1);
// blocks view
sLeft = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Current Status"));
sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5);
// add all stuff to the main container
sMain = new wxBoxSizer(wxHORIZONTAL);
sMain->Add(sLeft, 1, wxEXPAND|wxALL, 5);
sMain->Add(sButtons, 0, wxEXPAND, 0);
sMain->Add(sButtons2, 0, wxEXPAND, 0);
this->SetSizer(sMain);
sMain->SetSizeHints(this);
@ -208,6 +246,38 @@ void CDebugger::OnUpdate(wxCommandEvent& /*event*/)
this->NotifyUpdate();
}
// =======================================================================================
// Settings
// --------------
void CDebugger::SSBM(wxCommandEvent& event)
{
if(m_Check[3]->IsChecked() == 1)
{gSSBM = true;}
else
{gSSBM = false;}
}
void CDebugger::SSBMremedy1(wxCommandEvent& event)
{
if(m_Check[4]->IsChecked() == 1)
{gSSBMremedy1 = true;}
else
{gSSBMremedy1 = false;}
}
void CDebugger::SSBMremedy2(wxCommandEvent& event)
{
if(m_Check[5]->IsChecked() == 1)
{gSSBMremedy2 = true;}
else
{gSSBMremedy2 = false;}
}
// =======================================================================================
// =======================================================================================
// Change update frequency
// --------------
void CDebugger::ChangeFrequency(wxCommandEvent& event)
{
DoChangeFrequency();
@ -228,7 +298,13 @@ void CDebugger::DoChangeFrequency()
gUpdFreq = 30;
}
}
// ==============
// =======================================================================================
// Show or hide console window
// --------------
void CDebugger::ShowHideConsole(wxCommandEvent& event)
{
DoShowHideConsole();
@ -247,6 +323,8 @@ void CDebugger::DoShowHideConsole()
CloseConsole();
}
}
// ==============
void CDebugger::NotifyUpdate()
{

View File

@ -72,6 +72,9 @@ class CDebugger : public wxDialog
void DoShowHideConsole();
void ChangeFrequency(wxCommandEvent& event);
void DoChangeFrequency();
void SSBM(wxCommandEvent& event);
void SSBMremedy1(wxCommandEvent& event);
void SSBMremedy2(wxCommandEvent& event);
CPBView* m_GPRListView;
@ -91,11 +94,15 @@ class CDebugger : public wxDialog
IDC_CHECK0 = 2000,
IDC_CHECK1,
IDC_CHECK2,
IDC_CHECK3,
IDC_CHECK4,
IDC_CHECK5,
IDC_RADIO0,
IDC_RADIO1,
IDC_RADIO2,
IDC_RADIO3,
IDG_LABEL1,
IDG_LABEL2,
ID_UPD,
ID_SELC,
ID_PRESETS,

View File

@ -45,7 +45,9 @@
float ratioFactor; // a global to get the ratio factor from MixAdd
int gUpdFreq = 5;
u32 gLastBlock;
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
// Parameter blocks
@ -96,16 +98,16 @@ bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
int vectorLengthGUI = 8; // length of playback history bar for the GUI version
int vectorLength = 15; // for console version
int vectorLength2 = 100; // for console version
// More stuff
std::vector< std::vector<int> > vector1(64, std::vector<int>(100,0));
// should we worry about the additonal memory these lists require? bool will allocate
// very little memory
std::vector< std::vector<bool> > vector1(64, std::vector<bool>(vectorLength,0));
std::vector< std::vector<bool> > vector2(64, std::vector<bool>(vectorLength2,0));
std::vector<int> numberRunning(64);
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
// Classes
@ -114,15 +116,13 @@ extern CDebugger* m_frame;
// I placed this in CUCode_AX because there was some kind of problem to call it otherwise,
// I'm sure it's simple to fix but I couldn't.
// I placed this in CUCode_AX because it needs access to private members of that class.
void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// Control how often the screen is updated
j++;
@ -130,8 +130,9 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
if (j > (200/gUpdFreq))
{
// Move all items back - vector1 is a vector1[64][100] vector, I think
// =======================================================================================
// Move all items back - Vector1 is a vector1[64][100] vector
// --------------
/*
Move all items back like this:
1 to 2
@ -153,6 +154,35 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running;
}
// ==============
// =======================================================================================
// Have a separate set for which ones to show
// --------------
/*
Move all items back like this:
1 to 2
2 3
3 ...
*/
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength2; j++)
{
vector2.at(i).at(j-1) = vector2.at(i).at(j);
}
}
// Save the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector2.at(i).at(vectorLength2-1) = PBs[i].running;
}
// ==============
// =======================================================================================
// Count how many we have running now
@ -160,9 +190,9 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength-1; j++)
for (int j = 0; j < vectorLength2-1; j++)
{
if (vector1.at(i).at(j) == 1)
if (vector2.at(i).at(j) == 1)
{
jj++;
}
@ -344,7 +374,6 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// =======================================================================================
// Write global values
// ---------------
@ -352,6 +381,15 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
sbuff = sbuff + buffer; strcpy(buffer, "");
// ===============
// =======================================================================================
// Write settings
// ---------------
sprintf(buffer, "\nSettings: SSBM fix %i | SSBM remedy 1 %i | SSBM remedy 2 %i \n",
gSSBM, gSSBMremedy1, gSSBMremedy2);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ===============
// =======================================================================================
// Show update frequency

View File

@ -27,14 +27,19 @@
#include "UCode_AXStructs.h"
#include "UCode_AX.h"
// ---------------------------------------------------------------------------------------
// Externals
// -----------
extern float ratioFactor;
extern u32 gLastBlock;
bool gSSBM = true; // used externally
bool gSSBMremedy1 = true; // used externally
bool gSSBMremedy2 = true; // used externally
extern CDebugger* m_frame;
// -----------
CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii)
: IUCode(_rMailHandler)
, m_addressPBs(0xFFFFFFFF)
@ -150,52 +155,82 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
AXParamBlock& pb = PBs[i];
// =======================================================================================
// Sequenced music fix - This seems to work allright. I'm not sure which detection method cause
// the least side effects, but pred_scale seems to be nice and simple. Please report any side
// effects.
// ------------
if (!pb.running && pb.adpcm_loop_info.pred_scale)
/*
if (!pb.running &&
(pb.updates.num_updates[0] || pb.updates.num_updates[1] || pb.updates.num_updates[2]
|| pb.updates.num_updates[3] || pb.updates.num_updates[4])
)
*/
{
pb.running = true;
}
// =============
// =======================================================================================
/*
Fix a problem introduced with the SSBM fix - Sometimes when a music stream ended sampleEnd
Fix problems introduced with the SSBM fix - Sometimes when a music stream ended sampleEnd
would become extremely high and the game would play random sound data from ARAM resulting in
a strange noise. This should take care of that. However, when you leave the Continue menu there's
some kind of buzing or interference noise in the music. But it goes away, so I guess it's not a
big issue. Please report any side effects.
a strange noise. This should take care of that. - Some games (Monkey Ball 1 and Tales of
Symphonia) also had one odd block with a strange high loopPos and strange num_updates values,
the loopPos limit turns those off also. - Please report any side effects.Please report any
side effects.
*/
// ------------
const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
if (sampleEnd > 0x10000000)
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
if (
sampleEnd > 0x10000000 || loopPos > 0x10000000
&& gSSBMremedy1
)
{
pb.running = 0;
// also reset all values if it makes any difference
pb.audio_addr.cur_addr_hi = 0;
pb.audio_addr.cur_addr_lo = 0;
pb.audio_addr.end_addr_hi = 0;
pb.audio_addr.end_addr_lo = 0;
pb.audio_addr.loop_addr_hi = 0;
pb.audio_addr.loop_addr_lo = 0;
pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_lo = 0;
pb.audio_addr.end_addr_hi = 0; pb.audio_addr.end_addr_lo = 0;
pb.audio_addr.loop_addr_hi = 0; pb.audio_addr.loop_addr_lo = 0;
pb.audio_addr.looping = 0;
pb.adpcm_loop_info.pred_scale = 0;
pb.adpcm_loop_info.yn1 = 0;
pb.adpcm_loop_info.yn2 = 0;
pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn2 = 0;
}
/*
// the fact that no settings are reset (except running) after a SSBM type music stream has ended
could cause loud garbled sound to be played from several blocks. It could be seen as five or six
simultaneous looping blocks that presumable produced garbled music. My guess is that it was sound
effects that were placed in previous music blocks and mutated into these looping noise machines.
*/
if (
// detect blocks that have recently been running that we should reset
pb.running == 0 && pb.audio_addr.looping == 1
// this prevents us from ruining sequenced music blocks
&& !(pb.updates.num_updates[0] || pb.updates.num_updates[1] || pb.updates.num_updates[2]
|| pb.updates.num_updates[3] || pb.updates.num_updates[4])
&& gSSBMremedy2 // let us turn this fix on and off
)
{
// reset all values, or mostly all
pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_lo = 0;
pb.audio_addr.end_addr_hi = 0; pb.audio_addr.end_addr_lo = 0;
pb.audio_addr.loop_addr_hi = 0; pb.audio_addr.loop_addr_lo = 0;
pb.audio_addr.looping = 0;
pb.adpcm_loop_info.pred_scale = 0;
pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn2 = 0;
}
// =============
// =======================================================================================
/*
// Sequenced music fix - Because SSBM type music did no have its pred_scale (or any other parameter
except running) turned off after a song was stopped a pred_scale check here had the effect of
turning those blocks on immediately after the stopped. Because the pred_scale check caused these
effects I'm trying the num_updates check instead. Please report any side effects.
*/
// ------------
//if (!pb.running && pb.adpcm_loop_info.pred_scale)
/**/
if (!pb.running &&
(pb.updates.num_updates[0] || pb.updates.num_updates[1] || pb.updates.num_updates[2]
|| pb.updates.num_updates[3] || pb.updates.num_updates[4])
)
{
pb.running = 1;
}
// =============
@ -204,8 +239,7 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// =======================================================================================
// Set initial parameters
// ------------
//constants
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
//constants
const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor);
//variables
@ -236,11 +270,14 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// =======================================================================================
// Games that use looping to play non-looping music streams. SSBM has info in all pb.adpcm_loop_info
// parameters but has pb.audio_addr.looping = 0. If we treat these streams like any other looping
// streams the music works.
// Games that use looping to play non-looping music streams - SSBM has info in all
// pb.adpcm_loop_info parameters but has pb.audio_addr.looping = 0. If we treat these streams
// like any other looping streams the music works.
// ---------------------------------------------------------------------------------------
if(pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2)
if(
pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2
&& gSSBM
)
{
pb.audio_addr.looping = 1;
}
@ -248,22 +285,18 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// =======================================================================================
// Streaming music and volume - A lot of music in Paper Mario use the exact same settings, namely
// these:
// Streaming music and volume - The streaming music in Paper Mario use these settings:
// Base settings
// is_stream = 1
// src_type = 0
// coef (unknown1) = 1
// PBAudioAddr
// audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0)
// However. Some of the ingame music and seemingly randomly some other music incorrectly get
// volume = 0 for both left and right. There's also an issue of a hanging very similar to the Baten
// hanging. The Baten issue fixed itself when the music stream was allowed to play to the end and
// then stop. However, all five music streams that is playing when the gate locks up in Paper Mario
// is loooping streams... I don't know what may be wrong.
// ---------------------------------------------------------------------------------------
// A game that may be used as a comparison is Starfox Assault also has is_stream = 1, but it
// has src_type = 1, coef (unknown1) = 0 and its pb.src.ratio_lo (fraction) != 0
// audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0)
/*
However. Some of the ingame music and seemingly randomly some other music incorrectly get
volume = 0 for both left and right. This also affects Fire Emblem. But Starfox Assault
that also use is_stream = 1 has no problem wuth the volume, but its settings are somewhat
different, it uses src_type = 1 and pb.src.ratio_lo (fraction) != 0
*/
// =======================================================================================
@ -620,6 +653,9 @@ int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num)
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
pDest[p] = Common::swap16(pSrc[p]);
// To avoid a performance drop in the Release build I place this in the debug
// build only
#if defined(_DEBUG) || defined(DEBUGFAST)
gLastBlock = blockAddr + p*2 + 2; // save last block location
#endif