improvements to memwatch

This commit is contained in:
zeromus 2008-05-12 23:16:41 +00:00
parent c7db72391f
commit 43d21f1889
4 changed files with 170 additions and 90 deletions

View File

@ -1,26 +1,27 @@
/* FCE Ultra - NES/Famicom Emulator /* FCE Ultra - NES/Famicom Emulator
* *
* Copyright notice for this file: * Copyright notice for this file:
* Copyright (C) 2006 Luke Gustafson * Copyright (C) 2006 Luke Gustafson
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "common.h" #include "common.h"
#include "..\..\fceu.h" #include "..\..\fceu.h"
#include "memwatch.h" #include "memwatch.h"
#include "..\..\debug.h"
static HWND hwndMemWatch=0; static HWND hwndMemWatch=0;
static char addresses[24][16]; static char addresses[24][16];
@ -28,19 +29,23 @@ static char labels[24][24];
static int NeedsInit = 1; static int NeedsInit = 1;
char *MemWatchDir = 0; char *MemWatchDir = 0;
//mbg 5/12/08
//for the curious, I tested U16ToHexStr and it was 10x faster than printf.
//so the author of these dedicated functions is not insane, and I will leave them.
static char *U8ToStr(uint8 a) static char *U8ToStr(uint8 a)
{ {
static char TempArray[8]; static char TempArray[8];
TempArray[0] = '0' + a/100; TempArray[0] = '0' + a/100;
TempArray[1] = '0' + (a%100)/10; TempArray[1] = '0' + (a%100)/10;
TempArray[2] = '0' + (a%10); TempArray[2] = '0' + (a%10);
TempArray[3] = 0; TempArray[3] = 0;
return TempArray; return TempArray;
} }
//I don't trust scanf for speed //I don't trust scanf for speed
static uint16 FastStrToU16(char* s) static uint16 FastStrToU16(char* s, bool& valid)
{ {
int i; int i;
uint16 v=0; uint16 v=0;
@ -62,102 +67,139 @@ static uint16 FastStrToU16(char* s)
} }
else else
{ {
valid = false;
return 0xFFFF; return 0xFFFF;
} }
} }
valid = true;
return v; return v;
} }
static char *U16ToDecStr(uint16 a) static char *U16ToDecStr(uint16 a)
{ {
static char TempArray[8]; static char TempArray[8];
TempArray[0] = '0' + a/10000; TempArray[0] = '0' + a/10000;
TempArray[1] = '0' + (a%10000)/1000; TempArray[1] = '0' + (a%10000)/1000;
TempArray[2] = '0' + (a%1000)/100; TempArray[2] = '0' + (a%1000)/100;
TempArray[3] = '0' + (a%100)/10; TempArray[3] = '0' + (a%100)/10;
TempArray[4] = '0' + (a%10); TempArray[4] = '0' + (a%10);
TempArray[5] = 0; TempArray[5] = 0;
return TempArray; return TempArray;
} }
//sorry this is hard to read... but I don't trust printf for speed!
static char *U16ToHexStr(uint16 a) static char *U16ToHexStr(uint16 a)
{ {
static char TempArray[8]; static char TempArray[8];
TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096; 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[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[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[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
TempArray[4] = 0; TempArray[4] = 0;
return TempArray; return TempArray;
} }
static char *U8ToHexStr(uint8 a) static char *U8ToHexStr(uint8 a)
{ {
static char TempArray[8]; static char TempArray[8];
TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16; 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[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
TempArray[2] = 0; TempArray[2] = 0;
return TempArray; return TempArray;
} }
static const int MW_ADDR_Lookup[] = {
MW_ADDR00,MW_ADDR01,MW_ADDR02,MW_ADDR03,
MW_ADDR04,MW_ADDR05,MW_ADDR06,MW_ADDR07,
MW_ADDR08,MW_ADDR09,MW_ADDR10,MW_ADDR11,
MW_ADDR12,MW_ADDR13,MW_ADDR14,MW_ADDR15,
MW_ADDR16,MW_ADDR17,MW_ADDR18,MW_ADDR19,
MW_ADDR20,MW_ADDR21,MW_ADDR22,MW_ADDR23
};
static const int MWNUM = ARRAY_SIZE(MW_ADDR_Lookup);
static struct MWRec
{
static int findIndex(WORD ctl)
{
for(int i=0;i<MWNUM;i++)
if(MW_ADDR_Lookup[i] == ctl)
return i;
return -1;
}
void parse(WORD ctl)
{
char TempArray[16];
GetDlgItemText(hwndMemWatch,ctl,TempArray,16);
TempArray[15]=0;
valid = hex = twobytes = false;
switch(TempArray[0])
{
case 0:
break;
case '!':
twobytes=true;
addr=FastStrToU16(TempArray+1,valid);
break;
case 'x':
hex = true;
valid = true;
addr=FastStrToU16(TempArray+1,valid);
break;
case 'X':
hex = twobytes = true;
valid = true;
addr = FastStrToU16(TempArray+1,valid);
break;
default:
valid = true;
addr=FastStrToU16(TempArray,valid);
break;
}
}
bool valid, twobytes, hex;
uint16 addr;
} mwrecs[MWNUM];
//Update the values in the Memory Watch window //Update the values in the Memory Watch window
void UpdateMemWatch() void UpdateMemWatch()
{ {
if(hwndMemWatch) if(hwndMemWatch)
{ {
char TempArray[16]; for(int i = 0; i < MWNUM; i++)
int i, twobytes, hex;
uint16 a;
for(i = 0; i < 24; i++)
{ {
GetDlgItemText(hwndMemWatch,1001+i*3,TempArray,16); MWRec& mwrec = mwrecs[i];
twobytes=0; uint16& a = mwrec.addr;
hex = 0; bool& hex = mwrec.hex;
TempArray[15]=0; bool& twobytes = mwrec.twobytes;
switch(TempArray[0]) bool& valid = mwrec.valid;
if(mwrec.valid)
{ {
case 0: if(mwrec.hex)
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) if(mwrec.twobytes)
{ {
SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToStr(ARead[a](a))); SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToStr(GetMem(mwrec.addr)));
} }
else else
{ {
SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToDecStr(ARead[a](a)+256*ARead[a+1](a+1))); SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToDecStr(GetMem(mwrec.addr)+(GetMem(mwrec.addr+1)<<8)));
} }
} }
else else
{ {
if(twobytes == 0) if(mwrec.twobytes)
{ {
SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToHexStr(ARead[a](a))); SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToHexStr(GetMem(mwrec.addr)));
} }
else else
{ {
SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToHexStr(ARead[a](a)+256*ARead[a+1](a+1))); SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToHexStr(GetMem(mwrec.addr)+(GetMem(mwrec.addr+1)<<8)));
} }
} }
} }
@ -299,11 +341,11 @@ static void LoadMemWatch()
ofn.nMaxFile=256; ofn.nMaxFile=256;
ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
ofn.lpstrInitialDir=MemWatchDir; ofn.lpstrInitialDir=MemWatchDir;
if(GetOpenFileName(&ofn)) if(GetOpenFileName(&ofn))
{ {
int i,j; int i,j;
//Save the directory //Save the directory
if(ofn.nFileOffset < 1024) if(ofn.nFileOffset < 1024)
{ {
@ -312,7 +354,7 @@ static void LoadMemWatch()
strcpy(MemWatchDir,ofn.lpstrFile); strcpy(MemWatchDir,ofn.lpstrFile);
MemWatchDir[ofn.nFileOffset]=0; MemWatchDir[ofn.nFileOffset]=0;
} }
FILE *fp=FCEUD_UTF8fopen(nameo,"r"); FILE *fp=FCEUD_UTF8fopen(nameo,"r");
for(i=0;i<24;i++) for(i=0;i<24;i++)
{ {
@ -322,7 +364,7 @@ static void LoadMemWatch()
fscanf(fp, "%s\n", nameo); fscanf(fp, "%s\n", nameo);
for(j = 0; j < 24; j++) for(j = 0; j < 24; j++)
labels[i][j] = nameo[j]; labels[i][j] = nameo[j];
//Replace dummy strings with empty strings //Replace dummy strings with empty strings
if(addresses[i][0] == '|') if(addresses[i][0] == '|')
{ {
@ -333,7 +375,7 @@ static void LoadMemWatch()
labels[i][0] = 0; labels[i][0] = 0;
} }
PutInSpaces(i); PutInSpaces(i);
addresses[i][15] = 0; addresses[i][15] = 0;
labels[i][23] = 0; //just in case labels[i][23] = 0; //just in case
@ -345,6 +387,7 @@ static void LoadMemWatch()
} }
} }
static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
//mbg 5/7/08 - wtf? //mbg 5/7/08 - wtf?
@ -362,6 +405,17 @@ static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
case WM_COMMAND: case WM_COMMAND:
switch(HIWORD(wParam)) switch(HIWORD(wParam))
{ {
case EN_CHANGE:
{
//the contents of an address box changed. re-parse it.
//first, find which address changed
int changed = MWRec::findIndex(LOWORD(wParam));
if(changed==-1) break;
mwrecs[changed].parse(LOWORD(wParam));
break;
}
case BN_CLICKED: case BN_CLICKED:
switch(LOWORD(wParam)) switch(LOWORD(wParam))
{ {
@ -432,11 +486,11 @@ void CreateMemWatch(HWND parent)
SetFocus(hwndMemWatch); SetFocus(hwndMemWatch);
return; return;
} }
//Create //Create
//hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",parent,MemWatchCallB); //hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",parent,MemWatchCallB);
hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",NULL,MemWatchCallB); hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",NULL,MemWatchCallB);
//Initialize values to previous entered addresses/labels //Initialize values to previous entered addresses/labels
{ {
int i; int i;

Binary file not shown.

View File

@ -66,81 +66,105 @@
#define MENU_GUI_OPTIONS 327 #define MENU_GUI_OPTIONS 327
#define GUI_BOT_A_1 1000 #define GUI_BOT_A_1 1000
#define GUI_BOT_B_1 1001 #define GUI_BOT_B_1 1001
#define MW_ADDR00 1001
#define GUI_BOT_SELECT_1 1002 #define GUI_BOT_SELECT_1 1002
#define GUI_BOT_START_1 1003 #define GUI_BOT_START_1 1003
#define LV_MAPPING 1003 #define LV_MAPPING 1003
#define GUI_BOT_UP_1 1004 #define GUI_BOT_UP_1 1004
#define MW_ADDR01 1004
#define GUI_BOT_DOWN_1 1005 #define GUI_BOT_DOWN_1 1005
#define GUI_BOT_LEFT_1 1006 #define GUI_BOT_LEFT_1 1006
#define GUI_BOT_RIGHT_1 1007 #define GUI_BOT_RIGHT_1 1007
#define MW_ADDR02 1007
#define GUI_BOT_A_2 1008 #define GUI_BOT_A_2 1008
#define GUI_BOT_END 1009 #define GUI_BOT_END 1009
#define GUI_BOT_INVALID 1009 #define GUI_BOT_INVALID 1009
#define GUI_BOT_X 1010 #define GUI_BOT_X 1010
#define MW_ADDR03 1010
#define GUI_BOT_TIE1 1011 #define GUI_BOT_TIE1 1011
#define GUI_BOT_SCORE2 1011 #define GUI_BOT_SCORE2 1011
#define GUI_BOT_TIE2 1012 #define GUI_BOT_TIE2 1012
#define GUI_BOT_SCORE3 1012 #define GUI_BOT_SCORE3 1012
#define GUI_BOT_TIE3 1013 #define GUI_BOT_TIE3 1013
#define GUI_BOT_SCORE4 1013 #define GUI_BOT_SCORE4 1013
#define MW_ADDR04 1013
#define GUI_BOT_SAVE 1014 #define GUI_BOT_SAVE 1014
#define GUI_BOT_LOAD 1015 #define GUI_BOT_LOAD 1015
#define GUI_BOT_RUN 1016 #define GUI_BOT_RUN 1016
#define MW_ADDR05 1016
#define GUI_BOT_MAX 1017 #define GUI_BOT_MAX 1017
#define GUI_BOT_SCORE1 1017 #define GUI_BOT_SCORE1 1017
#define GUI_BOT_Y 1018 #define GUI_BOT_Y 1018
#define GUI_BOT_KEYS 1019 #define GUI_BOT_KEYS 1019
#define MW_ADDR06 1019
#define GUI_BOT_EXTRA 1020 #define GUI_BOT_EXTRA 1020
#define GUI_BOT_BEST 1021 #define GUI_BOT_BEST 1021
#define GUI_BOT_Z 1022 #define GUI_BOT_Z 1022
#define MW_ADDR07 1022
#define GUI_BOT_CHECK 1023 #define GUI_BOT_CHECK 1023
#define GUI_BOT_COMMENTS 1023 #define GUI_BOT_COMMENTS 1023
#define GUI_BOT_UPDATE 1024 #define GUI_BOT_UPDATE 1024
#define GUI_BOT_BOTMODE 1025 #define GUI_BOT_BOTMODE 1025
#define GUI_BOT_ROMNAME 1025 #define GUI_BOT_ROMNAME 1025
#define MW_ADDR08 1025
#define GUI_BOT_P 1026 #define GUI_BOT_P 1026
#define GUI_BOT_Q 1027 #define GUI_BOT_Q 1027
#define GUI_BOT_TEST 1028 #define GUI_BOT_TEST 1028
#define MW_ADDR09 1028
#define GUI_BOT_RESET 1029 #define GUI_BOT_RESET 1029
#define GUI_BOT_ROLLBACK 1030 #define GUI_BOT_ROLLBACK 1030
#define GUI_BOT_MAXFRAMES 1031 #define GUI_BOT_MAXFRAMES 1031
#define MW_ADDR10 1031
#define GUI_BOT_MAXATTEMPTS 1032 #define GUI_BOT_MAXATTEMPTS 1032
#define GUI_BOT_MAXPARTS 1033 #define GUI_BOT_MAXPARTS 1033
#define GUI_BOT_B_2 1034 #define GUI_BOT_B_2 1034
#define MW_ADDR11 1034
#define GUI_BOT_P1 1035 #define GUI_BOT_P1 1035
#define GUI_BOT_INTERNAL 1035 #define GUI_BOT_INTERNAL 1035
#define GUI_BOT_CLEAR 1036 #define GUI_BOT_CLEAR 1036
#define GUI_BOT_ATTEMPTS 1037 #define GUI_BOT_ATTEMPTS 1037
#define MW_ADDR12 1037
#define GUI_BOT_SELECT_2 1038 #define GUI_BOT_SELECT_2 1038
#define GUI_BOT_START_2 1039 #define GUI_BOT_START_2 1039
#define GUI_BOT_P2 1040 #define GUI_BOT_P2 1040
#define GUI_BOT_EXTERNAL 1040 #define GUI_BOT_EXTERNAL 1040
#define MW_ADDR13 1040
#define GUI_BOT_UP_2 1041 #define GUI_BOT_UP_2 1041
#define GUI_BOT_DOWN_2 1042 #define GUI_BOT_DOWN_2 1042
#define GUI_BOT_LEFT_2 1043 #define GUI_BOT_LEFT_2 1043
#define MW_ADDR14 1043
#define GUI_BOT_RIGHT_2 1044 #define GUI_BOT_RIGHT_2 1044
#define GUI_BOT_SCORE5 1045 #define GUI_BOT_SCORE5 1045
#define GUI_BOT_SCORE6 1046 #define GUI_BOT_SCORE6 1046
#define MW_ADDR15 1046
#define GUI_BOT_INIT_PART 1047 #define GUI_BOT_INIT_PART 1047
#define GUI_BOT_INIT_ATTEMPT 1048 #define GUI_BOT_INIT_ATTEMPT 1048
#define GUI_BOT_FRAMES 1049 #define GUI_BOT_FRAMES 1049
#define MW_ADDR16 1049
#define GUI_BOT_BESTRESULT 1050 #define GUI_BOT_BESTRESULT 1050
#define GUI_BOT_LAST 1051 #define GUI_BOT_LAST 1051
#define GUI_BOT_U 1052 #define GUI_BOT_U 1052
#define MW_ADDR17 1052
#define GUI_BOT_AVGMAX 1053 #define GUI_BOT_AVGMAX 1053
#define GUI_BOT_AVGTIE1 1054 #define GUI_BOT_AVGTIE1 1054
#define MW_ADDR18 1055
#define GUI_BOT_AVGTIE2 1056 #define GUI_BOT_AVGTIE2 1056
#define GUI_BOT_AVGTIE3 1057 #define GUI_BOT_AVGTIE3 1057
#define MW_ADDR19 1058
#define GUI_BOT_OK 1061 #define GUI_BOT_OK 1061
#define MW_ADDR20 1061
#define GUI_BOT_ATTEMPT_LAST 1062 #define GUI_BOT_ATTEMPT_LAST 1062
#define GUI_BOT_ATTEMPT_BEST 1063 #define GUI_BOT_ATTEMPT_BEST 1063
#define GUI_BOT_SCORE_LAST 1064 #define GUI_BOT_SCORE_LAST 1064
#define MW_ADDR21 1064
#define GUI_BOT_SCORE_BEST 1065 #define GUI_BOT_SCORE_BEST 1065
#define GUI_BOT_TIE1_LAST 1066 #define GUI_BOT_TIE1_LAST 1066
#define GUI_BOT_TIE1_BEST 1067 #define GUI_BOT_TIE1_BEST 1067
#define MW_ADDR22 1067
#define GUI_BOT_TIE2_BEST 1068 #define GUI_BOT_TIE2_BEST 1068
#define GUI_BOT_TIE3_BEST 1069 #define GUI_BOT_TIE3_BEST 1069
#define GUI_BOT_TIE4_BEST 1070 #define GUI_BOT_TIE4_BEST 1070
#define MW_ADDR23 1070
#define GUI_BOT_TIE5_BEST 1071 #define GUI_BOT_TIE5_BEST 1071
#define GUI_BOT_TIE2_LAST 1072 #define GUI_BOT_TIE2_LAST 1072
#define GUI_BOT_TIE3_LAST 1073 #define GUI_BOT_TIE3_LAST 1073

View File

@ -113,3 +113,5 @@ extern uint8 vsdip;
#define JOY_LEFT 0x40 #define JOY_LEFT 0x40
#define JOY_RIGHT 0x80 #define JOY_RIGHT 0x80
#endif #endif
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))