/*************************************************************************** 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 //////////////////////////////////////////////////////////////////////// // 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 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>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 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