mirror of https://github.com/PCSX2/pcsx2.git
443 lines
16 KiB
C
443 lines
16 KiB
C
/***************************************************************************
|
|
debug.c - description
|
|
-------------------
|
|
begin : Wed May 15 2002
|
|
copyright : (C) 2002 by Pete Bernert
|
|
email : BlackDove@addcom.de
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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; either version 2 of the License, or *
|
|
* (at your option) any later version. See also the license.txt file for *
|
|
* additional informations. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
//*************************************************************************//
|
|
// History of changes:
|
|
//
|
|
// 2004/12/25 - Pete
|
|
// - update mute checkboxes if core selection changes
|
|
//
|
|
// 2004/04/04 - Pete
|
|
// - changed plugin to emulate PS2 spu
|
|
//
|
|
// 2003/01/06 - Pete
|
|
// - added Neil's ADSR timings
|
|
//
|
|
// 2002/05/15 - Pete
|
|
// - generic cleanup for the Peops release
|
|
//
|
|
//*************************************************************************//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define _IN_DEBUG
|
|
|
|
#include "externals.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// WINDOWS DEBUG DIALOG HANDLING
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#include "resource.h"
|
|
|
|
//#define SMALLDEBUG
|
|
//#include <dbgout.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// display debug infos
|
|
|
|
const COLORREF crStreamCol[]={
|
|
RGB( 0, 0, 0),
|
|
RGB(255,255,255),
|
|
RGB(128, 0,128),
|
|
RGB( 0,128, 0),
|
|
RGB( 0, 0,255),
|
|
RGB(255, 0, 0)
|
|
};
|
|
|
|
const COLORREF crAdsrCol[] ={
|
|
RGB( 0, 0, 0),
|
|
RGB(255, 0, 0),
|
|
RGB( 0,255, 0),
|
|
RGB(255, 0,255),
|
|
RGB( 0, 0,255),
|
|
RGB( 0, 0, 0),
|
|
};
|
|
|
|
HBRUSH hBStream[6]; // brushes for stream lines
|
|
HPEN hPAdsr[6]; // pens for adsr lines
|
|
int iSelChannel=0; // user selected channel
|
|
int iCoreOffset=0;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// display the sound data waves: no subclassing used, so the
|
|
// area will not be redrawn... but faster that way, and good enuff
|
|
// for debugging purposes
|
|
|
|
void DisplayStreamInfos(HWND hW)
|
|
{
|
|
HWND hWS=GetDlgItem(hW,IDC_SAREA);
|
|
HDC hdc;RECT r;HBRUSH hBO;int ch,dy,i,j,id;
|
|
|
|
//----------------------------------------------------//
|
|
|
|
GetClientRect(hWS,&r); // get size of stream display
|
|
hdc=GetDC(hWS); // device context
|
|
r.right--; // leave the right border intact
|
|
ScrollDC(hdc,-1,0,&r,&r,NULL,NULL); // scroll one pixel to the left
|
|
|
|
//----------------------------------------------------//
|
|
|
|
hBO=SelectObject(hdc,hBStream[0]); // clean the right border
|
|
PatBlt(hdc,r.right-1,0,1,r.bottom,PATCOPY);
|
|
|
|
//----------------------------------------------------//
|
|
|
|
dy=r.bottom/HLFCHAN; // size of one channel area
|
|
|
|
for(ch=0;ch<HLFCHAN;ch++) // loop the channels
|
|
{
|
|
if(s_chan[ch+iCoreOffset].bOn) // channel is on?
|
|
{
|
|
if(s_chan[ch+iCoreOffset].iIrqDone)
|
|
{
|
|
s_chan[ch+iCoreOffset].iIrqDone=0;
|
|
PatBlt(hdc,r.right-1,ch*r.bottom/HLFCHAN,
|
|
1,dy,BLACKNESS);
|
|
continue;
|
|
}
|
|
|
|
j=s_chan[ch+iCoreOffset].sval;if(j<0) j=-j; // -> get one channel data (-32k ... 32k)
|
|
j=(dy*j)/33768; if(j==0) j=1; // -> adjust to display coords
|
|
i=(dy/2)+(ch*r.bottom/HLFCHAN)-j/2; // -> position where to paint it
|
|
|
|
|
|
|
|
if (s_chan[ch+iCoreOffset].iMute) id=1; // -> get color id
|
|
else if(s_chan[ch+iCoreOffset].bNoise) id=2;
|
|
else if(s_chan[ch+iCoreOffset].bFMod==2) id=3;
|
|
else if(s_chan[ch+iCoreOffset].bFMod==1) id=4;
|
|
else id=5;
|
|
|
|
SelectObject(hdc,hBStream[id]); // -> select the brush
|
|
PatBlt(hdc,r.right-1,i,1,j,PATCOPY); // -> paint the value line
|
|
}
|
|
|
|
if(ch) SetPixel(hdc,r.right-1, // -> not first line?
|
|
ch*r.bottom/HLFCHAN,RGB(0,0,0)); // --> draw the line (one dot scrolled to the left)
|
|
}
|
|
|
|
//----------------------------------------------------//
|
|
|
|
SelectObject(hdc,hBO); // repair brush
|
|
|
|
ReleaseDC(hWS,hdc); // release context
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// display adsr lines: also no subclassing for repainting used
|
|
|
|
void DisplayADSRInfos(HWND hW)
|
|
{
|
|
HWND hWS=GetDlgItem(hW,IDC_ADSR);
|
|
HDC hdc;RECT r;HBRUSH hBO;char szB[16];
|
|
int ch=iSelChannel+iCoreOffset,dx,dy,dm,dn,ia,id,is,ir;
|
|
|
|
//----------------------------------------------------// get display size
|
|
|
|
GetClientRect(hWS,&r);
|
|
hdc=GetDC(hWS);
|
|
|
|
//----------------------------------------------------// clean the area
|
|
|
|
hBO=SelectObject(hdc,hBStream[0]);
|
|
PatBlt(hdc,0,0,r.right,r.bottom,PATCOPY);
|
|
r.left++;r.right-=2;r.top++;r.bottom-=2; // shrink the display rect for better optics
|
|
|
|
//----------------------------------------------------//
|
|
|
|
ia=min(s_chan[ch].ADSR.AttackTime,10000); // get adsr, but limit it for drawing
|
|
id=min(s_chan[ch].ADSR.DecayTime,10000);
|
|
is=min(s_chan[ch].ADSR.SustainTime,10000);
|
|
ir=min(s_chan[ch].ADSR.ReleaseTime,10000);
|
|
|
|
dx=ia+id+is+ir; // get the dx in (limited) adsr units
|
|
|
|
// set the real values to the info statics
|
|
SetDlgItemInt(hW,IDC_SADSR1,s_chan[ch].ADSRX.AttackRate,FALSE);
|
|
SetDlgItemInt(hW,IDC_SADSR2,s_chan[ch].ADSRX.DecayRate,FALSE);
|
|
SetDlgItemInt(hW,IDC_SADSR3,s_chan[ch].ADSRX.SustainRate,FALSE);
|
|
SetDlgItemInt(hW,IDC_SADSR4,s_chan[ch].ADSRX.ReleaseRate,FALSE);
|
|
SetDlgItemInt(hW,IDC_SADSR5,s_chan[ch].ADSRX.SustainLevel,FALSE);
|
|
SetDlgItemInt(hW,IDC_SADSR6,s_chan[ch].ADSRX.SustainIncrease,TRUE);
|
|
SetDlgItemInt(hW,IDC_SADSR7,s_chan[ch].ADSRX.lVolume,TRUE);
|
|
wsprintf(szB,"%08lX",s_chan[ch].ADSRX.EnvelopeVol);
|
|
SetDlgItemText(hW,IDC_SADSR8,szB);
|
|
|
|
if(dx) // something to draw?
|
|
{
|
|
HPEN hPO=SelectObject(hdc,hPAdsr[1]); // sel A pen
|
|
dn=r.left;
|
|
MoveToEx(hdc,dn,r.bottom,NULL); // move to bottom left corner
|
|
|
|
dn+=(ia*r.right)/dx; // calc A x line pos
|
|
LineTo(hdc,dn,r.top); // line to AxPos,top
|
|
|
|
SelectObject(hdc,hPAdsr[2]); // sel D pen
|
|
dn+=(id*r.right)/dx; // calc D x line pos
|
|
dy=r.top+((1024-s_chan[ch].ADSR.SustainLevel)* // calc the D y pos
|
|
r.bottom)/1024; // (our S level is ranged from 0 to 1024)
|
|
LineTo(hdc,dn,dy); // line to DxPos,SLevel
|
|
|
|
SelectObject(hdc,hPAdsr[3]); // sel S pen
|
|
if(s_chan[ch].ADSR.SustainTime>10000)
|
|
dm=1; // we have to fake the S values... S will
|
|
else // inc/decrease until channel stop...
|
|
if(s_chan[ch].ADSR.SustainTime==0)
|
|
dm=0; // we dunno here when this will happen,
|
|
else
|
|
dm=21-(((s_chan[ch].ADSR.SustainTime/500))); // so we do some more or less angled line,
|
|
dy=dy-(s_chan[ch].ADSR.SustainModeDec*dm); // roughly depending on the S time
|
|
if(dy>r.bottom) dy=r.bottom;
|
|
if(dy<r.top) dy=r.top;
|
|
dn+=(is*r.right)/dx;
|
|
LineTo(hdc,dn,dy); // line to SxPos, fake end volume level
|
|
|
|
SelectObject(hdc,hPAdsr[4]); // sel R pen
|
|
dn+=(ir*r.right)/dx; // calc R x line pos
|
|
LineTo(hdc,dn,r.bottom); // line to RxPos, bottom right y
|
|
|
|
SelectObject(hdc,hPO); // repair pen
|
|
}
|
|
|
|
SelectObject(hdc,hBO); // repair brush
|
|
ReleaseDC(hWS,hdc); // release context
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void DisplayChannelInfos(HWND hW)
|
|
{
|
|
int ch=iSelChannel+iCoreOffset;char szB[16];
|
|
|
|
// channel infos
|
|
SetDlgItemInt(hW,IDC_CI1,s_chan[ch].bOn,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI2,s_chan[ch].bStop,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI3,s_chan[ch].bNoise,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI4,s_chan[ch].bFMod,TRUE);
|
|
wsprintf(szB,"L%d R%d",s_chan[ch].bReverbL,s_chan[ch].bReverbR);
|
|
SetDlgItemText(hW,IDC_CI5,szB);
|
|
SetDlgItemInt(hW,IDC_CI6,s_chan[ch].bRVBActive,TRUE);
|
|
wsprintf(szB,"%08lX",rvb[iCoreOffset/24].StartAddr);
|
|
SetDlgItemText(hW,IDC_CI7,szB);
|
|
wsprintf(szB,"%08lX",rvb[iCoreOffset/24].EndAddr);
|
|
SetDlgItemText(hW,IDC_CI8,szB);
|
|
wsprintf(szB,"%08lX",rvb[iCoreOffset/24].CurrAddr);
|
|
SetDlgItemText(hW,IDC_CI9,szB);
|
|
|
|
wsprintf(szB,"%08lX",((unsigned long)s_chan[ch].pStart-(unsigned long)spuMemC)>>1);
|
|
SetDlgItemText(hW,IDC_CI10,szB);
|
|
if(s_chan[ch].pCurr==(unsigned char *)-1)
|
|
SetDlgItemText(hW,IDC_CI11,"FFFFFFFF");
|
|
else
|
|
{
|
|
wsprintf(szB,"%08lX",((unsigned long)s_chan[ch].pCurr-(unsigned long)spuMemC)>>1);
|
|
SetDlgItemText(hW,IDC_CI11,szB);
|
|
}
|
|
|
|
wsprintf(szB,"%08lX",((unsigned long)s_chan[ch].pLoop-(unsigned long)spuMemC)>>1);
|
|
SetDlgItemText(hW,IDC_CI12,szB);
|
|
SetDlgItemInt(hW,IDC_CI13,s_chan[ch].iRightVolume,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI14,s_chan[ch].iLeftVolume,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI15,s_chan[ch].iActFreq,TRUE);
|
|
SetDlgItemInt(hW,IDC_CI16,s_chan[ch].iUsedFreq,TRUE);
|
|
|
|
// wsprintf(szB,"%04x",s_chan[ch].iRightVolRaw);
|
|
wsprintf(szB,"R%d",s_chan[ch].bVolumeR);
|
|
SetDlgItemText(hW,IDC_CI17,szB);
|
|
// wsprintf(szB,"%04x",s_chan[ch].iLeftVolRaw);
|
|
wsprintf(szB,"L%d",s_chan[ch].bVolumeL);
|
|
SetDlgItemText(hW,IDC_CI18,szB);
|
|
|
|
wsprintf(szB,"%08lX",s_chan[ch].iNextAdr);
|
|
SetDlgItemText(hW,IDC_CI19,szB);
|
|
|
|
// generic infos
|
|
/*if(pSpuIrq[ch]==0)
|
|
SetDlgItemText(hW,IDC_STA1,"FFFFFFFF");
|
|
else
|
|
{*/
|
|
wsprintf(szB,"%08lX",((unsigned long)pSpuIrq[ch/24]-(unsigned long)spuMemC)>>1);
|
|
SetDlgItemText(hW,IDC_STA1,szB);
|
|
/*}*/
|
|
|
|
wsprintf(szB,"%04X",spuCtrl2[ch/24]);
|
|
SetDlgItemText(hW,IDC_STA2,szB);
|
|
wsprintf(szB,"%04X",spuStat2[ch/24]);
|
|
SetDlgItemText(hW,IDC_STA3,szB);
|
|
|
|
wsprintf(szB,"%08lX",spuAddr2[ch/24]);
|
|
SetDlgItemText(hW,IDC_STA4,szB);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// display everything (called in dialog timer for value refreshing)
|
|
|
|
void DisplayDebugInfos(HWND hW)
|
|
{
|
|
DisplayStreamInfos(hW);
|
|
DisplayADSRInfos(hW);
|
|
DisplayChannelInfos(hW);
|
|
}
|
|
|
|
EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val);
|
|
EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// main debug dlg handler
|
|
|
|
char old_buffer[128];
|
|
int iBuffRepeats=0;
|
|
|
|
BOOL CALLBACK DebugDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
//--------------------------------------------------// init
|
|
case WM_INITDIALOG:
|
|
{
|
|
int i;
|
|
ShowCursor(TRUE); // mmm... who is hiding it? main emu? tsts
|
|
iSelChannel=0; // sel first channel
|
|
iCoreOffset=0;
|
|
CheckRadioButton(hW,IDC_CHAN1,IDC_CHAN24,IDC_CHAN1);
|
|
CheckRadioButton(hW,IDC_CORE1,IDC_CORE2,IDC_CORE1);
|
|
|
|
memset(old_buffer,0,128);
|
|
// create brushes/pens
|
|
hBStream[0]=CreateSolidBrush(GetSysColor(COLOR_3DFACE));
|
|
hPAdsr[0]=CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DFACE));
|
|
for(i=1;i<6;i++)
|
|
{
|
|
hBStream[i]=CreateSolidBrush(crStreamCol[i]);
|
|
hPAdsr[i]=CreatePen(PS_SOLID,0,crAdsrCol[i]);
|
|
}
|
|
SetTimer(hW,999,50,NULL); // now create update timer
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------// destroy
|
|
case WM_DESTROY:
|
|
{
|
|
int i;
|
|
KillTimer(hW,999); // first kill timer
|
|
for(i=0;i<6;i++) // then kill brushes/pens
|
|
{
|
|
DeleteObject(hBStream[i]);
|
|
DeleteObject(hPAdsr[i]);
|
|
}
|
|
}break;
|
|
//--------------------------------------------------// timer
|
|
case WM_TIMER:
|
|
{
|
|
if(wParam==999) DisplayDebugInfos(hW); // update all values
|
|
}break;
|
|
//--------------------------------------------------// command
|
|
case WM_COMMAND:
|
|
{
|
|
if(wParam==IDCANCEL) iDebugMode=2; // cancel? raise flag for destroying the dialog
|
|
|
|
if(wParam>=IDC_CORE1 && wParam<=IDC_CORE2) // core clicked?
|
|
{
|
|
int i;
|
|
|
|
if(IsDlgButtonChecked(hW,IDC_CORE1)) // -> sel correct half of channels
|
|
iCoreOffset=0;
|
|
else iCoreOffset=24;
|
|
|
|
for(i=IDC_MUTE1;i<=IDC_MUTE24;i++)
|
|
{
|
|
if(s_chan[i-IDC_MUTE1+iCoreOffset].iMute)
|
|
CheckDlgButton(hW,i,TRUE);
|
|
else CheckDlgButton(hW,i,FALSE);
|
|
}
|
|
|
|
InvalidateRect(hW,NULL,TRUE);
|
|
UpdateWindow(hW);
|
|
}
|
|
|
|
if(wParam>=IDC_MUTE1 && wParam<=IDC_MUTE24) // mute clicked?
|
|
{
|
|
if(IsDlgButtonChecked(hW,wParam)) // -> mute/unmute it
|
|
s_chan[wParam-IDC_MUTE1+iCoreOffset].iMute=1;
|
|
else
|
|
s_chan[wParam-IDC_MUTE1+iCoreOffset].iMute=0;
|
|
}
|
|
// all mute/unmute
|
|
if(wParam==IDC_MUTEOFF) SendMessage(hW,WM_MUTE,0,0);
|
|
if(wParam==IDC_MUTEON) SendMessage(hW,WM_MUTE,1,0);
|
|
|
|
if(wParam>=IDC_CHAN1 && wParam<=IDC_CHAN24) // sel channel
|
|
{
|
|
if(IsDlgButtonChecked(hW,wParam))
|
|
{
|
|
iSelChannel=wParam-IDC_CHAN1;
|
|
SetDlgItemInt(hW,IDC_CHANNUM,iSelChannel+1,FALSE);
|
|
}
|
|
}
|
|
}break;
|
|
//--------------------------------------------------// mute
|
|
case WM_MUTE:
|
|
{ // will be called by the mute/unmute all button and on savestate load
|
|
int i;
|
|
for(i=IDC_MUTE1;i<=IDC_MUTE24;i++)
|
|
{
|
|
CheckDlgButton(hW,i,wParam);
|
|
if(wParam)
|
|
s_chan[i-IDC_MUTE1+iCoreOffset].iMute=1;
|
|
else
|
|
s_chan[i-IDC_MUTE1+iCoreOffset].iMute=0;
|
|
}
|
|
}break;
|
|
//--------------------------------------------------// size
|
|
case WM_SIZE:
|
|
if(wParam==SIZE_MINIMIZED) SetFocus(hWMain); // if we get minimized, set the foxus to the main window
|
|
break;
|
|
//--------------------------------------------------// setcursor
|
|
case WM_SETCURSOR:
|
|
{
|
|
SetCursor(LoadCursor(NULL,IDC_ARROW)); // force the arrow
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------//
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
#include <stdio.h>
|
|
extern FILE * LogFile;
|
|
void logprintf(LPCTSTR pFormat, ...)
|
|
{
|
|
if(iDebugMode!=1) return;
|
|
if(!IsWindow(hWDebug)) return;
|
|
else
|
|
{
|
|
va_list list;
|
|
|
|
va_start(list,pFormat);
|
|
vfprintf(LogFile, pFormat, list);
|
|
va_end(list);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|