590 lines
17 KiB
C++
590 lines
17 KiB
C++
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2002 Ben Parnell
|
|
*
|
|
* 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.
|
|
*
|
|
* 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "debugger.h"
|
|
#include "..\..\x6502.h"
|
|
#include "..\..\fceu.h"
|
|
#include "..\..\cart.h" //mbg merge 7/19/06 moved after fceu.h
|
|
#include "cdlogger.h"
|
|
#include "..\..\file.h"
|
|
#include "..\..\debug.h"
|
|
#include "tracer.h"
|
|
#include "..\..\memview.h"
|
|
|
|
//#define LOG_SKIP_UNMAPPED 4
|
|
//#define LOG_ADD_PERIODS 8
|
|
|
|
//int logaxy = 1, logopdata = 1; //deleteme
|
|
int logging_options = -1;
|
|
int log_update_window = 0;
|
|
//int tracer_open=0;
|
|
volatile int logtofile = 0, logging = 0;
|
|
HWND hTracer;
|
|
HFONT hlogFont, hlogNewFont;
|
|
int log_optn_intlst[LOG_OPTION_SIZE] = {10000,8000,6000,4000,2000,1000,700,400,200,100};
|
|
char *log_optn_strlst[LOG_OPTION_SIZE] = {"10000","8000","6000","4000","2000","1000","700","400","200","100"};
|
|
char *logfilename = 0;
|
|
int oldcodecount, olddatacount;
|
|
|
|
SCROLLINFO tracesi;
|
|
char **tracelogbuf;
|
|
int tracelogbufsize, tracelogbufpos;
|
|
int tracelogbufusedsize;
|
|
|
|
FILE *LOG_FP;
|
|
|
|
void ShowLogDirDialog(void);
|
|
void BeginLoggingSequence(void);
|
|
void LogInstruction(void);
|
|
void OutputLogLine(char *str);
|
|
void EndLoggingSequence(void);
|
|
//void PauseLoggingSequence(void);
|
|
void UpdateLogWindow(void);
|
|
void UpdateLogText(void);
|
|
void EnableTracerMenuItems(void);
|
|
int PromptForCDLogger(void);
|
|
|
|
BOOL CALLBACK TracerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
int i;
|
|
LOGFONT lf;
|
|
switch(uMsg) {
|
|
case WM_INITDIALOG:
|
|
//CenterWindow(hwndDlg);
|
|
hTracer = hwndDlg;
|
|
|
|
//setup font
|
|
hlogFont = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0);
|
|
GetObject(hlogFont, sizeof(LOGFONT), &lf);
|
|
strcpy(lf.lfFaceName,"Courier");
|
|
hlogNewFont = CreateFontIndirect(&lf);
|
|
SendDlgItemMessage(hwndDlg,100,WM_SETFONT,(WPARAM)hlogNewFont,FALSE);
|
|
|
|
//check the disabled radio button
|
|
CheckRadioButton(hwndDlg,103,104,103);
|
|
|
|
//EnableWindow(GetDlgItem(hwndDlg,101),FALSE);
|
|
//fill in the options for the log size
|
|
for(i = 0;i < LOG_OPTION_SIZE;i++){
|
|
SendDlgItemMessage(hwndDlg,105,CB_INSERTSTRING,-1,(LPARAM)(LPSTR)log_optn_strlst[i]);
|
|
}
|
|
SendDlgItemMessage(hwndDlg,105,CB_SETCURSEL,0,0);
|
|
SetDlgItemText(hwndDlg, 100, "Welcome to the Trace Logger.");
|
|
logtofile = 0;
|
|
|
|
if(logging_options == -1){
|
|
logging_options = (LOG_REGISTERS | LOG_PROCESSOR_STATUS);
|
|
CheckDlgButton(hwndDlg, 110, BST_CHECKED);
|
|
CheckDlgButton(hwndDlg, 111, BST_CHECKED);
|
|
} else{
|
|
if(logging_options&LOG_REGISTERS)CheckDlgButton(hwndDlg, 110, BST_CHECKED);
|
|
if(logging_options&LOG_PROCESSOR_STATUS)CheckDlgButton(hwndDlg, 111, BST_CHECKED);
|
|
}
|
|
EnableWindow(GetDlgItem(hwndDlg,105),TRUE);
|
|
EnableWindow(GetDlgItem(hwndDlg,112),FALSE);
|
|
|
|
if(log_update_window)CheckDlgButton(hwndDlg, 116, BST_CHECKED);
|
|
|
|
EnableTracerMenuItems();
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT:
|
|
if(logging)EndLoggingSequence();
|
|
DeleteObject(hlogNewFont);
|
|
logging_options &= 3;
|
|
hTracer = 0;
|
|
EndDialog(hwndDlg,0);
|
|
break;
|
|
case WM_COMMAND:
|
|
switch(HIWORD(wParam)) {
|
|
case BN_CLICKED:
|
|
switch(LOWORD(wParam)) {
|
|
case 102: //start logging
|
|
if(logging)EndLoggingSequence();
|
|
else BeginLoggingSequence();
|
|
EnableTracerMenuItems();
|
|
break;
|
|
case 103:
|
|
logtofile = 0;
|
|
EnableTracerMenuItems();
|
|
break;
|
|
case 104:
|
|
logtofile = 1;
|
|
EnableTracerMenuItems();
|
|
break;
|
|
case 110:
|
|
logging_options ^= LOG_REGISTERS;
|
|
break;
|
|
case 111:
|
|
logging_options ^= LOG_PROCESSOR_STATUS;
|
|
break;
|
|
case 114:
|
|
logging_options ^= LOG_NEW_INSTRUCTIONS;
|
|
if(logging && (!PromptForCDLogger())){
|
|
logging_options ^= LOG_NEW_INSTRUCTIONS; //turn it back off
|
|
CheckDlgButton(hTracer, 114, BST_UNCHECKED);
|
|
}
|
|
//EnableTracerMenuItems();
|
|
break;
|
|
case 115:
|
|
logging_options ^= LOG_NEW_DATA;
|
|
if(logging && (!PromptForCDLogger())){
|
|
logging_options ^= LOG_NEW_DATA; //turn it back off
|
|
CheckDlgButton(hTracer, 115, BST_UNCHECKED);
|
|
}
|
|
break;
|
|
case 116:
|
|
//todo: if this gets unchecked then we need to clear out the window
|
|
log_update_window ^= 1;
|
|
if(!FCEUI_EmulationPaused() && !log_update_window) //mbg merge 7/19/06 changed to use EmulationPaused()
|
|
SetDlgItemText(hTracer, 100, "Press F2 to pause the game, or snap \r\nthe debugger to update this window.\r\n");
|
|
//PauseLoggingSequence();
|
|
break;
|
|
case 112:
|
|
ShowLogDirDialog();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case WM_MOVING:
|
|
StopSound();
|
|
break;
|
|
}
|
|
|
|
|
|
//if (logging && !logtofile) {
|
|
switch(uMsg) {
|
|
case WM_VSCROLL:
|
|
if (lParam) {
|
|
//if ((!logging) || (logging && logtofile))break;
|
|
//if(!(logging && !logtofile))break;
|
|
if ((!logging) || logtofile) break;
|
|
|
|
if(!FCEUI_EmulationPaused() && !log_update_window) break; //mbg merge 7/19/06 changd to use EmulationPaused()
|
|
|
|
StopSound();
|
|
GetScrollInfo((HWND)lParam,SB_CTL,&tracesi);
|
|
switch(LOWORD(wParam)) {
|
|
case SB_ENDSCROLL:
|
|
case SB_TOP:
|
|
case SB_BOTTOM: break;
|
|
case SB_LINEUP: tracesi.nPos--; break;
|
|
case SB_LINEDOWN:tracesi.nPos++; break;
|
|
case SB_PAGEUP: tracesi.nPos-=tracesi.nPage; break;
|
|
case SB_PAGEDOWN: tracesi.nPos+=tracesi.nPage; break;
|
|
case SB_THUMBPOSITION: //break;
|
|
case SB_THUMBTRACK: tracesi.nPos = tracesi.nTrackPos; break;
|
|
}
|
|
if(tracesi.nPos < tracesi.nMin) tracesi.nPos = tracesi.nMin;
|
|
if((tracesi.nPos+(int)tracesi.nPage) > tracesi.nMax) tracesi.nPos = tracesi.nMax-(int)tracesi.nPage; //mbg merge 7/19/06 added casts
|
|
if(tracesi.nPos < 0)tracesi.nPos = 0; //this fixes a bad crash that occurs if you scroll up when only a few isntructions were logged
|
|
SetScrollInfo((HWND)lParam,SB_CTL,&tracesi,TRUE);
|
|
UpdateLogText();
|
|
}
|
|
break;
|
|
}
|
|
//}
|
|
return FALSE;
|
|
}
|
|
|
|
void BeginLoggingSequence(void){
|
|
char str[2048], str2[100];
|
|
int i, j;
|
|
|
|
if(!PromptForCDLogger())return; //do nothing if user selected no and CD Logger is needed
|
|
|
|
if(logtofile){
|
|
LOG_FP = fopen(logfilename,"w");
|
|
if(LOG_FP == NULL){
|
|
sprintf(str,"Error Opening File %s",logfilename);
|
|
MessageBox(hTracer,str, "File Error", MB_OK);
|
|
return;
|
|
}
|
|
fprintf(LOG_FP,FCEU_NAME_AND_VERSION" - Trace Log File\n"); //mbg merge 7/19/06 changed string
|
|
} else {
|
|
strcpy(str,"Allocating Memory...\r\n");
|
|
SetDlgItemText(hTracer, 100, str);
|
|
tracelogbufsize = j = log_optn_intlst[SendDlgItemMessage(hTracer,105,CB_GETCURSEL,0,0)];
|
|
tracelogbuf = (char**)malloc(j*sizeof(char *)); //mbg merge 7/19/06 added cast
|
|
for(i = 0;i < j;i++){
|
|
tracelogbuf[i] = (char*)malloc(80); //mbg merge 7/19/06 added cast
|
|
tracelogbuf[i][0] = 0;
|
|
}
|
|
sprintf(str2,"%d Bytes Allocated...\r\n",j*80);
|
|
strcat(str,str2);
|
|
strcat(str,"Press F2 to pause the game, or snap \r\nthe debugger to update this window.\r\n");
|
|
SetDlgItemText(hTracer, 100, str);
|
|
tracelogbufpos = tracelogbufusedsize = 0;
|
|
}
|
|
|
|
oldcodecount = codecount;
|
|
olddatacount = datacount;
|
|
|
|
logging=1;
|
|
SetDlgItemText(hTracer, 102,"Stop Logging");
|
|
return;
|
|
}
|
|
/*
|
|
void LogInstructionOld(){
|
|
char str[96], chr[32];
|
|
int addr=X.PC;
|
|
int size, j;
|
|
uint8 opcode[3];
|
|
|
|
sprintf(str, "$%04X:", addr);
|
|
if ((size = opsize[GetMem(addr)]) == 0) {
|
|
sprintf(chr, "%02X UNDEFINED", GetMem(addr)); addr++;
|
|
strcat(str,chr);
|
|
}
|
|
else {
|
|
if ((addr+size) > 0xFFFF) {
|
|
sprintf(chr, "%02X OVERFLOW", GetMem(addr));
|
|
strcat(str,chr);
|
|
goto done;
|
|
}
|
|
for (j = 0; j < size; j++) {
|
|
sprintf(chr, "%02X ", opcode[j] = GetMem(addr)); addr++;
|
|
strcat(str,chr);
|
|
}
|
|
while (size < 3) {
|
|
strcat(str," "); //pad output to align ASM
|
|
size++;
|
|
}
|
|
strcat(strcat(str," "),BinToASM(addr,opcode));
|
|
}
|
|
done:
|
|
strcat(str,"\n");
|
|
if(logtofile){
|
|
fprintf(LOG_FP,str);
|
|
}
|
|
}*/
|
|
|
|
//todo: really speed this up
|
|
void FCEUD_TraceInstruction(){
|
|
if(!logging) return;
|
|
|
|
char address[7], data[11], disassembly[28], axystate[16], procstatus[12];
|
|
char str[96];
|
|
int addr=X.PC;
|
|
int size, j;
|
|
uint8 opcode[3], tmp;
|
|
static int unloggedlines;
|
|
|
|
if(((logging_options & LOG_NEW_INSTRUCTIONS) && (oldcodecount != codecount)) ||
|
|
((logging_options & LOG_NEW_DATA) && (olddatacount != datacount))){//something new was logged
|
|
oldcodecount = codecount;
|
|
olddatacount = datacount;
|
|
if(unloggedlines > 0){
|
|
sprintf(str,"(%d lines skipped)",unloggedlines);
|
|
OutputLogLine(str);
|
|
unloggedlines = 0;
|
|
}
|
|
} else {
|
|
if((logging_options & LOG_NEW_INSTRUCTIONS) ||
|
|
(logging_options & LOG_NEW_DATA)){
|
|
if(FCEUI_GetLoggingCD())unloggedlines++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
sprintf(address, "$%04X:", addr);
|
|
axystate[0] = str[0] = 0;
|
|
size = opsize[GetMem(addr)];
|
|
|
|
if ((addr+size) > 0xFFFF){
|
|
sprintf(data, "%02X ", GetMem(addr&0xFFFF));
|
|
sprintf(disassembly,"OVERFLOW");
|
|
} else {
|
|
switch(size){
|
|
case 0:
|
|
sprintf(data, "%02X ", GetMem(addr));
|
|
sprintf(disassembly,"UNDEFINED");
|
|
break;
|
|
case 1:
|
|
opcode[0]=GetMem(addr++);
|
|
sprintf(data, "%02X ", opcode[0]);
|
|
strcpy(disassembly,BinToASM(addr,opcode));
|
|
break;
|
|
case 2:
|
|
opcode[0]=GetMem(addr++);
|
|
opcode[1]=GetMem(addr++);
|
|
sprintf(data, "%02X %02X ", opcode[0],opcode[1]);
|
|
strcpy(disassembly,BinToASM(addr,opcode));
|
|
break;
|
|
case 3:
|
|
opcode[0]=GetMem(addr++);
|
|
opcode[1]=GetMem(addr++);
|
|
opcode[2]=GetMem(addr++);
|
|
sprintf(data, "%02X %02X %02X ", opcode[0],opcode[1],opcode[2]);
|
|
strcpy(disassembly,BinToASM(addr,opcode));
|
|
break;
|
|
}
|
|
}
|
|
//stretch the disassembly string out if we have to output other stuff.
|
|
if(logging_options & (LOG_REGISTERS|LOG_PROCESSOR_STATUS)){
|
|
for(j = strlen(disassembly);j < 27;j++)disassembly[j] = ' ';
|
|
disassembly[27] = 0;
|
|
}
|
|
|
|
if(logging_options & LOG_REGISTERS){
|
|
sprintf(axystate,"A:%02X X:%02X Y:%02X",(X.A),(X.X),(X.Y));
|
|
}
|
|
|
|
if(logging_options & LOG_PROCESSOR_STATUS){
|
|
tmp = X.P^0xFF;
|
|
sprintf(procstatus,"P:%c%c%c%c%c%c%c%c",
|
|
'N'|(tmp&0x80)>>2,
|
|
'V'|(tmp&0x40)>>1,
|
|
'U'|(tmp&0x20),
|
|
'B'|(tmp&0x10)<<1,
|
|
'D'|(tmp&0x08)<<2,
|
|
'I'|(tmp&0x04)<<3,
|
|
'Z'|(tmp&0x02)<<4,
|
|
'C'|(tmp&0x01)<<5
|
|
);
|
|
}
|
|
|
|
|
|
strcat(str,address);
|
|
strcat(str,data);
|
|
strcat(str,disassembly);
|
|
if(logging_options & LOG_REGISTERS)strcat(str,axystate);
|
|
if((logging_options & LOG_REGISTERS) && (logging_options & LOG_PROCESSOR_STATUS))strcat(str," ");
|
|
if(logging_options & LOG_PROCESSOR_STATUS)strcat(str,procstatus);
|
|
|
|
OutputLogLine(str);
|
|
|
|
return;
|
|
}
|
|
|
|
void OutputLogLine(char *str){
|
|
if(logtofile){
|
|
strcat(str,"\n");
|
|
fputs(str,LOG_FP);
|
|
fflush(LOG_FP);
|
|
}else{
|
|
strcat(str,"\r\n");
|
|
if(strlen(str) < 80)strcpy(tracelogbuf[tracelogbufpos],str);
|
|
tracelogbufpos++;
|
|
if(tracelogbufusedsize < tracelogbufsize)tracelogbufusedsize++;
|
|
tracelogbufpos%=tracelogbufsize;
|
|
}
|
|
}
|
|
|
|
void EndLoggingSequence(void){
|
|
int j, i;
|
|
if(logtofile){
|
|
fclose(LOG_FP);
|
|
} else {
|
|
j = tracelogbufsize;
|
|
for(i = 0;i < j;i++){
|
|
free(tracelogbuf[i]);
|
|
}
|
|
free(tracelogbuf);
|
|
SetDlgItemText(hTracer, 100, "Welcome to the Trace Logger.");
|
|
}
|
|
logging=0;
|
|
SetDlgItemText(hTracer, 102,"Start Logging");
|
|
|
|
}
|
|
|
|
//void PauseLoggingSequence(void){
|
|
void UpdateLogWindow(void){
|
|
|
|
//if((tracelogbufpos == 0) || (tracelogbuf[tracelogbufpos][0]))
|
|
// tracesi.nMax = tracelogbufsize;
|
|
//else tracesi.nMax = tracelogbufpos;
|
|
|
|
//todo: fix this up.
|
|
//if(!log_update_window && !userpause){
|
|
// SetDlgItemText(hTracer, 100, "Press F2 to pause the game, or snap \r\nthe debugger to update this window.\r\n");
|
|
// return;
|
|
//}
|
|
|
|
//
|
|
|
|
//we don't want to continue if the trace logger isn't logging, or if its logging to a file.
|
|
if((!logging) || logtofile)return;
|
|
|
|
//if the game isn't paused, and the option to update the log window while running isn't checked, then halt here.
|
|
if(!FCEUI_EmulationPaused() && !log_update_window){ //mbg merge 7/19/06 changd to use EmulationPaused()
|
|
return;
|
|
}
|
|
|
|
tracesi.cbSize = sizeof(SCROLLINFO);
|
|
tracesi.fMask = SIF_ALL;
|
|
tracesi.nPage = 21;
|
|
tracesi.nMin = 0;
|
|
tracesi.nMax = tracelogbufusedsize; //todo: try -2
|
|
tracesi.nPos = tracesi.nMax-tracesi.nPage;
|
|
if (tracesi.nPos < tracesi.nMin) tracesi.nPos = tracesi.nMin;
|
|
SetScrollInfo(GetDlgItem(hTracer,101),SB_CTL,&tracesi,TRUE);
|
|
UpdateLogText();
|
|
|
|
return;
|
|
}
|
|
|
|
void UpdateLogText(void){
|
|
int i, j;
|
|
char str[2048];
|
|
str[0] = 0;
|
|
/*
|
|
for(i = 21;i > 0;i--){
|
|
j = tracelogbufpos-i-1;
|
|
if((tracelogbufusedsize == tracelogbufsize) && (j < 0))j = tracelogbufsize+j;
|
|
if(j >= 0)strcat(str,tracelogbuf[j]);
|
|
}
|
|
*/
|
|
|
|
for(i = tracesi.nPos;i < min(tracesi.nMax,tracesi.nPos+21);i++){
|
|
j = i;
|
|
if(tracelogbufusedsize == tracelogbufsize){
|
|
j = (tracelogbufpos+i)%tracelogbufsize;
|
|
}
|
|
strcat(str,tracelogbuf[j]);
|
|
}
|
|
SetDlgItemText(hTracer, 100, str);
|
|
sprintf(str,"nPage = %d, nPos = %d, nMax = %d, nMin = %d",tracesi.nPage,tracesi.nPos,tracesi.nMax,tracesi.nMin);
|
|
SetDlgItemText(hTracer, 1002, str);
|
|
return;
|
|
}
|
|
|
|
void EnableTracerMenuItems(void){
|
|
|
|
//if(logging_options & LOG_NEW_INSTRUCTIONS){
|
|
//EnableWindow(GetDlgItem(hTracer,115),TRUE);
|
|
//} else {
|
|
// CheckDlgButton(hTracer, 115, BST_UNCHECKED);
|
|
//EnableWindow(GetDlgItem(hTracer,115),FALSE);
|
|
//}
|
|
|
|
if(logging){
|
|
EnableWindow(GetDlgItem(hTracer,103),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,104),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,105),FALSE);
|
|
//EnableWindow(GetDlgItem(hTracer,110),FALSE);
|
|
//EnableWindow(GetDlgItem(hTracer,111),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,112),FALSE);
|
|
//EnableWindow(GetDlgItem(hTracer,114),FALSE);
|
|
//EnableWindow(GetDlgItem(hTracer,115),FALSE);
|
|
return;
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hTracer,103),TRUE);
|
|
EnableWindow(GetDlgItem(hTracer,104),TRUE);
|
|
EnableWindow(GetDlgItem(hTracer,105),TRUE);
|
|
//EnableWindow(GetDlgItem(hTracer,110),TRUE);
|
|
//EnableWindow(GetDlgItem(hTracer,111),TRUE); //uncomment me
|
|
EnableWindow(GetDlgItem(hTracer,112),TRUE);
|
|
EnableWindow(GetDlgItem(hTracer,114),TRUE);
|
|
|
|
if(logtofile){
|
|
EnableWindow(GetDlgItem(hTracer,105),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,112),TRUE);
|
|
CheckDlgButton(hTracer, 116, BST_UNCHECKED);
|
|
log_update_window = 0;
|
|
EnableWindow(GetDlgItem(hTracer,116),FALSE);
|
|
} else{
|
|
EnableWindow(GetDlgItem(hTracer,105),TRUE);
|
|
EnableWindow(GetDlgItem(hTracer,112),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,116),TRUE);
|
|
}
|
|
|
|
/*
|
|
if(FCEUI_GetLoggingCD()){
|
|
EnableWindow(GetDlgItem(hTracer,114),TRUE);
|
|
if(logging_options & LOG_NEW_INSTRUCTIONS){
|
|
EnableWindow(GetDlgItem(hTracer,115),TRUE);
|
|
} else EnableWindow(GetDlgItem(hTracer,115),FALSE);
|
|
}
|
|
else{
|
|
EnableWindow(GetDlgItem(hTracer,114),FALSE);
|
|
EnableWindow(GetDlgItem(hTracer,115),FALSE);
|
|
CheckDlgButton(hTracer, 114, BST_UNCHECKED);
|
|
CheckDlgButton(hTracer, 115, BST_UNCHECKED);
|
|
logging_options &= 3;
|
|
}
|
|
*/
|
|
return;
|
|
}
|
|
|
|
//this returns 1 if the CD logger is activated when needed, or 0 if the user selected no, not to activate it
|
|
int PromptForCDLogger(void){
|
|
if((logging_options & (LOG_NEW_INSTRUCTIONS|LOG_NEW_DATA)) && (!FCEUI_GetLoggingCD())){
|
|
StopSound();
|
|
if(MessageBox(hTracer,"In order for some of the features you have selected to take effect,\
|
|
the Code/Data Logger must also be running.\
|
|
Would you like to Start the Code/Data Logger Now?","Start Code/Data Logger?",
|
|
MB_YESNO) == IDYES){
|
|
DoCDLogger();
|
|
FCEUI_SetLoggingCD(1);
|
|
//EnableTracerMenuItems();
|
|
SetDlgItemText(hCDLogger, 105, "Pause");
|
|
return 1;
|
|
}
|
|
return 0; //user selected no so 0 is returned
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void ShowLogDirDialog(void){
|
|
const char filter[]="6502 Trace Log File(*.log,*.txt)\0*.log;*.txt\0";
|
|
char nameo[2048];
|
|
OPENFILENAME ofn;
|
|
StopSound();
|
|
memset(&ofn,0,sizeof(ofn));
|
|
ofn.lStructSize=sizeof(ofn);
|
|
ofn.hInstance=fceu_hInstance;
|
|
ofn.lpstrTitle="Log Trace As...";
|
|
ofn.lpstrFilter=filter;
|
|
nameo[0]=0;
|
|
ofn.lpstrFile=nameo;
|
|
ofn.nMaxFile=256;
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
ofn.hwndOwner = hTracer;
|
|
GetSaveFileName(&ofn);
|
|
if(nameo[0]){
|
|
if(logfilename)free(logfilename);
|
|
logfilename = (char*)malloc(strlen(nameo)+1); //mbg merge 7/19/06 added cast
|
|
strcpy(logfilename,nameo);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void DoTracer(){
|
|
|
|
if (!GI) {
|
|
FCEUD_PrintError("You must have a game loaded before you can use the Trace Logger.");
|
|
return;
|
|
}
|
|
if (GI->type==GIT_NSF) { //todo: NSF support!
|
|
FCEUD_PrintError("Sorry, you can't yet use the Trace Logger with NSFs.");
|
|
return;
|
|
}
|
|
|
|
if(!hTracer){
|
|
CreateDialog(fceu_hInstance,"TRACER",NULL,TracerCallB);
|
|
//hTracer gets set in WM_INITDIALOG
|
|
} else {
|
|
SetWindowPos(hTracer,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
|
}
|
|
}
|