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 // externals
extern int gUpdFreq; extern int gUpdFreq;
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
// ======================================================================================= // =======================================================================================
// Declare events // Declare events
@ -33,6 +36,9 @@ BEGIN_EVENT_TABLE(CDebugger,wxDialog)
EVT_CLOSE(CDebugger::OnClose) EVT_CLOSE(CDebugger::OnClose)
EVT_BUTTON(ID_UPD,CDebugger::OnUpdate) EVT_BUTTON(ID_UPD,CDebugger::OnUpdate)
EVT_CHECKBOX(IDC_CHECK2,CDebugger::ShowHideConsole) 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) EVT_RADIOBOX(IDC_RADIO1,CDebugger::ChangeFrequency)
END_EVENT_TABLE() END_EVENT_TABLE()
// ======================================================================================= // =======================================================================================
@ -132,6 +138,29 @@ SetTitle(wxT("Sound Debugging"));
m_checkSizer->Add(m_Check[2], 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 ----------------------------------------------------- // radio boxes -----------------------------------------------------
int m_radioBoxNChoices[2]; int m_radioBoxNChoices[2];
@ -154,12 +183,18 @@ SetTitle(wxT("Sound Debugging"));
m_Presets = new wxButton(this, ID_PRESETS, wxT("Presets"), m_Presets = new wxButton(this, ID_PRESETS, wxT("Presets"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); 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; wxBoxSizer* sButtons;
sButtons = new wxBoxSizer(wxVERTICAL); sButtons = new wxBoxSizer(wxVERTICAL);
sButtons->AddStretchSpacer(1); sButtons->AddStretchSpacer(1);
sButtons->Add(m_Upd, 0, 0, 5); sButtons->Add(m_Upd, 0, 0, 5);
@ -180,13 +215,16 @@ SetTitle(wxT("Sound Debugging"));
sButtons->AddStretchSpacer(1); sButtons->AddStretchSpacer(1);
// blocks view
sLeft = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Current Status"));
sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5); sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5);
// add all stuff to the main container
sMain = new wxBoxSizer(wxHORIZONTAL); sMain = new wxBoxSizer(wxHORIZONTAL);
sMain->Add(sLeft, 1, wxEXPAND|wxALL, 5); sMain->Add(sLeft, 1, wxEXPAND|wxALL, 5);
sMain->Add(sButtons, 0, wxEXPAND, 0); sMain->Add(sButtons, 0, wxEXPAND, 0);
sMain->Add(sButtons2, 0, wxEXPAND, 0);
this->SetSizer(sMain); this->SetSizer(sMain);
sMain->SetSizeHints(this); sMain->SetSizeHints(this);
@ -208,6 +246,38 @@ void CDebugger::OnUpdate(wxCommandEvent& /*event*/)
this->NotifyUpdate(); 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) void CDebugger::ChangeFrequency(wxCommandEvent& event)
{ {
DoChangeFrequency(); DoChangeFrequency();
@ -228,7 +298,13 @@ void CDebugger::DoChangeFrequency()
gUpdFreq = 30; gUpdFreq = 30;
} }
} }
// ==============
// =======================================================================================
// Show or hide console window
// --------------
void CDebugger::ShowHideConsole(wxCommandEvent& event) void CDebugger::ShowHideConsole(wxCommandEvent& event)
{ {
DoShowHideConsole(); DoShowHideConsole();
@ -247,6 +323,8 @@ void CDebugger::DoShowHideConsole()
CloseConsole(); CloseConsole();
} }
} }
// ==============
void CDebugger::NotifyUpdate() void CDebugger::NotifyUpdate()
{ {

View File

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

View File

@ -45,7 +45,9 @@
float ratioFactor; // a global to get the ratio factor from MixAdd float ratioFactor; // a global to get the ratio factor from MixAdd
int gUpdFreq = 5; int gUpdFreq = 5;
u32 gLastBlock; u32 gLastBlock;
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
// Parameter blocks // Parameter blocks
@ -96,16 +98,16 @@ bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar 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 vectorLengthGUI = 8; // length of playback history bar for the GUI version
int vectorLength = 15; // for console version int vectorLength = 15; // for console version
int vectorLength2 = 100; // for console version
// More stuff // 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<int> numberRunning(64);
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
// Classes // Classes
@ -114,8 +116,7 @@ extern CDebugger* m_frame;
// I placed this in CUCode_AX because there was some kind of problem to call it otherwise, // I placed this in CUCode_AX because it needs access to private members of that class.
// I'm sure it's simple to fix but I couldn't.
void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a) void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{ {
@ -123,15 +124,15 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS); int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// Control how often the screen is updated // Control how often the screen is updated
j++; j++;
l++; l++;
if (j > (200/gUpdFreq)) 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: Move all items back like this:
1 to 2 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; 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 // Count how many we have running now
@ -160,9 +190,9 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
int jj = 0; int jj = 0;
for (int i = 0; i < 64; i++) 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++; jj++;
} }
@ -344,7 +374,6 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// ======================================================================================= // =======================================================================================
// Write global values // Write global values
// --------------- // ---------------
@ -353,6 +382,15 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// =============== // ===============
// =======================================================================================
// 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 // Show update frequency
// --------------- // ---------------

View File

@ -27,14 +27,19 @@
#include "UCode_AXStructs.h" #include "UCode_AXStructs.h"
#include "UCode_AX.h" #include "UCode_AX.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// Externals // Externals
// ----------- // -----------
extern float ratioFactor; extern float ratioFactor;
extern u32 gLastBlock; extern u32 gLastBlock;
bool gSSBM = true; // used externally
bool gSSBMremedy1 = true; // used externally
bool gSSBMremedy2 = true; // used externally
extern CDebugger* m_frame; extern CDebugger* m_frame;
// ----------- // -----------
CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii) CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii)
: IUCode(_rMailHandler) : IUCode(_rMailHandler)
, m_addressPBs(0xFFFFFFFF) , m_addressPBs(0xFFFFFFFF)
@ -150,52 +155,82 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
AXParamBlock& pb = PBs[i]; 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 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 a strange noise. This should take care of that. - Some games (Monkey Ball 1 and Tales of
some kind of buzing or interference noise in the music. But it goes away, so I guess it's not a Symphonia) also had one odd block with a strange high loopPos and strange num_updates values,
big issue. Please report any side effects. 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; 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; pb.running = 0;
// also reset all values if it makes any difference // also reset all values if it makes any difference
pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_lo = 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.end_addr_hi = 0; pb.audio_addr.loop_addr_hi = 0; pb.audio_addr.loop_addr_lo = 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.audio_addr.looping = 0;
pb.adpcm_loop_info.pred_scale = 0; pb.adpcm_loop_info.pred_scale = 0;
pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn2 = 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;
} }
// ============= // =============
@ -205,7 +240,6 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// Set initial parameters // Set initial parameters
// ------------ // ------------
//constants //constants
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor); const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor);
//variables //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 // Games that use looping to play non-looping music streams - SSBM has info in all
// parameters but has pb.audio_addr.looping = 0. If we treat these streams like any other looping // pb.adpcm_loop_info parameters but has pb.audio_addr.looping = 0. If we treat these streams
// streams the music works. // 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; 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 // Streaming music and volume - The streaming music in Paper Mario use these settings:
// these:
// Base settings // Base settings
// is_stream = 1 // is_stream = 1
// src_type = 0 // src_type = 0
// coef (unknown1) = 1
// PBAudioAddr // PBAudioAddr
// audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 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. There's also an issue of a hanging very similar to the Baten However. Some of the ingame music and seemingly randomly some other music incorrectly get
// hanging. The Baten issue fixed itself when the music stream was allowed to play to the end and volume = 0 for both left and right. This also affects Fire Emblem. But Starfox Assault
// then stop. However, all five music streams that is playing when the gate locks up in Paper Mario that also use is_stream = 1 has no problem wuth the volume, but its settings are somewhat
// is loooping streams... I don't know what may be wrong. different, it uses src_type = 1 and pb.src.ratio_lo (fraction) != 0
// --------------------------------------------------------------------------------------- */
// 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
// ======================================================================================= // =======================================================================================
@ -620,6 +653,9 @@ int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num)
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{ {
pDest[p] = Common::swap16(pSrc[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) #if defined(_DEBUG) || defined(DEBUGFAST)
gLastBlock = blockAddr + p*2 + 2; // save last block location gLastBlock = blockAddr + p*2 + 2; // save last block location
#endif #endif