2006-07-19 05:57:00 +00:00
|
|
|
/* 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 "..\..\fceu.h"
|
|
|
|
#include "..\..\cart.h" //mbg merge 7/18/06 moved beneath fceu.h
|
|
|
|
#include "..\..\x6502.h"
|
2006-07-24 04:18:46 +00:00
|
|
|
#include "..\..\debug.h"
|
|
|
|
#include "debugger.h"
|
2006-07-24 04:58:44 +00:00
|
|
|
#include "tracer.h"
|
2006-07-24 04:18:46 +00:00
|
|
|
#include "cdlogger.h"
|
2006-07-19 05:57:00 +00:00
|
|
|
|
|
|
|
#define INESPRIV
|
|
|
|
#include "..\..\ines.h"
|
|
|
|
|
|
|
|
void LoadCDLogFile();
|
|
|
|
void SaveCDLogFileAs();
|
|
|
|
void SaveCDLogFile();
|
|
|
|
void SaveStrippedRom();
|
|
|
|
|
|
|
|
extern iNES_HEADER head; //defined in ines.c
|
|
|
|
extern uint8 *trainerpoo;
|
|
|
|
//extern uint8 *ROM;
|
|
|
|
//extern uint8 *VROM;
|
|
|
|
|
2006-07-24 04:18:46 +00:00
|
|
|
//volatile int loggingcodedata;
|
2006-07-19 05:57:00 +00:00
|
|
|
//int cdlogger_open;
|
2006-07-24 04:18:46 +00:00
|
|
|
|
|
|
|
HWND hCDLogger;
|
|
|
|
char loadedcdfile[1024];
|
|
|
|
|
2006-07-19 05:57:00 +00:00
|
|
|
|
|
|
|
BOOL CALLBACK CDLoggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
|
|
switch(uMsg) {
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
hCDLogger = hwndDlg;
|
|
|
|
codecount = datacount = 0;
|
|
|
|
undefinedcount = PRGsize[0];
|
|
|
|
cdloggerdata = (unsigned char*)malloc(PRGsize[0]); //mbg merge 7/18/06 added cast
|
|
|
|
ZeroMemory(cdloggerdata,PRGsize[0]);
|
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
|
|
case WM_QUIT:
|
|
|
|
if((logging) && (logging_options & LOG_NEW_INSTRUCTIONS)){
|
|
|
|
StopSound();
|
|
|
|
MessageBox(hCDLogger,
|
|
|
|
"The Trace logger is currently using this for some of its features.\
|
|
|
|
Please turn the trace logger off and try again.","Unable to Pause Code/Data Logger",
|
|
|
|
MB_OK);
|
|
|
|
break;
|
|
|
|
}
|
2006-07-24 04:18:46 +00:00
|
|
|
FCEUI_SetLoggingCD(0);
|
2006-07-19 05:57:00 +00:00
|
|
|
free(cdloggerdata);
|
|
|
|
cdloggerdata=0;
|
|
|
|
hCDLogger = 0;
|
|
|
|
EndDialog(hwndDlg,0);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch(HIWORD(wParam)) {
|
|
|
|
case BN_CLICKED:
|
|
|
|
switch(LOWORD(wParam)) {
|
|
|
|
case 103:
|
|
|
|
codecount = datacount = 0;
|
|
|
|
undefinedcount = PRGsize[0];
|
|
|
|
ZeroMemory(cdloggerdata,PRGsize[0]);
|
|
|
|
UpdateCDLogger();
|
|
|
|
break;
|
|
|
|
case 104:
|
|
|
|
LoadCDLogFile();
|
|
|
|
break;
|
|
|
|
case 105:
|
2006-07-24 04:18:46 +00:00
|
|
|
if(FCEUI_GetLoggingCD()){
|
2006-07-19 05:57:00 +00:00
|
|
|
if((logging) && (logging_options & LOG_NEW_INSTRUCTIONS)){
|
|
|
|
MessageBox(hCDLogger,
|
|
|
|
"The Trace logger is currently using this for some of its features.\
|
|
|
|
Please turn the trace logger off and try again.","Unable to Pause Code/Data Logger",
|
|
|
|
MB_OK);
|
|
|
|
break;
|
|
|
|
}
|
2006-07-24 04:18:46 +00:00
|
|
|
FCEUI_SetLoggingCD(0);
|
2006-07-19 05:57:00 +00:00
|
|
|
EnableTracerMenuItems();
|
|
|
|
SetDlgItemText(hCDLogger, 105, "Start");
|
|
|
|
}
|
|
|
|
else{
|
2006-07-24 04:18:46 +00:00
|
|
|
FCEUI_SetLoggingCD(1);
|
2006-07-19 05:57:00 +00:00
|
|
|
EnableTracerMenuItems();
|
|
|
|
SetDlgItemText(hCDLogger, 105, "Pause");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 106:
|
|
|
|
SaveCDLogFileAs();
|
|
|
|
break;
|
|
|
|
case 107:
|
|
|
|
SaveCDLogFile();
|
|
|
|
break;
|
|
|
|
case 108:
|
|
|
|
SaveStrippedRom();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_MOVING:
|
|
|
|
StopSound();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadCDLogFile(){
|
|
|
|
FILE *FP;
|
|
|
|
int i, j;
|
|
|
|
const char filter[]="Code Data Log File(*.CDL)\0*.cdl\0";
|
|
|
|
char nameo[2048]; //todo: possibly no need for this? can lpstrfilter point to loadedcdfile instead?
|
|
|
|
OPENFILENAME ofn;
|
|
|
|
StopSound();
|
|
|
|
memset(&ofn,0,sizeof(ofn));
|
|
|
|
ofn.lStructSize=sizeof(ofn);
|
|
|
|
ofn.hInstance=fceu_hInstance;
|
|
|
|
ofn.lpstrTitle="Load Code Data Log File...";
|
|
|
|
ofn.lpstrFilter=filter;
|
|
|
|
nameo[0]=0;
|
|
|
|
ofn.lpstrFile=nameo;
|
|
|
|
ofn.nMaxFile=256;
|
|
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
|
|
ofn.hwndOwner = hCDLogger;
|
|
|
|
if(!GetOpenFileName(&ofn))return;
|
|
|
|
strcpy(loadedcdfile,nameo);
|
|
|
|
//FCEUD_PrintError(loadedcdfile);
|
|
|
|
|
|
|
|
//fseek(FP,0,SEEK_SET);
|
|
|
|
//codecount = datacount = 0;
|
|
|
|
//undefinedcount = PRGsize[0];
|
|
|
|
|
|
|
|
//cdloggerdata = malloc(PRGsize[0]);
|
|
|
|
|
|
|
|
|
|
|
|
FP = fopen(loadedcdfile,"rb");
|
|
|
|
if(FP == NULL){
|
|
|
|
FCEUD_PrintError("Error Opening File");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//codecount = datacount = 0;
|
|
|
|
//undefinedcount = PRGsize[0];
|
|
|
|
|
|
|
|
for(i = 0;i < (int)PRGsize[0];i++){
|
|
|
|
j = fgetc(FP);
|
|
|
|
if(j == EOF)break;
|
|
|
|
if((j & 1) && !(cdloggerdata[i] & 1))codecount++; //if the new byte has something logged and
|
|
|
|
if((j & 2) && !(cdloggerdata[i] & 2))datacount++; //and the old one doesn't. Then increment
|
|
|
|
if((j & 3) && !(cdloggerdata[i] & 3))undefinedcount--; //the appropriate counter.
|
|
|
|
cdloggerdata[i] |= j;
|
|
|
|
}
|
|
|
|
fclose(FP);
|
|
|
|
UpdateCDLogger();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveCDLogFileAs(){
|
|
|
|
const char filter[]="Code Data Log File(*.CDL)\0*.cdl\0";
|
|
|
|
char nameo[2048]; //todo: possibly no need for this? can lpstrfilter point to loadedcdfile instead?
|
|
|
|
OPENFILENAME ofn;
|
|
|
|
StopSound();
|
|
|
|
memset(&ofn,0,sizeof(ofn));
|
|
|
|
ofn.lStructSize=sizeof(ofn);
|
|
|
|
ofn.hInstance=fceu_hInstance;
|
|
|
|
ofn.lpstrTitle="Save Code Data Log File As...";
|
|
|
|
ofn.lpstrFilter=filter;
|
|
|
|
nameo[0]=0;
|
|
|
|
ofn.lpstrFile=nameo;
|
|
|
|
ofn.nMaxFile=256;
|
|
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
|
|
ofn.hwndOwner = hCDLogger;
|
|
|
|
if(!GetSaveFileName(&ofn))return;
|
|
|
|
strcpy(loadedcdfile,nameo);
|
|
|
|
SaveCDLogFile();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveCDLogFile(){ //todo make this button work before you've saved as
|
|
|
|
FILE *FP;
|
|
|
|
//if(loadedcdfile[0] == 0)SaveCDLogFileAs();
|
|
|
|
//FCEUD_PrintError(loadedcdfile);
|
|
|
|
|
|
|
|
FP = fopen(loadedcdfile,"wb");
|
|
|
|
if(FP == NULL){
|
|
|
|
FCEUD_PrintError("Error Opening File");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fwrite(cdloggerdata,PRGsize[0],1,FP);
|
|
|
|
fclose(FP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DoCDLogger(){
|
|
|
|
if (!GI) {
|
|
|
|
FCEUD_PrintError("You must have a game loaded before you can use the Code Data Logger.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (GI->type==GIT_NSF) { //todo: NSF support!
|
|
|
|
FCEUD_PrintError("Sorry, you can't yet use the Code Data Logger with NSFs.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!hCDLogger){
|
|
|
|
CreateDialog(fceu_hInstance,"CDLOGGER",NULL,CDLoggerCallB);
|
|
|
|
} else {
|
|
|
|
SetWindowPos(hCDLogger,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateCDLogger(){
|
|
|
|
char str[50];
|
|
|
|
float fcodecount = codecount, fdatacount = datacount,
|
|
|
|
fundefinedcount = undefinedcount, fromsize = PRGsize[0];
|
|
|
|
if(!hCDLogger)return;
|
|
|
|
sprintf(str,"0x%06x %.2f%%",codecount,fcodecount/fromsize*100);
|
|
|
|
SetDlgItemText(hCDLogger,100,str);
|
|
|
|
sprintf(str,"0x%06x %.2f%%",datacount,fdatacount/fromsize*100);
|
|
|
|
SetDlgItemText(hCDLogger,101,str);
|
|
|
|
sprintf(str,"0x%06x %.2f%%",undefinedcount,fundefinedcount/fromsize*100);
|
|
|
|
SetDlgItemText(hCDLogger,102,str);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogPCM(int romaddress){
|
|
|
|
int i = GetPRGAddress(romaddress);
|
|
|
|
if(i == -1)return;
|
|
|
|
if(cdloggerdata[i] & 0x40)return;
|
|
|
|
cdloggerdata[i] |= 0x40;
|
|
|
|
|
|
|
|
if(!(cdloggerdata[i] & 2)){
|
|
|
|
datacount++;
|
|
|
|
cdloggerdata[i] |= 2;
|
|
|
|
if(!(cdloggerdata[i] & 1))undefinedcount--;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveStrippedRom(){ //this is based off of iNesSave()
|
|
|
|
//todo: make this support nsfs
|
|
|
|
const char filter[]="Stripped iNes Rom file(*.NES)\0*.nes\0";
|
|
|
|
char sromfilename[MAX_PATH];
|
|
|
|
FILE *fp;
|
|
|
|
OPENFILENAME ofn;
|
|
|
|
int i;
|
|
|
|
if(codecount == 0){
|
|
|
|
MessageBox(NULL, "Unable to Generate Stripped Rom. Get Something Logged and try again.", "Error", MB_OK);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
StopSound();
|
|
|
|
memset(&ofn,0,sizeof(ofn));
|
|
|
|
ofn.lStructSize=sizeof(ofn);
|
|
|
|
ofn.hInstance=fceu_hInstance;
|
|
|
|
ofn.lpstrTitle="Save Stripped Rom File As...";
|
|
|
|
ofn.lpstrFilter=filter;
|
|
|
|
sromfilename[0]=0;
|
|
|
|
ofn.lpstrFile=sromfilename;
|
|
|
|
ofn.nMaxFile=256;
|
|
|
|
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
|
|
|
|
ofn.hwndOwner = hCDLogger;
|
|
|
|
if(!GetSaveFileName(&ofn))return;
|
|
|
|
|
|
|
|
fp = fopen(sromfilename,"wb");
|
|
|
|
|
|
|
|
if(fwrite(&head,1,16,fp)!=16)return;
|
|
|
|
|
|
|
|
if(head.ROM_type&4) /* Trainer */
|
|
|
|
{
|
|
|
|
fwrite(trainerpoo,512,1,fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0;i < head.ROM_size*0x4000;i++){
|
|
|
|
if(cdloggerdata[i] & 3)fputc(ROM[i],fp);
|
|
|
|
else fputc(0,fp);
|
|
|
|
}
|
|
|
|
//fwrite(ROM,0x4000,head.ROM_size,fp);
|
|
|
|
|
|
|
|
if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);
|
|
|
|
fclose(fp);
|
|
|
|
}
|