diff --git a/src/drivers/common/config.cpp b/src/drivers/common/config.cpp index 15e8f8b5..ab0a060d 100644 --- a/src/drivers/common/config.cpp +++ b/src/drivers/common/config.cpp @@ -7,7 +7,7 @@ * 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. - * + *fs * 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 @@ -31,6 +31,7 @@ #include #include "../../types.h" +#include "../../driver.h" #include "config.h" static int FReadString(FILE *fp, char *str, int n) @@ -48,6 +49,87 @@ static int FReadString(FILE *fp, char *str, int n) return 1; } +#include +#include +typedef std::map CFGMAP; +static CFGMAP cfgmap; + +static void cfg_Parse(FILE *fp) +{ + //yes... it is a homebrewed key-value-pair parser + std::string key,value; + enum { + NEWLINE, KEY, SEPARATOR, VALUE, COMMENT + } state = NEWLINE; + bool bail = false; + for(;;) + { + int c = fgetc(fp); + if(c == -1) + goto bail; + bool iswhitespace = (c==' '||c=='\t'); + bool iscommentchar = (c=='#'); + bool isnewline = (c==10||c==13); + switch(state) + { + case NEWLINE: + if(iswhitespace) goto done; + if(iscommentchar) goto docomment; + if(isnewline) goto done; + key = ""; + value = ""; + goto dokey; + break; + case COMMENT: + docomment: + state = COMMENT; + if(isnewline) state = NEWLINE; + break; + case KEY: + dokey: //dookie + state = KEY; + if(iswhitespace) goto doseparator; + if(isnewline) goto commit; + key += c; + break; + case SEPARATOR: + doseparator: + state = SEPARATOR; + if(isnewline) goto commit; + if(!iswhitespace) goto dovalue; + break; + case VALUE: + dovalue: + state = VALUE; + if(isnewline) goto commit; + value += c; + } + goto done; + + bail: + bail = true; + if(state == VALUE) goto commit; + commit: + cfgmap[key] = value; + state = NEWLINE; + if(bail) break; + done: ; + } +} + +static void cfg_Save(FILE *fp) +{ + for(CFGMAP::iterator it(cfgmap.begin()); it != cfgmap.end(); it++) + { + if(it->first.size()>30 || it->second.size()>30) + { + int zzz=9; + } + fprintf(fp,"%s %s\n",it->first.c_str(),it->second.c_str()); + } +} + + static void GetValueR(FILE *fp, char *str, void *v, int c) { char buf[256]; @@ -93,7 +175,7 @@ void SetValueR(FILE *fp, const char *str, void *v, int c) } /** -* Parses a configuration structure and saves information from the structure into a file. +* Parses a c onfiguration structure and saves information from the structure into a file. * * @param cfgst The configuration structure. * @param fp File handle. @@ -105,12 +187,10 @@ void SaveParse(const CFGSTRUCT *cfgst, FILE *fp) while(cfgst[x].ptr) { - if(!cfgst[x].name) // Link to new config structure - { - SaveParse((CFGSTRUCT*)cfgst[x].ptr, fp); // Recursion is sexy. I could - // save a little stack space if I made - // the file pointer a non-local - // variable... + //structure contains another embedded structure. + //recurse. + if(!cfgst[x].name) { + SaveParse((CFGSTRUCT*)cfgst[x].ptr, fp); x++; continue; } @@ -135,26 +215,6 @@ void SaveParse(const CFGSTRUCT *cfgst, FILE *fp) } } -/** -* Stores information from a configuration struct into a configuration file. -* -* @param filename Name of the configuration file -* @param cfgst The configuration struct -**/ -void SaveFCEUConfig(const char *filename, const CFGSTRUCT *cfgst) -{ - FILE *fp = fopen(filename,"wb"); - - if(fp==NULL) - { - return; - } - - SaveParse(cfgst, fp); - - fclose(fp); -} - /** * Parses information from a file into a configuration structure. * @@ -179,21 +239,204 @@ void LoadParse(CFGSTRUCT *cfgst, FILE *fp) } } -/** -* Loads config information from the config file. -* -* @param filename Name of the config file. -**/ -void LoadFCEUConfig(const char *filename, CFGSTRUCT *cfgst) + +static void StringToBytes(std::string& str, void* data, int len) { - FILE *fp = fopen(filename,"rb"); + if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X') + goto hex; + + if(len==1) { + int x = atoi(str.c_str()); + *(unsigned char*)data = x; + return; + } else if(len==2) { + int x = atoi(str.c_str()); + *(unsigned short*)data = x; + return; + } else if(len==4) { + int x = atoi(str.c_str()); + *(unsigned int*)data = x; + return; + } + //else it had better be hex + FCEUD_PrintError("Config error: no hex data found somewhere it is required"); +hex: + int amt = len; + int bytesAvailable = str.size()/2; + if(bytesAvailable < amt) + amt = bytesAvailable; + const char* cstr = str.c_str()+2; + for(int i=0;i='A') a=a-'A'+10; + else a-='0'; + if(b>='A') b=b-'A'+10; + else b-='0'; + unsigned char val = ((unsigned char)a<<4)|(unsigned char)b; + ((unsigned char*)data)[i] = val; + } +} + +static std::string BytesToString(void* data, int len) +{ + char temp[16]; + if(len==1) { + sprintf(temp,"%d",*(unsigned char*)data); + return temp; + } else if(len==2) { + sprintf(temp,"%d",*(unsigned short*)data); + return temp; + } else if(len==4) { + sprintf(temp,"%d",*(unsigned int*)data); + return temp; + } + std::string ret; + ret.resize(len*2+2); + char* str= (char*)ret.c_str(); + str[0] = '0'; + str[1] = 'x'; + str += 2; + for(int i=0;i>4); + int b = (((unsigned char*)data)[i])&15; + if(a>9) a += 'A'-10; + else a += '0'; + if(b>9) b += 'A'-10; + else b += '0'; + str[i*2] = a; + str[i*2+1] = b; + } + return ret; +} + +static void cfg_OldToNew(const CFGSTRUCT *cfgst) +{ + int x=0; + + while(cfgst[x].ptr) + { + //structure contains another embedded structure. recurse. + if(!cfgst[x].name) { + cfg_OldToNew((CFGSTRUCT*)cfgst[x].ptr); + x++; + continue; + } + + if(cfgst[x].len) + { + //binary data + cfgmap[cfgst[x].name] = BytesToString(cfgst[x].ptr,cfgst[x].len); + } + else + { + //string data + if(*(char*)cfgst[x].ptr) + cfgmap[cfgst[x].name] = *(char**)cfgst[x].ptr; + else cfgmap[cfgst[x].name] = ""; + } + + x++; + } +} + +void cfg_NewToOld(CFGSTRUCT *cfgst) +{ + int x=0; + + while(cfgst[x].ptr) + { + //structure contains another embedded structure. recurse. + if(!cfgst[x].name) { + cfg_NewToOld((CFGSTRUCT*)cfgst[x].ptr); + x++; + continue; + } + + //if the key was not found, skip it + if(cfgmap.find(std::string(cfgst[x].name)) == cfgmap.end()) + { + x++; + continue; + } + + if(cfgst[x].len) + { + //binary data + StringToBytes(cfgmap[cfgst[x].name],cfgst[x].ptr,cfgst[x].len); + } + else + { + //string data + if(*(char*)cfgst[x].ptr) + free(cfgst[x].ptr); + std::string& str = cfgmap[cfgst[x].name]; + if(str == "") + *(char**)cfgst[x].ptr = 0; + else + *(char**)cfgst[x].ptr = strdup(cfgmap[cfgst[x].name].c_str()); + } + + x++; + } +} + +//saves the old fceu98 format +void SaveFCEUConfig_old(const char *filename, const CFGSTRUCT *cfgst) +{ + FILE *fp = fopen(filename,"wb"); if(fp==NULL) { return; } - LoadParse(cfgst, fp); + SaveParse(cfgst, fp); fclose(fp); } + +void SaveFCEUConfig(const char *filename, const CFGSTRUCT *cfgst) +{ + FILE *fp = fopen(filename,"wb"); + + if(fp==NULL) + return; + + fp = fopen(filename,"wb"); + cfg_OldToNew(cfgst); + cfg_Save(fp); + fclose(fp); +} + +//loads the old fceu98 format +void LoadFCEUConfig_old(const char *filename, CFGSTRUCT *cfgst) +{ + FILE *fp = fopen(filename,"rb"); + + if(fp==NULL) + return; + + LoadParse(cfgst,fp); + + fclose(fp); +} + +void LoadFCEUConfig(const char *filename, CFGSTRUCT *cfgst) +{ + FILE *fp = fopen(filename,"rb"); + + cfgmap.clear(); + + //make sure there is a version key set + cfgmap["!version"] = "1"; + + if(fp==NULL) + return; + + cfg_Parse(fp); + cfg_NewToOld(cfgst); + + fclose(fp); +} \ No newline at end of file diff --git a/src/drivers/win/basicbot.cpp b/src/drivers/win/basicbot.cpp index 4cd92fe1..0f243f5c 100644 --- a/src/drivers/win/basicbot.cpp +++ b/src/drivers/win/basicbot.cpp @@ -46,6 +46,8 @@ static char BBcaption[] = "Basic Bot v0.3.4a by qFox"; // save/load version static int BBsaveload = 2; +int BasicBot_wndx=0, BasicBot_wndy=0; + static HWND hwndBasicBot = 0; // GUI handle static bool BotRunning = false; // Is the bot computing or not? static bool ResetStatsASAP = false; // Do we need to reset the stats asap? (when pressing reset in gui) @@ -2414,7 +2416,16 @@ static BOOL CALLBACK BasicBotCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA // cant change gui controls in this event // seems to be a inherited "feature", for backwards // compatibility. + SetWindowPos(hwndDlg,0,BasicBot_wndx,BasicBot_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); break; + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + BasicBot_wndx = wrect.left; + BasicBot_wndy = wrect.top; + break; + }; + case WM_CLOSE: case WM_QUIT: CrashWindow(); diff --git a/src/drivers/win/cdlogger.cpp b/src/drivers/win/cdlogger.cpp index b7808e39..a6692cbc 100644 --- a/src/drivers/win/cdlogger.cpp +++ b/src/drivers/win/cdlogger.cpp @@ -37,6 +37,9 @@ void SaveStrippedRom(); extern iNES_HEADER head; //defined in ines.c extern uint8 *trainerpoo; + +int CDLogger_wndx=0, CDLogger_wndy=0; + //extern uint8 *ROM; //extern uint8 *VROM; @@ -49,7 +52,15 @@ char loadedcdfile[1024]; BOOL CALLBACK CDLoggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + CDLogger_wndx = wrect.left; + CDLogger_wndy = wrect.top; + break; + }; case WM_INITDIALOG: + SetWindowPos(hwndDlg,0,CDLogger_wndx,CDLogger_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); hCDLogger = hwndDlg; codecount = datacount = 0; undefinedcount = PRGsize[0]; diff --git a/src/drivers/win/cheat.cpp b/src/drivers/win/cheat.cpp index c4ee5ca5..f697a7df 100644 --- a/src/drivers/win/cheat.cpp +++ b/src/drivers/win/cheat.cpp @@ -34,6 +34,7 @@ int CheatStyle=1; int selcheat; int ChtPosX,ChtPosY; +int GGConv_wndx=0, GGConv_wndy=0; static HFONT hFont,hNewFont; static int scrollindex; @@ -517,8 +518,16 @@ BOOL CALLBACK GGConvCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) int i; switch(uMsg) { + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + GGConv_wndx = wrect.left; + GGConv_wndy = wrect.top; + break; + }; case WM_INITDIALOG: //todo: set text limits + SetWindowPos(hwndDlg,0,GGConv_wndx,GGConv_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); break; case WM_CREATE: diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index 9843105b..c41360b1 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -40,6 +40,7 @@ extern int autoHoldKey, autoHoldClearKey; extern int frame_display; extern int input_display; extern char *BasicBotDir; +extern int disableUDLR; //window positions: extern int ChtPosX,ChtPosY; @@ -49,6 +50,12 @@ extern int MemFind_wndx, MemFind_wndy; extern int NTViewPosX,NTViewPosY; extern int PPUViewPosX,PPUViewPosY; extern int MainWindow_wndx, MainWindow_wndy; +extern int BasicBot_wndx, BasicBot_wndy; +extern int MemWatch_wndx, MemWatch_wndy; +extern int Monitor_wndx, Monitor_wndy; +extern int Tracer_wndx, Tracer_wndy; +extern int CDLogger_wndx, CDLogger_wndy; +extern int GGConv_wndx, GGConv_wndy; /** * Structure that contains configuration information @@ -160,12 +167,14 @@ static CFGSTRUCT fceuconfig[] = { AC(autoHoldClearKey), AC(frame_display), AC(input_display), - ACS(MemWatchDir), //mbg merge 7/18/06 removed + ACS(MemWatchDir), ACS(BasicBotDir), AC(EnableBackgroundInput), AC(MemWatchLoadOnStart), AC(MemWatchLoadFileOnStart), + AC(disableUDLR), + //window positions AC(ChtPosX), AC(ChtPosY), @@ -181,6 +190,18 @@ static CFGSTRUCT fceuconfig[] = { AC(PPUViewPosY), AC(MainWindow_wndx), AC(MainWindow_wndy), + AC(BasicBot_wndx), + AC(BasicBot_wndy), + AC(MemWatch_wndx), + AC(MemWatch_wndy), + AC(Monitor_wndx), + AC(Monitor_wndy), + AC(Tracer_wndx), + AC(Tracer_wndy), + AC(CDLogger_wndx), + AC(CDLogger_wndy), + AC(GGConv_wndx), + AC(GGConv_wndy), //ACS(memwLastfile[2048]), ENDCFGSTRUCT diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index 1f6d35b8..9acd4490 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -136,7 +136,7 @@ static int DIPS=0; //#define KEY(__a) keys_nr[MKK(__a)] int cidisabled=0; -static int disableUDLR=0; +int disableUDLR=0; #define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} #define MC(x) {{BUTTC_KEYBOARD},{0},{x},1} diff --git a/src/drivers/win/memwatch.cpp b/src/drivers/win/memwatch.cpp index e148ca99..edbf6139 100644 --- a/src/drivers/win/memwatch.cpp +++ b/src/drivers/win/memwatch.cpp @@ -24,6 +24,7 @@ #include "..\..\debug.h" #include "debugger.h" +int MemWatch_wndx=0, MemWatch_wndy=0; static HDC hdc; static HWND hwndMemWatch=0; static char addresses[24][16]; @@ -666,7 +667,16 @@ static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA switch(uMsg) { + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + MemWatch_wndx = wrect.left; + MemWatch_wndy = wrect.top; + break; + }; + case WM_INITDIALOG: + SetWindowPos(hwndDlg,0,MemWatch_wndx,MemWatch_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); hdc = GetDC(hwndDlg); SelectObject (hdc, debugSystem->hFixedFont); SetTextAlign(hdc,TA_UPDATECP | TA_TOP | TA_LEFT); diff --git a/src/drivers/win/monitor.cpp b/src/drivers/win/monitor.cpp index 5995571b..2794b342 100644 --- a/src/drivers/win/monitor.cpp +++ b/src/drivers/win/monitor.cpp @@ -34,6 +34,7 @@ const char* rule_strings[] = { "Any", "Exact value", "All but value", "Less than unsigned char snapshots[NUMBER_OF_RULES][SIZE_OF_RAM];// = { first_snapshot, second_snapshot, third_snapshot, fourth_snapshot, fifth_snapshot }; +int Monitor_wndx=0, Monitor_wndy=0; unsigned int last_button = 0; BOOL verify_rule(unsigned int rule_number, unsigned int chosen_rule, unsigned int offset, unsigned int value) @@ -220,7 +221,16 @@ unsigned int ruleBox_to_ruleInput(unsigned int ruleBox) BOOL CALLBACK MonitorCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + Monitor_wndx = wrect.left; + Monitor_wndy = wrect.top; + break; + }; + case WM_INITDIALOG: + SetWindowPos(hwndDlg,0,Monitor_wndx,Monitor_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); monitor_open = 1; // CenterWindow(hwndDlg); diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index b403501a..0b219502 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 a3ec3d34..319babb0 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -304,6 +304,7 @@ #define MEMW_OPTIONS_LOADLASTFILE 40114 #define ID_RECENT_ 40115 #define ID_RECENT_1 40116 +#define ID_FILE_RECENT 40117 #define MENU_LOG_SOUND 40120 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -316,7 +317,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 108 -#define _APS_NEXT_COMMAND_VALUE 40117 +#define _APS_NEXT_COMMAND_VALUE 40118 #define _APS_NEXT_CONTROL_VALUE 1129 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/tracer.cpp b/src/drivers/win/tracer.cpp index cd0cc610..863cb05a 100644 --- a/src/drivers/win/tracer.cpp +++ b/src/drivers/win/tracer.cpp @@ -54,6 +54,8 @@ int tracelogbufusedsize; FILE *LOG_FP; +int Tracer_wndx=0, Tracer_wndy=0; + void ShowLogDirDialog(void); void BeginLoggingSequence(void); void LogInstruction(void); @@ -69,8 +71,15 @@ BOOL CALLBACK TracerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) int i; LOGFONT lf; switch(uMsg) { + case WM_MOVE: { + RECT wrect; + GetWindowRect(hwndDlg,&wrect); + Tracer_wndx = wrect.left; + Tracer_wndy = wrect.top; + break; + }; case WM_INITDIALOG: - //CenterWindow(hwndDlg); + SetWindowPos(hwndDlg,0,Tracer_wndx,Tracer_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); hTracer = hwndDlg; //setup font