rlm@1: #include "stdafx.h" rlm@1: #include "WinMiscUtil.h" rlm@1: #include "WinResUtil.h" rlm@1: #include "resource.h" rlm@1: #include "../NLS.h" rlm@1: #include "VBA.h" rlm@1: #include "Reg.h" rlm@1: #include "../common/movie.h" rlm@1: #include rlm@1: rlm@1: #include "GSACodeSelect.h" rlm@1: #include "../gba/GBACheats.h" rlm@1: #include "../gb/gbCheats.h" rlm@1: rlm@1: // #undef WinDef macro garbage rlm@1: #ifdef max rlm@1: #undef max rlm@1: #endif rlm@1: rlm@1: #ifdef min rlm@1: #undef min rlm@1: #endif rlm@1: rlm@1: using std::max; rlm@1: using std::min; rlm@1: rlm@1: extern int emulating; rlm@1: rlm@1: extern const char IDS_ROM_DIR[] = "romDir"; rlm@1: extern const char IDS_GBXROM_DIR[] = "gbromDir"; rlm@1: extern const char IDS_BATTERY_DIR[] = "batteryDir"; rlm@1: extern const char IDS_SAVE_DIR[] = "saveDir"; rlm@1: extern const char IDS_MOVIE_DIR[] = "moviesDir"; rlm@1: extern const char IDS_CHEAT_DIR[] = "cheatsDir"; rlm@1: extern const char IDS_LUA_DIR[] = "luaDir"; rlm@1: extern const char IDS_IPS_DIR[] = "ipsDir"; rlm@1: extern const char IDS_AVI_DIR[] = "aviRecordDir"; rlm@1: extern const char IDS_WAV_DIR[] = "soundRecordDir"; rlm@1: extern const char IDS_CAPTURE_DIR[] = "captureDir"; rlm@1: extern const char IDS_WATCH_DIR[] = "watchDir"; rlm@1: rlm@1: extern const char IDS_ROM_DEFAULT_DIR[] = "\\roms"; rlm@1: extern const char IDS_GBXROM_DEFAULT_DIR[] = "\\gbroms"; rlm@1: extern const char IDS_BATTERY_DEFAULT_DIR[] = "\\battery"; rlm@1: extern const char IDS_SAVE_DEFAULT_DIR[] = "\\save"; rlm@1: extern const char IDS_MOVIE_DEFAULT_DIR[] = "\\movies"; rlm@1: extern const char IDS_CHEAT_DEFAULT_DIR[] = "\\cheats"; rlm@1: extern const char IDS_LUA_DEFAULT_DIR[] = "\\lua"; rlm@1: extern const char IDS_IPS_DEFAULT_DIR[] = "\\ips"; rlm@1: extern const char IDS_AVI_DEFAULT_DIR[] = "\\avi"; rlm@1: extern const char IDS_WAV_DEFAULT_DIR[] = "\\wav"; rlm@1: extern const char IDS_CAPTURE_DEFAULT_DIR[] = "\\screen"; rlm@1: extern const char IDS_WATCH_DEFAULT_DIR[] = "\\watches"; rlm@1: rlm@1: extern const char *IDS_tbl[] = { rlm@1: IDS_ROM_DIR, IDS_GBXROM_DIR, IDS_BATTERY_DIR, IDS_SAVE_DIR, rlm@1: IDS_MOVIE_DIR, IDS_CHEAT_DIR, IDS_LUA_DIR, IDS_IPS_DIR, rlm@1: IDS_AVI_DIR, IDS_WAV_DIR, IDS_CAPTURE_DIR, IDS_WATCH_DIR rlm@1: }; rlm@1: rlm@1: extern const char *IDS_def_tbl[] = { rlm@1: IDS_ROM_DEFAULT_DIR, IDS_GBXROM_DEFAULT_DIR, IDS_BATTERY_DEFAULT_DIR, IDS_SAVE_DEFAULT_DIR, rlm@1: IDS_MOVIE_DEFAULT_DIR, IDS_CHEAT_DEFAULT_DIR, IDS_LUA_DEFAULT_DIR, IDS_IPS_DEFAULT_DIR, rlm@1: IDS_AVI_DEFAULT_DIR, IDS_WAV_DEFAULT_DIR, IDS_CAPTURE_DEFAULT_DIR, IDS_WATCH_DEFAULT_DIR rlm@1: }; rlm@1: rlm@1: // these could be made VBA members, but the VBA class is already oversized too much rlm@1: // rlm@1: rlm@1: bool winFileExists(const CString &filename) rlm@1: { rlm@1: FILE *f = fopen(filename, "rb"); rlm@1: if (f) rlm@1: { rlm@1: fclose(f); rlm@1: return true; rlm@1: } rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool winIsDriveRoot(const CString &file) rlm@1: { rlm@1: if (file.GetLength() == 3) rlm@1: { rlm@1: if (file[1] == ':' && file[2] == '\\') rlm@1: return true; rlm@1: } rlm@1: return false; rlm@1: } rlm@1: rlm@1: CString winGetOriginalFilename(const CString &file) rlm@1: { rlm@1: int index = file.Find('|'); rlm@1: rlm@1: if (index != -1) rlm@1: return file.Left(index); rlm@1: else rlm@1: return file; rlm@1: } rlm@1: rlm@1: CString winGetDirFromFilename(const CString &file) rlm@1: { rlm@1: CString temp = winGetOriginalFilename(file); rlm@1: int index = max(temp.ReverseFind('/'), temp.ReverseFind('\\')); rlm@1: if (index != -1) rlm@1: { rlm@1: temp = temp.Left(index); rlm@1: if (temp.GetLength() == 2 && temp[1] == ':') rlm@1: temp += "\\"; rlm@1: } rlm@1: rlm@1: return temp; rlm@1: } rlm@1: rlm@1: CString winGetDestDir(const CString &TargetDirReg) rlm@1: { rlm@1: CString targetDir = regQueryStringValue(TargetDirReg, NULL); rlm@1: int pos = targetDir.ReverseFind('\\'); rlm@1: if (pos > 0 && pos == targetDir.GetLength() - 1) rlm@1: targetDir.Delete(pos); rlm@1: rlm@1: // it makes no sense to create rom directories rlm@1: // see MainWnd::winFileOpenSelect for more info rlm@1: if (!TargetDirReg.Compare(IDS_ROM_DIR) || !TargetDirReg.Compare(IDS_GBXROM_DIR)) rlm@1: return targetDir; rlm@1: rlm@1: if (targetDir.IsEmpty()) rlm@1: { rlm@1: targetDir = theApp.exeDir; // reset the targetDir to the application's path rlm@1: if (!TargetDirReg.Compare(IDS_BATTERY_DIR)) rlm@1: { rlm@1: targetDir += IDS_BATTERY_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_SAVE_DIR)) rlm@1: { rlm@1: targetDir += IDS_SAVE_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_MOVIE_DIR)) rlm@1: { rlm@1: targetDir += IDS_MOVIE_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_CHEAT_DIR)) rlm@1: { rlm@1: targetDir += IDS_CHEAT_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_LUA_DIR)) rlm@1: { rlm@1: targetDir += IDS_LUA_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_IPS_DIR)) rlm@1: { rlm@1: targetDir += IDS_IPS_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_AVI_DIR)) rlm@1: { rlm@1: targetDir += IDS_AVI_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_WAV_DIR)) rlm@1: { rlm@1: targetDir += IDS_WAV_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_CAPTURE_DIR)) rlm@1: { rlm@1: targetDir += IDS_CAPTURE_DEFAULT_DIR; rlm@1: } rlm@1: else if (!TargetDirReg.Compare(IDS_WATCH_DIR)) rlm@1: { rlm@1: targetDir += IDS_WATCH_DEFAULT_DIR; rlm@1: } rlm@1: regSetStringValue(TargetDirReg, targetDir); // Add the directory to the INI file rlm@1: } rlm@1: rlm@1: _mkdir(targetDir); // make the directory rlm@1: rlm@1: return targetDir; rlm@1: } rlm@1: rlm@1: CString winGetDestFilename(const CString &LogicalRomName, const CString &TargetDirReg, const CString &ext) rlm@1: { rlm@1: if (LogicalRomName.GetLength() == 0) rlm@1: return CString(); rlm@1: rlm@1: CString targetDir = winGetDestDir(TargetDirReg); rlm@1: targetDir += '\\'; rlm@1: rlm@1: CString buffer = LogicalRomName; rlm@1: rlm@1: int index = max(buffer.ReverseFind('/'), max(buffer.ReverseFind('\\'), buffer.ReverseFind('|'))); rlm@1: if (index != -1) rlm@1: buffer = buffer.Right(buffer.GetLength() - index - 1); rlm@1: rlm@1: index = buffer.ReverseFind('.'); rlm@1: if (index != -1) rlm@1: buffer = buffer.Left(index); rlm@1: rlm@1: CString filename; rlm@1: filename.Format("%s%s%s", targetDir, buffer, ext); rlm@1: bool fileExists = winFileExists(filename); rlm@1: rlm@1: // check for old style of naming, for better backward compatibility rlm@1: if (!fileExists || theApp.filenamePreference == 0) rlm@1: { rlm@1: index = LogicalRomName.Find('|'); rlm@1: if (index != -1) rlm@1: { rlm@1: buffer = LogicalRomName.Left(index); rlm@1: index = max(buffer.ReverseFind('/'), buffer.ReverseFind('\\')); rlm@1: rlm@1: int dotIndex = buffer.ReverseFind('.'); rlm@1: if (dotIndex > index) rlm@1: buffer = buffer.Left(dotIndex); rlm@1: rlm@1: if (index != -1) rlm@1: buffer = buffer.Right(buffer.GetLength() - index - 1); rlm@1: rlm@1: CString filename2; rlm@1: filename2.Format("%s%s%s", targetDir, buffer, ext); rlm@1: bool file2Exists = winFileExists(filename2); rlm@1: rlm@1: if ((file2Exists && !fileExists) || (theApp.filenamePreference == 0 && (file2Exists || !fileExists))) rlm@1: return filename2; rlm@1: } rlm@1: } rlm@1: rlm@1: return filename; rlm@1: } rlm@1: rlm@1: CString winGetSavestateFilename(const CString &LogicalRomName, int nID) rlm@1: { rlm@1: CString ext; rlm@1: // size_t startindex; // forget about C89/ANSI-C rlm@1: // size_t endindex; rlm@1: if (VBAMovieActive() && theApp.AsscWithSaveState) rlm@1: { rlm@1: std::string fs(VBAMovieGetFilename()); // RVO tip rlm@1: size_t startindex = fs.find_last_of("/\\") ; rlm@1: if (startindex < fs.length()) rlm@1: ++startindex; // luckily the found character can't be at the end of fs rlm@1: else rlm@1: startindex = 0; rlm@1: size_t endindex = fs.find_last_of("."); rlm@1: if (endindex < fs.length() && endindex > startindex) rlm@1: endindex; //?? rlm@1: else rlm@1: endindex = fs.length(); rlm@1: fs = fs.substr(startindex, endindex - startindex); rlm@1: ext.Format("-%s-%d.sgm", fs.c_str(), nID); rlm@1: } rlm@1: else rlm@1: { rlm@1: ext.Format("%d.sgm", nID); rlm@1: } rlm@1: return winGetDestFilename(LogicalRomName, IDS_SAVE_DIR, ext); rlm@1: } rlm@1: rlm@1: CString winGetSavestateMenuString(const CString &LogicalRomName, int nID) rlm@1: { rlm@1: CString str; rlm@1: if (theApp.showSlotTime) rlm@1: { rlm@1: CFileStatus status; rlm@1: if (emulating && CFile::GetStatus(winGetSavestateFilename(LogicalRomName, nID), status)) rlm@1: { rlm@1: str.Format("#&%d %s", nID, status.m_mtime.Format("%Y/%m/%d %H:%M:%S")); rlm@1: } rlm@1: else rlm@1: { rlm@1: str.Format("#&%d ----/--/-- --:--:--", nID); rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: str.Format("Slot #&%d", nID); rlm@1: } rlm@1: rlm@1: return str; rlm@1: } rlm@1: rlm@1: void winCorrectPath(CString &path) rlm@1: { rlm@1: if (winFileExists(path)) rlm@1: { rlm@1: return; rlm@1: } rlm@1: rlm@1: CString tempStr = theApp.exeDir; rlm@1: tempStr += "\\"; rlm@1: tempStr += path; rlm@1: rlm@1: if (winFileExists(tempStr)) rlm@1: { rlm@1: path = tempStr; rlm@1: return; rlm@1: } rlm@1: rlm@1: for (int i = 0; i < _countof(IDS_tbl); ++i) rlm@1: { rlm@1: tempStr = winGetDestDir(IDS_tbl[i]); rlm@1: tempStr += "\\"; rlm@1: tempStr += path; rlm@1: rlm@1: if (winFileExists(tempStr)) rlm@1: { rlm@1: path = tempStr; rlm@1: return; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void winCorrectPath(char *path) rlm@1: { rlm@1: CString pathCStr(path); rlm@1: winCorrectPath(pathCStr); rlm@1: strcpy(path, pathCStr); rlm@1: } rlm@1: rlm@1: // some file I/O rlm@1: rlm@1: int winScreenCapture(int captureNumber) rlm@1: { rlm@1: CString ext; rlm@1: CString captureName; rlm@1: rlm@1: do rlm@1: { rlm@1: if (theApp.captureFormat == 0) rlm@1: ext.Format("_%03d.png", captureNumber); rlm@1: else rlm@1: ext.Format("_%03d.bmp", captureNumber); rlm@1: rlm@1: captureName = winGetDestFilename(theApp.gameFilename, IDS_CAPTURE_DIR, ext); rlm@1: ++captureNumber; rlm@1: } while (winFileExists(captureName) && captureNumber > 0); rlm@1: rlm@1: if (captureNumber < 0) rlm@1: { rlm@1: systemMessage(0, "Too many existing files (not less than %d)! Screen capture failed!", captureNumber - 1); rlm@1: return 0; rlm@1: } rlm@1: rlm@1: if (theApp.captureFormat == 0) rlm@1: theApp.emulator.emuWritePNG(captureName); rlm@1: else rlm@1: theApp.emulator.emuWriteBMP(captureName); rlm@1: rlm@1: systemScreenMessage(winResLoadString(IDS_SCREEN_CAPTURE)); rlm@1: rlm@1: return captureNumber; rlm@1: } rlm@1: rlm@1: bool winImportGSACodeFile(CString &fileName) rlm@1: { rlm@1: FILE *f = fopen(fileName, "rb"); rlm@1: rlm@1: if (f == NULL) rlm@1: { rlm@1: systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", fileName); rlm@1: return false; rlm@1: } rlm@1: rlm@1: if (systemCartridgeType == 1) rlm@1: { rlm@1: fclose(f); rlm@1: return gbCheatReadGSCodeFile(fileName); rlm@1: } rlm@1: rlm@1: u32 len; rlm@1: fread(&len, 1, 4, f); rlm@1: if (len != 14) rlm@1: { rlm@1: fclose(f); rlm@1: systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", rlm@1: fileName); rlm@1: return false; rlm@1: } rlm@1: char buffer[16]; rlm@1: fread(buffer, 1, 14, f); rlm@1: buffer[14] = 0; rlm@1: if (memcmp(buffer, "SharkPortCODES", 14)) rlm@1: { rlm@1: fclose(f); rlm@1: systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", rlm@1: fileName); rlm@1: return false; rlm@1: } rlm@1: fseek(f, 0x1e, SEEK_SET); rlm@1: fread(&len, 1, 4, f); rlm@1: int game = 0; rlm@1: if (len > 1) rlm@1: { rlm@1: GSACodeSelect dlg(f); rlm@1: game = dlg.DoModal(); rlm@1: } rlm@1: fclose(f); rlm@1: rlm@1: bool v3 = false; rlm@1: rlm@1: int index = fileName.ReverseFind('.'); rlm@1: rlm@1: if (index != -1) rlm@1: { rlm@1: if (fileName.Right(3).CompareNoCase("XPC") == 0) rlm@1: v3 = true; rlm@1: } rlm@1: rlm@1: if (game != -1) rlm@1: { rlm@1: return cheatsImportGSACodeFile(fileName, game, v3); rlm@1: } rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: void winLoadCheatList(const char *name) rlm@1: { rlm@1: bool res = false; rlm@1: rlm@1: if (systemCartridgeType == 0) rlm@1: res = cheatsLoadCheatList(name); rlm@1: else rlm@1: res = gbCheatsLoadCheatList(name); rlm@1: rlm@1: if (res) rlm@1: systemScreenMessage(winResLoadString(IDS_LOADED_CHEATS)); rlm@1: } rlm@1: rlm@1: void winSaveCheatList(const char *name) rlm@1: { rlm@1: if (systemCartridgeType == 0) rlm@1: cheatsSaveCheatList(name); rlm@1: else rlm@1: gbCheatsSaveCheatList(name); rlm@1: } rlm@1: rlm@1: void winLoadCheatListDefault() rlm@1: { rlm@1: CString cheatName = winGetDestFilename(theApp.gameFilename, IDS_CHEAT_DIR, ".clt"); rlm@1: rlm@1: winLoadCheatList(cheatName); rlm@1: } rlm@1: rlm@1: void winSaveCheatListDefault() rlm@1: { rlm@1: CString cheatName = winGetDestFilename(theApp.gameFilename, IDS_CHEAT_DIR, ".clt"); rlm@1: rlm@1: winSaveCheatList(cheatName); rlm@1: } rlm@1: rlm@1: bool winReadBatteryFile() rlm@1: { rlm@1: CString batteryName = winGetDestFilename(theApp.gameFilename, IDS_BATTERY_DIR, ".sav"); rlm@1: rlm@1: bool res = false; rlm@1: rlm@1: if (theApp.emulator.emuReadBattery) rlm@1: res = theApp.emulator.emuReadBattery(batteryName); rlm@1: rlm@1: if (res) rlm@1: systemScreenMessage(winResLoadString(IDS_LOADED_BATTERY)); rlm@1: rlm@1: return res; rlm@1: } rlm@1: rlm@1: bool winWriteBatteryFile() rlm@1: { rlm@1: CString batteryName = winGetDestFilename(theApp.gameFilename, IDS_BATTERY_DIR, ".sav"); rlm@1: rlm@1: if (theApp.emulator.emuWriteBattery) rlm@1: return theApp.emulator.emuWriteBattery(batteryName); rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool winEraseBatteryFile() rlm@1: { rlm@1: CString batteryName = winGetDestFilename(theApp.gameFilename, IDS_BATTERY_DIR, ".sav"); rlm@1: return !remove(batteryName); rlm@1: } rlm@1: rlm@1: bool winReadSaveGame(const char *name) rlm@1: { rlm@1: if (theApp.emulator.emuReadState) rlm@1: return theApp.emulator.emuReadState(name); rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool winWriteSaveGame(const char *name) rlm@1: { rlm@1: if (theApp.emulator.emuWriteState) rlm@1: return theApp.emulator.emuWriteState(name); rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool winEraseSaveGame(const char *name) rlm@1: { rlm@1: return !remove(name); rlm@1: }