diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index c126c4d1..5011c1ba 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -38,6 +38,7 @@ #include "../../debug.h" #include "input.h" #include "netplay.h" +#include "memwatch.h" #include "joystick.h" #include "keyboard.h" #include "ppuview.h" @@ -415,12 +416,6 @@ static void DriverKill(void) ByebyeWindow(); } -//mbg merge 7/18/06 - the function that contains the code that used to just be UpdateMemWatch() -void _updateMemWatch() { - //UpdateMemWatch() - //but soon we will do more! -} - #ifdef _USE_SHARED_MEMORY_ HANDLE mapGameMemBlock; HANDLE mapRAM; @@ -716,6 +711,7 @@ void _updateWindow() UpdateMemoryView(0); UpdateCDLogger(); UpdateLogWindow(); + UpdateMemWatch(); NTViewDoBlit(0); } diff --git a/src/drivers/win/memwatch.cpp b/src/drivers/win/memwatch.cpp new file mode 100644 index 00000000..d11c7005 --- /dev/null +++ b/src/drivers/win/memwatch.cpp @@ -0,0 +1,451 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 Luke Gustafson + * + * 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 "memwatch.h" + +static HWND hwndMemWatch=0; +static char addresses[24][16]; +static char labels[24][24]; +static int NeedsInit = 1; +char *MemWatchDir = 0; + +static char *U8ToStr(uint8 a) +{ + static char TempArray[8]; + TempArray[0] = '0' + a/100; + TempArray[1] = '0' + (a%100)/10; + TempArray[2] = '0' + (a%10); + TempArray[3] = 0; + return TempArray; +} + + +//I don't trust scanf for speed +static uint16 FastStrToU16(char* s) +{ + int i; + uint16 v=0; + for(i=0; i < 4; i++) + { + if(s[i] == 0) return v; + v<<=4; + if(s[i] >= '0' && s[i] <= '9') + { + v+=s[i]-'0'; + } + else if(s[i] >= 'a' && s[i] <= 'f') + { + v+=s[i]-'a'+10; + } + else if(s[i] >= 'A' && s[i] <= 'F') + { + v+=s[i]-'A'+10; + } + else + { + return 0xFFFF; + } + } + return v; +} + +static char *U16ToDecStr(uint16 a) +{ + static char TempArray[8]; + TempArray[0] = '0' + a/10000; + TempArray[1] = '0' + (a%10000)/1000; + TempArray[2] = '0' + (a%1000)/100; + TempArray[3] = '0' + (a%100)/10; + TempArray[4] = '0' + (a%10); + TempArray[5] = 0; + return TempArray; +} + +//sorry this is hard to read... but I don't trust printf for speed! +static char *U16ToHexStr(uint16 a) +{ + static char TempArray[8]; + TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096; + TempArray[1] = (a%4096)/256 > 9?'A'+(a%4096)/256 - 10:'0' + (a%4096)/256; + TempArray[2] = (a%256)/16 > 9?'A'+(a%256)/16 - 10:'0' + (a%256)/16; + TempArray[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16); + TempArray[4] = 0; + return TempArray; +} + +static char *U8ToHexStr(uint8 a) +{ + static char TempArray[8]; + TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16; + TempArray[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16); + TempArray[2] = 0; + return TempArray; +} + +//Update the values in the Memory Watch window +void UpdateMemWatch() +{ + if(hwndMemWatch) + { + char TempArray[16]; + int i, twobytes, hex; + uint16 a; + for(i = 0; i < 24; i++) + { + GetDlgItemText(hwndMemWatch,1001+i*3,TempArray,16); + twobytes=0; + hex = 0; + TempArray[15]=0; + switch(TempArray[0]) + { + case 0: + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)"---"); + continue; + case '!': + twobytes=1; + a=FastStrToU16(TempArray+1); + break; + case 'x': + hex = 1; + a=FastStrToU16(TempArray+1); + break; + case 'X': + hex = twobytes = 1; + a = FastStrToU16(TempArray+1); + break; + default: + a=FastStrToU16(TempArray); + break; + } + if(a != 0xFFFF) + { + if(hex == 0) + { + if(twobytes == 0) + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToStr(ARead[a](a))); + } + else + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToDecStr(ARead[a](a)+256*ARead[a+1](a+1))); + } + } + else + { + if(twobytes == 0) + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToHexStr(ARead[a](a))); + } + else + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToHexStr(ARead[a](a)+256*ARead[a+1](a+1))); + } + } + } + else + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)"---"); + } + } + } +} + +//Save labels/addresses so next time dialog is opened, +//you don't lose what you've entered. +static void SaveStrings() +{ + int i; + for(i=0;i<24;i++) + { + GetDlgItemText(hwndMemWatch,1001+i*3,addresses[i],16); + GetDlgItemText(hwndMemWatch,1000+i*3,labels[i],24); + } +} + +//replaces spaces with a dummy character +static void TakeOutSpaces(int i) +{ + int j; + for(j=0;j<16;j++) + { + if(addresses[i][j] == ' ') addresses[i][j] = '|'; + if(labels[i][j] == ' ') labels[i][j] = '|'; + } + for(;j<24;j++) + { + if(labels[i][j] == ' ') labels[i][j] = '|'; + } +} + +//replaces dummy characters with spaces +static void PutInSpaces(int i) +{ + int j; + for(j=0;j<16;j++) + { + if(addresses[i][j] == '|') addresses[i][j] = ' '; + if(labels[i][j] == '|') labels[i][j] = ' '; + } + for(;j<24;j++) + { + if(labels[i][j] == '|') labels[i][j] = ' '; + } +} + +//Saves all the addresses and labels to disk +static void SaveMemWatch() +{ + const char filter[]="Memory address list(*.txt)\0*.txt\0"; + char nameo[2048]; + OPENFILENAME ofn; + memset(&ofn,0,sizeof(ofn)); + ofn.lStructSize=sizeof(ofn); + ofn.hInstance=fceu_hInstance; + ofn.lpstrTitle="Save Memory Watch As..."; + ofn.lpstrFilter=filter; + nameo[0]=0; + ofn.lpstrFile=nameo; + ofn.nMaxFile=256; + ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT; + ofn.lpstrInitialDir=MemWatchDir; + if(GetSaveFileName(&ofn)) + { + int i; + + //Save the directory + if(ofn.nFileOffset < 1024) + { + free(MemWatchDir); + MemWatchDir=(char*)malloc(strlen(ofn.lpstrFile)+1); + strcpy(MemWatchDir,ofn.lpstrFile); + MemWatchDir[ofn.nFileOffset]=0; + } + + //quick get length of nameo + for(i=0;i<2048;i++) + { + if(nameo[i] == 0) + { + break; + } + } + + //add .txt if nameo doesn't have it + if((i < 4 || nameo[i-4] != '.') && i < 2040) + { + nameo[i] = '.'; + nameo[i+1] = 't'; + nameo[i+2] = 'x'; + nameo[i+3] = 't'; + nameo[i+4] = 0; + } + + SaveStrings(); + FILE *fp=FCEUD_UTF8fopen(nameo,"w"); + for(i=0;i<24;i++) + { + //Use dummy strings to fill empty slots + if(labels[i][0] == 0) + { + labels[i][0] = '|'; + labels[i][1] = 0; + } + if(addresses[i][0] == 0) + { + addresses[i][0] = '|'; + addresses[i][1] = 0; + } + //spaces can be a problem for scanf so get rid of them + TakeOutSpaces(i); + fprintf(fp, "%s %s\n", addresses[i], labels[i]); + PutInSpaces(i); + } + fclose(fp); + } +} + +//Loads a previously saved file +static void LoadMemWatch() +{ + const char filter[]="Memory address list(*.txt)\0*.txt\0"; + char nameo[2048]; + OPENFILENAME ofn; + memset(&ofn,0,sizeof(ofn)); + ofn.lStructSize=sizeof(ofn); + ofn.hInstance=fceu_hInstance; + ofn.lpstrTitle="Load Memory Watch..."; + ofn.lpstrFilter=filter; + nameo[0]=0; + ofn.lpstrFile=nameo; + ofn.nMaxFile=256; + ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; + ofn.lpstrInitialDir=MemWatchDir; + + if(GetOpenFileName(&ofn)) + { + int i,j; + + //Save the directory + if(ofn.nFileOffset < 1024) + { + free(MemWatchDir); + MemWatchDir=(char*)malloc(strlen(ofn.lpstrFile)+1); + strcpy(MemWatchDir,ofn.lpstrFile); + MemWatchDir[ofn.nFileOffset]=0; + } + + FILE *fp=FCEUD_UTF8fopen(nameo,"r"); + for(i=0;i<24;i++) + { + fscanf(fp, "%s ", nameo); //re-using nameo--bady style :P + for(j = 0; j < 16; j++) + addresses[i][j] = nameo[j]; + fscanf(fp, "%s\n", nameo); + for(j = 0; j < 24; j++) + labels[i][j] = nameo[j]; + + //Replace dummy strings with empty strings + if(addresses[i][0] == '|') + { + addresses[i][0] = 0; + } + if(labels[i][0] == '|') + { + labels[i][0] = 0; + } + PutInSpaces(i); + + addresses[i][15] = 0; + labels[i][23] = 0; //just in case + + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR) "---"); + SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]); + SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]); + } + fclose(fp); + } +} + +static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + //mbg 5/7/08 - wtf? + //DSMFix(uMsg); + switch(uMsg) + { + case WM_INITDIALOG: + break; + case WM_CLOSE: + case WM_QUIT: + SaveStrings(); + DestroyWindow(hwndMemWatch); + hwndMemWatch=0; + break; + case WM_COMMAND: + switch(HIWORD(wParam)) + { + case BN_CLICKED: + switch(LOWORD(wParam)) + { + case 101: //Save button clicked + //StopSound(); //mbg 5/7/08 + SaveMemWatch(); + break; + case 102: //Load button clicked + //StopSound(); //mbg 5/7/08 + LoadMemWatch(); + break; + case 103: //Clear button clicked + //StopSound(); //mbg 5/7/08 + if(MessageBox(hwndMemWatch, "Clear all text?", "Confirm clear", MB_YESNO)==IDYES) + { + int i; + for(i=0;i<24;i++) + { + addresses[i][0] = 0; + labels[i][0] = 0; + SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]); + SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]); + } + } + break; + default: + break; + } + } + + if(!(wParam>>16)) //Close button clicked + { + switch(wParam&0xFFFF) + { + case 1: + SaveStrings(); + DestroyWindow(hwndMemWatch); + hwndMemWatch=0; + break; + } + } + break; + default: + break; + } + return 0; +} + +//Open the Memory Watch dialog +void CreateMemWatch(HWND parent) +{ + if(NeedsInit) //Clear the strings + { + NeedsInit = 0; + int i,j; + for(i=0;i<24;i++) + { + for(j=0;j<24;j++) + { + addresses[i][j] = 0; + labels[i][j] = 0; + } + } + } + + if(hwndMemWatch) //If already open, give focus + { + SetFocus(hwndMemWatch); + return; + } + + //Create + //hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",parent,MemWatchCallB); + hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",NULL,MemWatchCallB); + + //Initialize values to previous entered addresses/labels + { + int i; + for(i = 0; i < 24; i++) + { + SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR) "---"); + SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]); + SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]); + } + } +} + diff --git a/src/drivers/win/memwatch.h b/src/drivers/win/memwatch.h new file mode 100644 index 00000000..008d24d8 --- /dev/null +++ b/src/drivers/win/memwatch.h @@ -0,0 +1,3 @@ +void UpdateMemWatch(); +void CreateMemWatch(HWND parent); +extern char * MemWatchDir; diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 420aecab..b065caf7 100644 Binary files a/src/drivers/win/res.rc and b/src/drivers/win/res.rc differ diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index c30a37b7..4f38566e 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -230,6 +230,7 @@ #define MENU_CDLOGGER 40078 #define MENU_GAMEGENIEDECODER 40079 #define MENU_DEBUGGER 40080 +#define MENU_MEMORY_WATCH 40081 #define MENU_LOG_SOUND 40120 #define GUI_BOT_DEBUG 65436 #define GUI_BOT_ERROR 65438 diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index f209c5e1..a960e036 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -33,6 +33,7 @@ #include "video.h" #include "../../input.h" +#include "memwatch.h" #include "ppuview.h" #include "debugger.h" #include "cheat.h" @@ -995,8 +996,10 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) #endif //case 204:ConfigAddCheat(hWnd);break; //mbg merge TODO 7/17/06 - had to remove this - //mbg merge TODO 7/17/06 - had to remove this - //case 205:CreateMemWatch(hWnd);break; + + case MENU_MEMORY_WATCH: + CreateMemWatch(hWnd); + break; case MENU_OPEN_FILE: // User selected the Open File menu => Show the file selection dialog diff --git a/vc8/fceux.vcproj b/vc8/fceux.vcproj index 2eaa6e8a..cb47bec9 100644 --- a/vc8/fceux.vcproj +++ b/vc8/fceux.vcproj @@ -962,6 +962,14 @@ RelativePath="..\src\drivers\win\memviewsp.h" > + + + +