dolphin/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp
John Peterson d4f8f0d3ae Added the StretchToFit option to the config menu in the OpenGL plugin. This fixes the blackness in SSBM. I also added a keep aspect ratio option, it will keep your aspect ratio at 4:3, but then SSBM will have the blackness problem again. You find the options under the Enhancements window in the OpenGL configuration.
I also added a wx debugging window for the OpenGL plugin. I connected it to the old console window that was in the plugin. Other than that it doesn't do anything at the moment but it could be useful to show all the current important information and parameter statuses and so on.

Again there's a problem with wx windows collisions.  Show() can't be used because then DLL_PROCESS_DETACH is called immediately after the window is opened, and if we open it with ShowModal() before we have loaded a game the main video window will be blocked. And we can't pass on any variables from a DllDebugger() that is called when Dolphin is started because the dll is reloaded and lose all variables sometime before a game is loaded. So we can't auto open the window that way. So I made the debugging window open as a game is loaded if it is enabled in the ini, the downside is that the ini setting will open the window even if we are not opening Dolphin with the -d flag. However, this will only affect people that have used the debugger at least once so in my opinion this is the most convenient solution. But feel free to come up with a better solution. Preferably some solution to how to use Show() and preventing DLL_PROCESS_DETACH to be called.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@812 8ced0084-cf51-0410-be5f-012b33b47a6e
2008-10-09 18:47:53 +00:00

685 lines
20 KiB
C++

//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// 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/
//
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
#include <iostream>
#include <vector>
#include <string> // so that we can test std::string == abc
#include <math.h> // for the pow() function
#ifdef _WIN32
#include <windows.h>
#endif
#include "../Debugger/Debugger.h"
#include "../Debugger/PBView.h"
#include "Console.h" // open and close console, clear console window
#include "../Globals.h"
#include "../UCodes/UCodes.h"
#include "../UCodes/UCode_AXStructs.h"
#include "../UCodes/UCode_AX.h"
// Externals
extern int nFiles;
float ratioFactor; // a global to get the ratio factor from MixAdd
int gUpdFreq = 5;
int gPreset = 0;
u32 gLastBlock;
extern bool gSSBM;
extern bool gSSBMremedy1;
extern bool gSSBMremedy2;
extern bool gSequenced;
extern bool gReset;
bool gOnlyLooping = false;
extern int gSaveFile;
// Parameter blocks
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
// main
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// PBSampleRateConverter src
std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gmix_unknown(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmix_unknown2(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gmixer_vol1(64);
std::vector<u16> gmixer_vol2(64);
std::vector<u16> gmixer_vol3(64);
std::vector<u16> gmixer_vol4(64);
std::vector<u16> gmixer_vol5(64);
std::vector<u16> gmixer_vol6(64);
std::vector<u16> gmixer_vol7(64);
std::vector<u16> gmixer_d1(64);
std::vector<u16> gmixer_d2(64);
std::vector<u16> gmixer_d3(64);
std::vector<u16> gmixer_d4(64);
std::vector<u16> gmixer_d5(64);
std::vector<u16> gmixer_d6(64);
std::vector<u16> gmixer_d7(64);
// PBVolumeEnvelope vol_env
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
// PBAudioAddr audio_addr (incl looping)
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
// PBADPCMInfo adpcm
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
// updates
std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
std::vector<u32> gupdates_data(64);
// Counters
int j = 0;
int k = 0;
unsigned int l = 0;
int iupd = 0;
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
// 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);
// Classes
extern CDebugger* m_frame;
// =======================================================================================
// Write title
// --------------
std::string writeTitle(int a)
{
std::string b;
if(a == 0)
{
b = " adpcm adpcm_loop\n";
b = b + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n";
}
else if(a == 1)
{
b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5\n";
}
else if(a == 2)
{
b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
}
else if(a == 3)
{
b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n";
}
return b;
}
// =======================================================================================
// =======================================================================================
// Write main message (presets)
// --------------
std::string writeMessage(int a, int i)
{
char buf [1000] = "";
std::string sbuf;
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
PRESET 0
" Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000 00000 00000 000 00000 00000 | 00000 00000[0 00000]
PRESET 1 (updates)
" Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 0 | 0 0 0 0 0
PRESET 2
" Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000000 000000
*/
if(a == 0)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i]
);
}
else if(a == 1)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i %i | %i %i %i %i %i %08x %08x",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
gsrc_type[i], gaudioFormat[i], gcoef[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], gupdates_data[i]
);
}
else if(a == 2)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i | %06i %06i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gsampleEnd[i] - gloopPos[i], gsampleEnd[i] - gsamplePos[i]
);
}
/*
PRESET 3
" Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n";
"---------------|00 00000 00000 00000 00000 00000 00000 00000 0 | 00000 00000 00000 00000 00000 00000 00000 | 00000 00000 00000 00000 00000 00000 00000
*/
else if(a == 3)
{
sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %05i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i",
223, i,
gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i],
gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING),
gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i],
gmixer_vol6[i], gmixer_vol7[i],
gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i],
gmixer_d6[i], gmixer_d7[i]
);
}
sbuf = buf;
return sbuf;
}
// =======================================================================================
// 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);
// =======================================================================================
// Update parameter values
// --------------
// We could chose to update these only if a block is currently running - Later I'll add options
// to see both the current and the lastets active value.
//if (PBs[i].running)
int irun = 0;
for (int i = 0; i < numberOfPBs; i++)
{
if(PBs[i].running)
{
irun++;
}
// write a line if nothing is playing
if (i == numberOfPBs - 1 && irun == 0)
{
for (int i = 0; i < nFiles; i++)
{
std::string sfbuff;
sfbuff = "-----";
aprintf(i, (char *)sfbuff.c_str());
}
}
// ---------------------------------------------------------------------------------------
// Prepare conditions
// --------------
bool Conditions;
if (gOnlyLooping)
{
Conditions = PBs[i].audio_addr.looping;
}
else
{
Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping);
}
// --------------
if(Conditions)
{
// AXPB base
gcoef[i] = PBs[i].unknown1;
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gupdates_data[i] = Memory_Read_U32(gupdates_addr[i]);
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmix_unknown[i] = PBs[i].mixer.unknown;
gmix_unknown2[i] = PBs[i].mixer.unknown2;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
gmixer_vol1[i] = PBs[i].mixer.unknown3[0];
gmixer_vol2[i] = PBs[i].mixer.unknown3[2];
gmixer_vol3[i] = PBs[i].mixer.unknown3[4];
gmixer_vol4[i] = PBs[i].mixer.unknown3[6];
gmixer_vol5[i] = PBs[i].mixer.unknown3[0];
gmixer_vol6[i] = PBs[i].mixer.unknown3[2];
gmixer_vol7[i] = PBs[i].mixer.unknown3[4];
gmixer_d1[i] = PBs[i].mixer.unknown4[1];
gmixer_d2[i] = PBs[i].mixer.unknown4[3];
gmixer_d3[i] = PBs[i].mixer.unknown4[5];
gmixer_d4[i] = PBs[i].mixer.unknown4[7];
gmixer_d5[i] = PBs[i].mixer.unknown4[1];
gmixer_d6[i] = PBs[i].mixer.unknown4[3];
gmixer_d7[i] = PBs[i].mixer.unknown4[5];
// ---------------------------------------------------------------------------------------
// Write to file
// --------------
for (int ii = 0; ii < nFiles; ii++)
{
std::string sfbuff;
if(a == 0) sfbuff = "***"; // note if it's before or after an update
else sfbuff = " ";
sfbuff = sfbuff + writeMessage(ii, i);
sfbuff = sfbuff + "\n";
aprintf(ii, (char *)sfbuff.c_str());
}
// --------------
}
}
// ==============
// =======================================================================================
// Control how often the screen is updated, and then update the screen
// --------------
if(a == 0) j++;
//if(l == pow((double)2,32)) l=0; // reset l
//l++;
if (j > (200/gUpdFreq))
{
// =======================================================================================
// Move all items back - Vector1 is a vector1[64][100] vector
// --------------
/*
Move all items back like this:
1 to 2
2 3
3 ...
*/
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength; j++)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// Save the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running ? true : false;
}
// ==============
// =======================================================================================
// 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
// --------------
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength2-1; j++)
{
if (vector2.at(i).at(j) == 1)
{
jj++;
}
numberRunning.at(i) = jj;
}
}
// ==============
// =======================================================================================
// Write header
// --------------
char buffer [1000] = "";
std::string sbuff;
sbuff = writeTitle(gPreset);
// ==============
// go through all running blocks
for (int i = 0; i < numberOfPBs; i++)
{
// ---------------------------------------------------------------------------------------
// Prepare conditions. TODO: We use this in two places now, make it only one
// --------------
bool Conditions;
if (gOnlyLooping)
{
Conditions = PBs[i].audio_addr.looping;
}
else
{
Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping);
}
// --------------
// use the condition
if (Conditions)
{
// Playback history for the GUI debugger --------------------------
if(m_frame)
{
std::string guipr; // gui progress
for (int j = 0; j < vectorLengthGUI; j++)
{
if(vector1.at(i).at(j) == 0)
{
guipr = guipr + "0";
}
else
{
guipr = guipr + "1";
}
}
u32 run = atoi( guipr.c_str());
m_frame->m_GPRListView->m_CachedRegs[1][i] = run;
guipr.clear();
}
// Playback history for the console debugger --------------------------
for (int j = 0; j < vectorLength; j++)
{
if(vector1.at(i).at(j) == 0)
{
//strcat(buffer, " ");
sbuff = sbuff + " ";
}
else
{
//sprintf(buffer, "%s%c", buffer, 177); // this will add strange letters if buffer has
// not been given any string yet
sprintf(buffer, "%c", 177);
//strcat(buffer, tmpbuff);
//strcpy(buffer, "");
//sprintf(buffer, "%c", 177);
sbuff = sbuff + buffer; strcpy(buffer, "");
}
}
// ---------
// hopefully this is false if we don't have a debugging window and so it doesn't cause a crash
if(m_frame)
{
m_frame->m_GPRListView->m_CachedRegs[2][i] = gsamplePos[i];
m_frame->m_GPRListView->m_CachedRegs[3][i] = gsampleEnd[i];
m_frame->m_GPRListView->m_CachedRegs[4][i] = gloopPos[i];
m_frame->m_GPRListView->m_CachedRegs[5][i] = gvolume_left[i];
m_frame->m_GPRListView->m_CachedRegs[6][i] = gvolume_right[i];
m_frame->m_GPRListView->m_CachedRegs[7][i] = glooping[i];
m_frame->m_GPRListView->m_CachedRegs[8][i] = gloop1[i];
m_frame->m_GPRListView->m_CachedRegs[9][i] = gloop2[i];
m_frame->m_GPRListView->m_CachedRegs[10][i] = gloop3[i];
m_frame->m_GPRListView->m_CachedRegs[11][i] = gis_stream[i];
m_frame->m_GPRListView->m_CachedRegs[12][i] = gaudioFormat[i];
m_frame->m_GPRListView->m_CachedRegs[13][i] = gsrc_type[i];
m_frame->m_GPRListView->m_CachedRegs[14][i] = gcoef[i];
m_frame->m_GPRListView->m_CachedRegs[15][i] = gfrac[i];
m_frame->m_GPRListView->m_CachedRegs[16][i] = gratio[i];
m_frame->m_GPRListView->m_CachedRegs[17][i] = gratiohi[i];
m_frame->m_GPRListView->m_CachedRegs[18][i] = gratiolo[i];
m_frame->m_GPRListView->m_CachedRegs[19][i] = gupdates1[i];
m_frame->m_GPRListView->m_CachedRegs[20][i] = gupdates2[i];
m_frame->m_GPRListView->m_CachedRegs[21][i] = gupdates3[i];
m_frame->m_GPRListView->m_CachedRegs[22][i] = gupdates4[i];
m_frame->m_GPRListView->m_CachedRegs[23][i] = gupdates5[i];
}
// add new line
sbuff = sbuff + writeMessage(gPreset, i); strcpy(buffer, "");
sbuff = sbuff + "\n";
} // end of if (PBs[i].running)
} // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values
// ---------------
sprintf(buffer, "\nThe parameter blocks span from %08x to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ===============
// =======================================================================================
// Write settings
// ---------------
sprintf(buffer, "\nSettings: SSBM fix %i | SSBM rem1 %i | SSBM rem2 %i | Sequenced %i | Reset %i | Only looping %i | Save file %i\n",
gSSBM, gSSBMremedy1, gSSBMremedy2, gSequenced, gReset, gOnlyLooping, gSaveFile);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ===============
// =======================================================================================
// Show update frequency
// ---------------
sbuff = sbuff + "\n";
if(!iupdonce)
{
/*
for (int i = 0; i < 10; i++)
{
viupd.at(i) == 0;
}
*/
viupd.at(0) = 1;
viupd.at(1) = 1;
viupd.at(2) = 1;
iupdonce = true;
}
for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9
{
if (i < viupd.size()-1)
{
viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward
}
else
{
viupd.at(0) = viupd.at(viupd.size()-1);
}
// Correction
if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1)
{
viupd.at(0) = 0;
}
if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0)
{
viupd.at(0) = 1;
}
}
for (int i = 0; i < viupd.size(); i++)
{
if(viupd.at(i) == 0)
sbuff = sbuff + " ";
else
sbuff = sbuff + ".";
}
// ================
// =======================================================================================
// Print
// ----------------
ClearScreen();
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ================
// New values are written so update - DISABLED - It flickered a lot, even worse than a
// console window. So for now only the console windows is updated.
/*
if(m_frame)
{
m_frame->NotifyUpdate();
}
*/
k=0;
j=0;
} // end of if (j>20)
} // end of function