// Deletes a directory filename, returns true on success bool DeleteDir(const std::string &filename) { INFO_LOG(COMMON, "DeleteDir: directory %s", filename.c_str()); // check if a directory if (!File::IsDirectory(filename)) { ERROR_LOG(COMMON, "DeleteDir: Not a directory %s", filename.c_str()); return false; } #ifdef _WIN32 if (::RemoveDirectory(ConvertUTF8ToWString(filename).c_str())) return true; #else if (rmdir(filename.c_str()) == 0) return true; #endif ERROR_LOG(COMMON, "DeleteDir: %s: %s", filename.c_str(), GetLastErrorMsg()); return false; }
void CtrlModuleList::GetColumnText(wchar_t* dest, int row, int col) { if (row < 0 || row >= (int)modules.size()) { return; } switch (col) { case ML_NAME: wcscpy(dest,ConvertUTF8ToWString(modules[row].name).c_str()); break; case ML_ADDRESS: wsprintf(dest,L"%08X",modules[row].address); break; case ML_SIZE: wsprintf(dest,L"%08X",modules[row].size); break; case ML_ACTIVE: wcscpy(dest,modules[row].active ? L"true" : L"false"); break; } }
std::vector<std::string> CWCheatEngine::GetCodesList() { //Reads the entire cheat list from the appropriate .ini. std::string line; std::vector<std::string> codesList; // Read from INI here #ifdef _WIN32 std::ifstream list(ConvertUTF8ToWString(activeCheatFile)); #else std::ifstream list(activeCheatFile.c_str()); #endif if (!list) { return codesList; } for (int i = 0; !list.eof(); i ++) { getline(list, line, '\n'); if (line.length() > 3 && (line.substr(0,1) == "_"||line.substr(0,2) == "//")){ codesList.push_back(line); } } for(size_t i = 0; i < codesList.size(); i++) { trim2(codesList[i]); } return codesList; }
// Returns true if filename is a directory bool IsDirectory(const std::string &filename) { struct stat64 file_info; #if defined(_WIN32) && defined(UNICODE) && !defined(__MINGW32__) std::wstring copy = ConvertUTF8ToWString(filename); StripTailDirSlashes(copy); int result = _wstat64(copy.c_str(), &file_info); #else std::string copy(filename); StripTailDirSlashes(copy); int result = stat64(copy.c_str(), &file_info); #endif if (result < 0) { WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", filename.c_str(), GetLastErrorMsg()); return false; } return IsDirectory(file_info); }
PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { PSPFileInfo x; x.name = filename; std::string fullName = GetLocalPath(filename); if (! File::Exists(fullName)) { #if HOST_IS_CASE_SENSITIVE if (! FixPathCase(basePath,filename, FPC_FILE_MUST_EXIST)) return x; fullName = GetLocalPath(filename); if (! File::Exists(fullName)) return x; #else return x; #endif } x.type = File::IsDirectory(fullName) ? FILETYPE_DIRECTORY : FILETYPE_NORMAL; x.exists = true; if (x.type != FILETYPE_DIRECTORY) { #ifdef _WIN32 struct _stat64i32 s; _wstat64i32(ConvertUTF8ToWString(fullName).c_str(), &s); #else struct stat s; stat(fullName.c_str(), &s); #endif x.size = File::GetSize(fullName); x.access = s.st_mode & 0x1FF; localtime_r((time_t*)&s.st_atime,&x.atime); localtime_r((time_t*)&s.st_ctime,&x.ctime); localtime_r((time_t*)&s.st_mtime,&x.mtime); } return x; }
// Returns true if successful, or path already exists. bool CreateDir(const std::string &path) { INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str()); #ifdef _WIN32 #ifdef UNICODE if (::CreateDirectory(ConvertUTF8ToWString(path).c_str(), NULL)) #else if (::CreateDirectory(path.c_str(), NULL)) #endif return true; DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); return true; } ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %i", path.c_str(), error); return false; #else #ifdef BLACKBERRY if (mkdir(path.c_str(), 0775) == 0) #else if (mkdir(path.c_str(), 0755) == 0) #endif return true; int err = errno; if (err == EEXIST) { WARN_LOG(COMMON, "CreateDir: mkdir failed on %s: already exists", path.c_str()); return true; } ERROR_LOG(COMMON, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); return false; #endif }
// Returns the size of filename (64bit) u64 GetSize(const std::string &filename) { struct stat64 file_info; #if defined(_WIN32) && defined(UNICODE) int result = _wstat64(ConvertUTF8ToWString(filename).c_str(), &file_info); #else int result = stat64(filename.c_str(), &file_info); #endif if (result != 0) { WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str()); return 0; } if (IsDirectory(file_info)) { WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); return 0; } DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)file_info.st_size); return file_info.st_size; }
// Returns the size of file (64bit) // TODO: Add a way to return an error. u64 GetFileSize(const std::string &filename) { #if defined(_WIN32) && defined(UNICODE) WIN32_FILE_ATTRIBUTE_DATA attr; if (!GetFileAttributesEx(ConvertUTF8ToWString(filename).c_str(), GetFileExInfoStandard, &attr)) return 0; if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return 0; return ((u64)attr.nFileSizeHigh << 32) | (u64)attr.nFileSizeLow; #else struct stat64 file_info; int result = stat64(filename.c_str(), &file_info); if (result != 0) { WARN_LOG(COMMON, "GetSize: failed %s: No such file", filename.c_str()); return 0; } if (S_ISDIR(file_info.st_mode)) { WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); return 0; } DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)file_info.st_size); return file_info.st_size; #endif }
// Returns file attributes. bool GetFileDetails(const std::string &filename, FileDetails *details) { #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA attr; if (!GetFileAttributesEx(ConvertUTF8ToWString(filename).c_str(), GetFileExInfoStandard, &attr)) return false; details->isDirectory = (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; details->size = ((u64)attr.nFileSizeHigh << 32) | (u64)attr.nFileSizeLow; details->atime = FiletimeToStatTime(attr.ftLastAccessTime); details->mtime = FiletimeToStatTime(attr.ftLastWriteTime); details->ctime = FiletimeToStatTime(attr.ftCreationTime); if (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { details->access = 0444; // Read } else { details->access = 0666; // Read/Write } if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { details->access |= 0111; // Execute } return true; #else if (!Exists(filename)) { return false; } struct stat64 buf; if (stat64(filename.c_str(), &buf) == 0) { details->size = buf.st_size; details->isDirectory = S_ISDIR(buf.st_mode); details->atime = buf.st_atime; details->mtime = buf.st_mtime; details->ctime = buf.st_ctime; details->access = buf.st_mode & 0x1ff; return true; } else { return false; } #endif }
bool MipsAssembleOpcode(const char* line, DebugInterface* cpu, u32 address) { #if defined(_WIN32) || defined(ANDROID) PspAssemblerFile file; StringList errors; wchar_t str[64]; swprintf(str,64,L".psp\n.org 0x%08X\n",address); ArmipsArguments args; args.mode = ArmipsMode::Memory; args.content = str + ConvertUTF8ToWString(line); args.silent = true; args.memoryFile = &file; args.errorsResult = &errors; symbolMap.GetLabels(args.labels); errorText = L""; if (!runArmips(args)) { for (size_t i = 0; i < errors.size(); i++) { errorText += errors[i]; if (i != errors.size()-1) errorText += L"\n"; } return false; } return true; #else errorText = L"Unsupported platform"; return false; #endif }
// Deletes a given filename, return true on success // Doesn't supports deleting a directory bool Delete(const std::string &filename) { INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); // Return true because we care about the file no // being there, not the actual delete. if (!Exists(filename)) { WARN_LOG(COMMON, "Delete: %s does not exists", filename.c_str()); return true; } // We can't delete a directory if (IsDirectory(filename)) { WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str()); return false; } #ifdef _WIN32 if (!DeleteFile(ConvertUTF8ToWString(filename).c_str())) { WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg()); return false; } #else if (unlink(filename.c_str()) == -1) { WARN_LOG(COMMON, "Delete: unlink failed on %s: %s", filename.c_str(), GetLastErrorMsg()); return false; } #endif return true; }
u64 DirectoryFileSystem::FreeSpace(const std::string &path) { #ifdef _WIN32 const std::wstring w32path = ConvertUTF8ToWString(GetLocalPath(path)); ULARGE_INTEGER free; if (GetDiskFreeSpaceExW(w32path.c_str(), &free, nullptr, nullptr)) return free.QuadPart; #elif defined(__SYMBIAN32__) QSystemStorageInfo storageInfo; return (u64)storageInfo.availableDiskSpace("E"); #else std::string localPath = GetLocalPath(path); struct statvfs diskstat; int res = statvfs(localPath.c_str(), &diskstat); #if HOST_IS_CASE_SENSITIVE std::string fixedCase = path; if (res != 0 && FixPathCase(basePath, fixedCase, FPC_FILE_MUST_EXIST)) { // May have failed due to case sensitivity, try again. localPath = GetLocalPath(fixedCase); res = statvfs(localPath.c_str(), &diskstat); } #endif if (res == 0) { #ifndef ANDROID if (diskstat.f_flag & ST_RDONLY) { return 0; } #endif return (u64)diskstat.f_bavail * (u64)diskstat.f_frsize; } #endif // Just assume they're swimming in free disk space if we don't know otherwise. return std::numeric_limits<u64>::max(); }
// Returns true if file filename exists. Will return true on directories. bool Exists(const std::string &filename) { std::string fn = filename; StripTailDirSlashes(fn); #if defined(_WIN32) std::wstring copy = ConvertUTF8ToWString(fn); // Make sure Windows will no longer handle critical errors, which means no annoying "No disk" dialog #if !PPSSPP_PLATFORM(UWP) int OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif WIN32_FILE_ATTRIBUTE_DATA data{}; if (!GetFileAttributesEx(copy.c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { return false; } #if !PPSSPP_PLATFORM(UWP) SetErrorMode(OldMode); #endif return true; #else struct stat file_info; return stat(fn.c_str(), &file_info) == 0; #endif }
bool SymbolMap::LoadSymbolMap(const char *filename) { Clear(); // let's not recurse the lock lock_guard guard(lock_); #if defined(_WIN32) && defined(UNICODE) gzFile f = gzopen_w(ConvertUTF8ToWString(filename).c_str(), "r"); #else gzFile f = gzopen(filename, "r"); #endif if (f == Z_NULL) return false; //char temp[256]; //fgets(temp,255,f); //.text section layout //fgets(temp,255,f); // Starting Virtual //fgets(temp,255,f); // address Size address //fgets(temp,255,f); // ----------------------- bool started = false; bool hasModules = false; while (!gzeof(f)) { char line[512], temp[256] = {0}; char *p = gzgets(f, line, 512); if (p == NULL) break; // Chop any newlines off. for (size_t i = strlen(line) - 1; i > 0; i--) { if (line[i] == '\r' || line[i] == '\n') { line[i] = '\0'; } } if (strlen(line) < 4 || sscanf(line, "%s", temp) != 1) continue; if (strcmp(temp,"UNUSED")==0) continue; if (strcmp(temp,".text")==0) {started=true;continue;}; if (strcmp(temp,".init")==0) {started=true;continue;}; if (strcmp(temp,"Starting")==0) continue; if (strcmp(temp,"extab")==0) continue; if (strcmp(temp,".ctors")==0) break; if (strcmp(temp,".dtors")==0) break; if (strcmp(temp,".rodata")==0) continue; if (strcmp(temp,".data")==0) continue; if (strcmp(temp,".sbss")==0) continue; if (strcmp(temp,".sdata")==0) continue; if (strcmp(temp,".sdata2")==0) continue; if (strcmp(temp,"address")==0) continue; if (strcmp(temp,"-----------------------")==0) continue; if (strcmp(temp,".sbss2")==0) break; if (temp[1]==']') continue; if (!started) continue; u32 address = -1, size, vaddress = -1; int moduleIndex = 0; int typeInt; SymbolType type; char name[128] = {0}; if (sscanf(line, ".module %x %08x %08x %127c", &moduleIndex, &address, &size, name) == 4) { // Found a module definition. ModuleEntry mod; mod.index = moduleIndex; strcpy(mod.name, name); mod.start = address; mod.size = size; modules.push_back(mod); hasModules = true; continue; } sscanf(line, "%08x %08x %x %i %127c", &address, &size, &vaddress, &typeInt, name); type = (SymbolType) typeInt; if (!hasModules) { if (!Memory::IsValidAddress(vaddress)) { ERROR_LOG(LOADER, "Invalid address in symbol file: %08x (%s)", vaddress, name); continue; } } else { // The 3rd field is now used for the module index. moduleIndex = vaddress; vaddress = GetModuleAbsoluteAddr(address, moduleIndex); if (!Memory::IsValidAddress(vaddress)) { ERROR_LOG(LOADER, "Invalid address in symbol file: %08x (%s)", vaddress, name); continue; } } if (type == ST_DATA && size == 0) size = 4; if (!strcmp(name, ".text") || !strcmp(name, ".init") || strlen(name) <= 1) { } else { switch (type) { case ST_FUNCTION: AddFunction(name, vaddress, size, moduleIndex); break; case ST_DATA: AddData(vaddress,size,DATATYPE_BYTE, moduleIndex); if (name[0] != 0) AddLabel(name, vaddress, moduleIndex); break; case ST_NONE: case ST_ALL: // Shouldn't be possible. break; } } } gzclose(f); SortSymbols(); return started; }
void LaunchBrowser(const char *url) { ShellExecute(NULL, L"open", ConvertUTF8ToWString(url).c_str(), NULL, NULL, SW_SHOWNORMAL); }
void CtrlBreakpointList::handleNotify(LPARAM lParam) { const LPNMHDR header = (LPNMHDR)lParam; if (header->code == NM_DBLCLK) { const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam; gotoBreakpointAddress(item->iItem); return; } if (header->code == NM_RCLICK) { const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE)lParam; showBreakpointMenu(item->iItem, item->ptAction); return; } if (header->code == LVN_GETDISPINFO) { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)lParam; bool isMemory; int index = getBreakpointIndex(dispInfo->item.iItem,isMemory); if (index == -1) return; breakpointText = L""; switch (dispInfo->item.iSubItem) { case BPL_TYPE: { if (isMemory) { switch (displayedMemChecks_[index].cond) { case MEMCHECK_READ: breakpointText = L"Read"; break; case MEMCHECK_WRITE: breakpointText = L"Write"; break; case MEMCHECK_READWRITE: breakpointText = L"Read/Write"; break; } } else { breakpointText = L"Execute"; } } break; case BPL_OFFSET: { wchar_t temp[256]; if (isMemory) { wsprintf(temp,L"0x%08X",displayedMemChecks_[index].start); } else { wsprintf(temp,L"0x%08X",displayedBreakPoints_[index].addr); } breakpointText = temp; } break; case BPL_SIZELABEL: { if (isMemory) { auto mc = displayedMemChecks_[index]; wchar_t temp[256]; if (mc.end == 0) wsprintf(temp,L"0x%08X",1); else wsprintf(temp,L"0x%08X",mc.end-mc.start); breakpointText = temp; } else { const char* sym = cpu->findSymbolForAddress(displayedBreakPoints_[index].addr); if (sym != NULL) { breakpointText = ConvertUTF8ToWString(sym); } else { breakpointText = L"-"; } } } break; case BPL_OPCODE: { if (isMemory) { breakpointText = L"-"; } else { char temp[256]; disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp); breakpointText = ConvertUTF8ToWString(temp); } } break; case BPL_CONDITION: { if (isMemory || displayedBreakPoints_[index].hasCond == false) { breakpointText = L"-"; } else { breakpointText = ConvertUTF8ToWString(displayedBreakPoints_[index].cond.expressionString); } } break; case BPL_HITS: { if (isMemory) { wchar_t temp[256]; wsprintf(temp,L"%d",displayedMemChecks_[index].numHits); breakpointText = temp; } else { breakpointText = L"-"; } } break; case BPL_ENABLED: { if (isMemory) { breakpointText = displayedMemChecks_[index].result & MEMCHECK_BREAK ? L"True" : L"False"; } else { breakpointText = displayedBreakPoints_[index].enabled ? L"True" : L"False"; } } break; default: return; } if (breakpointText.empty()) breakpointText = L"Invalid"; dispInfo->item.pszText = &breakpointText[0]; } }
void CtrlThreadList::handleNotify(LPARAM lParam) { LPNMHDR mhdr = (LPNMHDR) lParam; if (mhdr->code == NM_DBLCLK) { LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam; u32 address; switch (threads[item->iItem].status) { case THREADSTATUS_DORMANT: case THREADSTATUS_DEAD: address = threads[item->iItem].entrypoint; break; default: address = threads[item->iItem].curPC; break; } SendMessage(GetParent(wnd),WM_DEB_GOTOWPARAM,address,0); return; } if (mhdr->code == NM_RCLICK) { const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE)lParam; showMenu(item->iItem, item->ptAction); return; } if (mhdr->code == LVN_GETDISPINFO) { NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)lParam; int index = dispInfo->item.iItem; stringBuffer[0] = 0; switch (dispInfo->item.iSubItem) { case TL_NAME: wcscpy(stringBuffer, ConvertUTF8ToWString(threads[index].name).c_str()); break; case TL_PROGRAMCOUNTER: switch (threads[index].status) { case THREADSTATUS_DORMANT: case THREADSTATUS_DEAD: wcscpy(stringBuffer, L"N/A"); break; default: wsprintf(stringBuffer, L"0x%08X",threads[index].curPC); break; }; break; case TL_ENTRYPOINT: wsprintf(stringBuffer,L"0x%08X",threads[index].entrypoint); break; case TL_PRIORITY: wsprintf(stringBuffer,L"%d",threads[index].priority); break; case TL_STATE: switch (threads[index].status) { case THREADSTATUS_RUNNING: wcscpy(stringBuffer,L"Running"); break; case THREADSTATUS_READY: wcscpy(stringBuffer,L"Ready"); break; case THREADSTATUS_WAIT: wcscpy(stringBuffer,L"Waiting"); break; case THREADSTATUS_SUSPEND: wcscpy(stringBuffer,L"Suspended"); break; case THREADSTATUS_DORMANT: wcscpy(stringBuffer,L"Dormant"); break; case THREADSTATUS_DEAD: wcscpy(stringBuffer,L"Dead"); break; case THREADSTATUS_WAITSUSPEND: wcscpy(stringBuffer,L"Waiting/Suspended"); break; default: wcscpy(stringBuffer,L"Invalid"); break; } break; case TL_WAITTYPE: wcscpy(stringBuffer, ConvertUTF8ToWString(getWaitTypeName(threads[index].waitType)).c_str()); break; } if (stringBuffer[0] == 0) wcscat(stringBuffer,L"Invalid"); dispInfo->item.pszText = stringBuffer; } }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("Emu"); // And graphics... host = new WindowsHost(MainWindow::GetHInstance(), MainWindow::GetHWND(), MainWindow::GetDisplayHWND()); host->SetWindowTitle(nullptr); // Convert the command-line arguments to Unicode, then to proper UTF-8 // (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of Convert<whatever>To<whatever>). // This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs // (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..). // -TheDax std::vector<std::wstring> wideArgs = GetWideCmdLine(); std::vector<std::string> argsUTF8; for (auto& string : wideArgs) { argsUTF8.push_back(ConvertWStringToUTF8(string)); } std::vector<const char *> args; for (auto& string : argsUTF8) { args.push_back(string.c_str()); } bool performingRestart = NativeIsRestarting(); NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", nullptr); host->UpdateUI(); GraphicsContext *graphicsContext = nullptr; std::string error_string; if (!host->InitGraphics(&error_string, &graphicsContext)) { // Before anything: are we restarting right now? if (performingRestart) { // Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart. // This happens on NVIDIA when switching OpenGL -> Vulkan. g_Config.Save(); W32Util::ExitAndRestart(); } I18NCategory *err = GetI18NCategory("Error"); Reporting::ReportMessage("Graphics init error: %s", error_string.c_str()); const char *defaultErrorVulkan = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to OpenGL?\n\nError message:"; const char *defaultErrorOpenGL = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message:"; const char *defaultErrorDirect3D9 = "Failed initializing graphics. Try upgrading your graphics drivers and directx 9 runtime.\n\nWould you like to try switching to OpenGL?\n\nError message:"; const char *genericError; int nextBackend = GPU_BACKEND_DIRECT3D9; switch (g_Config.iGPUBackend) { case GPU_BACKEND_DIRECT3D9: nextBackend = GPU_BACKEND_OPENGL; genericError = err->T("GenericDirect3D9Error", defaultErrorDirect3D9); break; case GPU_BACKEND_VULKAN: nextBackend = GPU_BACKEND_OPENGL; genericError = err->T("GenericVulkanError", defaultErrorVulkan); break; case GPU_BACKEND_OPENGL: default: nextBackend = GPU_BACKEND_DIRECT3D9; genericError = err->T("GenericOpenGLError", defaultErrorOpenGL); break; } std::string full_error = StringFromFormat("%s\n\n%s", genericError, error_string.c_str()); std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); bool yes = IDYES == MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); ERROR_LOG(BOOT, full_error.c_str()); if (yes) { // Change the config to the alternative and restart. g_Config.iGPUBackend = nextBackend; g_Config.Save(); W32Util::ExitAndRestart(); } // No safe way out without graphics. ExitProcess(1); } NativeInitGraphics(graphicsContext); NativeResized(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); while (GetUIState() != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(graphicsContext); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). NativeShutdown(); _InterlockedExchange(&emuThreadReady, THREAD_END); return 0; }
// Deletes the given directory and anything under it. Returns true on success. bool DeleteDirRecursively(const std::string &directory) { #if PPSSPP_PLATFORM(UWP) return false; #else INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory.c_str()); #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(ConvertUTF8ToWString(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } // windows loop do { const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName); #else struct dirent *result = NULL; DIR *dirp = opendir(directory.c_str()); if (!dirp) return false; // non windows loop while ((result = readdir(dirp))) { const std::string virtualName = result->d_name; #endif // check for "." and ".." if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; std::string newPath = directory + DIR_SEP + virtualName; if (IsDirectory(newPath)) { if (!DeleteDirRecursively(newPath)) { #ifndef _WIN32 closedir(dirp); #else FindClose(hFind); #endif return false; } } else { if (!File::Delete(newPath)) { #ifndef _WIN32 closedir(dirp); #else FindClose(hFind); #endif return false; } } #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif return File::DeleteDir(directory); #endif }
// copies file srcFilename to destFilename, returns true on success bool Copy(const std::string &srcFilename, const std::string &destFilename) { INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 #if PPSSPP_PLATFORM(UWP) if (CopyFile2(ConvertUTF8ToWString(srcFilename).c_str(), ConvertUTF8ToWString(destFilename).c_str(), nullptr)) return true; return false; #else if (CopyFile(ConvertUTF8ToWString(srcFilename).c_str(), ConvertUTF8ToWString(destFilename).c_str(), FALSE)) return true; #endif ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; #else // buffer size #define BSIZE 1024 char buffer[BSIZE]; // Open input file FILE *input = fopen(srcFilename.c_str(), "rb"); if (!input) { ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; } // open output file FILE *output = fopen(destFilename.c_str(), "wb"); if (!output) { fclose(input); ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); return false; } // copy loop while (!feof(input)) { // read input int rnum = fread(buffer, sizeof(char), BSIZE, input); if (rnum != BSIZE) { if (ferror(input) != 0) { ERROR_LOG(COMMON, "Copy: failed reading from source, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); fclose(input); fclose(output); return false; } } // write output int wnum = fwrite(buffer, sizeof(char), rnum, output); if (wnum != rnum) { ERROR_LOG(COMMON, "Copy: failed writing to output, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); fclose(input); fclose(output); return false; } } // close flushs fclose(input); fclose(output); return true; #endif }
void CtrlBreakpointList::GetColumnText(wchar_t* dest, int row, int col) { bool isMemory; int index = getBreakpointIndex(row,isMemory); if (index == -1) return; switch (col) { case BPL_TYPE: { if (isMemory) { switch (displayedMemChecks_[index].cond) { case MEMCHECK_READ: wcscpy(dest,L"Read"); break; case MEMCHECK_WRITE: wcscpy(dest,L"Write"); break; case MEMCHECK_READWRITE: wcscpy(dest,L"Read/Write"); break; } } else { wcscpy(dest,L"Execute"); } } break; case BPL_OFFSET: { if (isMemory) { wsprintf(dest,L"0x%08X",displayedMemChecks_[index].start); } else { wsprintf(dest,L"0x%08X",displayedBreakPoints_[index].addr); } } break; case BPL_SIZELABEL: { if (isMemory) { auto mc = displayedMemChecks_[index]; if (mc.end == 0) wsprintf(dest,L"0x%08X",1); else wsprintf(dest,L"0x%08X",mc.end-mc.start); } else { const char* sym = cpu->findSymbolForAddress(displayedBreakPoints_[index].addr); if (sym != NULL) { std::wstring s = ConvertUTF8ToWString(sym); wcscpy(dest,s.c_str()); } else { wcscpy(dest,L"-"); } } } break; case BPL_OPCODE: { if (isMemory) { wcscpy(dest,L"-"); } else { char temp[256]; disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp); std::wstring s = ConvertUTF8ToWString(temp); wcscpy(dest,s.c_str()); } } break; case BPL_CONDITION: { if (isMemory || displayedBreakPoints_[index].hasCond == false) { wcscpy(dest,L"-"); } else { std::wstring s = ConvertUTF8ToWString(displayedBreakPoints_[index].cond.expressionString); wcscpy(dest,s.c_str()); } } break; case BPL_HITS: { if (isMemory) { wsprintf(dest,L"%d",displayedMemChecks_[index].numHits); } else { wsprintf(dest,L"-"); } } break; case BPL_ENABLED: { if (isMemory) { wsprintf(dest,displayedMemChecks_[index].result & MEMCHECK_BREAK ? L"True" : L"False"); } else { wsprintf(dest,displayedBreakPoints_[index].enabled ? L"True" : L"False"); } } break; } }
BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { //if (!m_hDlg) return FALSE; switch(message) { case WM_INITDIALOG: { return TRUE; } break; case WM_NOTIFY: switch (wParam) { case IDC_LEFTTABS: leftTabs->HandleNotify(lParam); break; case IDC_BREAKPOINTLIST: breakpointList->HandleNotify(lParam); break; case IDC_THREADLIST: threadList->HandleNotify(lParam); break; case IDC_STACKFRAMES: stackTraceView->HandleNotify(lParam); break; case IDC_MODULELIST: moduleList->HandleNotify(lParam); break; case IDC_DEBUG_BOTTOMTABS: bottomTabs->HandleNotify(lParam); break; } break; case WM_COMMAND: { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); CtrlRegisterList *reglist = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST)); switch(LOWORD(wParam)) { case ID_TOGGLE_PAUSE: SendMessage(MainWindow::GetHWND(),WM_COMMAND,ID_TOGGLE_PAUSE,0); break; case ID_DEBUG_DISPLAYMEMVIEW: bottomTabs->ShowTab(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW)); break; case ID_DEBUG_DISPLAYBREAKPOINTLIST: bottomTabs->ShowTab(breakpointList->GetHandle()); break; case ID_DEBUG_DISPLAYTHREADLIST: bottomTabs->ShowTab(threadList->GetHandle()); break; case ID_DEBUG_DISPLAYSTACKFRAMELIST: bottomTabs->ShowTab(stackTraceView->GetHandle()); break; case ID_DEBUG_DSIPLAYREGISTERLIST: leftTabs->ShowTab(0); break; case ID_DEBUG_DSIPLAYFUNCTIONLIST: leftTabs->ShowTab(1); break; case ID_DEBUG_ADDBREAKPOINT: { keepStatusBarText = true; bool isRunning = Core_IsActive(); if (isRunning) { SetDebugMode(true, false); Core_EnableStepping(true); Core_WaitInactive(200); } BreakpointWindow bpw(m_hDlg,cpu); if (bpw.exec()) bpw.addBreakpoint(); if (isRunning) { SetDebugMode(false, false); Core_EnableStepping(false); } keepStatusBarText = false; } break; case ID_DEBUG_STEPOVER: if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) stepOver(); break; case ID_DEBUG_STEPINTO: if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) stepInto(); break; case ID_DEBUG_RUNTOLINE: if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) runToLine(); break; case ID_DEBUG_STEPOUT: if (GetFocus() == GetDlgItem(m_hDlg,IDC_DISASMVIEW)) stepOut(); break; case ID_DEBUG_HIDEBOTTOMTABS: { RECT rect; hideBottomTabs = !hideBottomTabs; GetClientRect(m_hDlg,&rect); UpdateSize(rect.right-rect.left,rect.bottom-rect.top); } break; case ID_DEBUG_TOGGLEBOTTOMTABTITLES: bottomTabs->SetShowTabTitles(!bottomTabs->GetShowTabTitles()); break; case IDC_SHOWVFPU: vfpudlg->Show(true); break; case IDC_FUNCTIONLIST: switch (HIWORD(wParam)) { case CBN_DBLCLK: { HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ListBox_GetCurSel(lb); if (n!=-1) { unsigned int addr = (unsigned int)ListBox_GetItemData(lb,n); ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } } break; }; break; case IDC_GOTOINT: switch (HIWORD(wParam)) { case LBN_SELCHANGE: { HWND lb =GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ComboBox_GetCurSel(lb); unsigned int addr = (unsigned int)ComboBox_GetItemData(lb,n); if (addr != 0xFFFFFFFF) { ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } } break; }; break; case IDC_STOPGO: { if (!PSP_IsInited()) { break; } if (!Core_IsStepping()) // stop { ptr->setDontRedraw(false); SetDebugMode(true, true); Core_EnableStepping(true); _dbg_update_(); Sleep(1); //let cpu catch up ptr->gotoPC(); UpdateDialog(); vfpudlg->Update(); } else { // go lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); SetDebugMode(false, true); Core_EnableStepping(false); } } break; case IDC_STEP: stepInto(); break; case IDC_STEPOVER: stepOver(); break; case IDC_STEPOUT: stepOut(); break; case IDC_STEPHLE: { if (Core_IsActive()) break; lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); hleDebugBreak(); SetDebugMode(false, true); _dbg_update_(); Core_EnableStepping(false); } break; case IDC_MEMCHECK: SendMessage(m_hDlg,WM_COMMAND,ID_DEBUG_ADDBREAKPOINT,0); break; case IDC_GOTOPC: { ptr->gotoPC(); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); UpdateDialog(); } break; case IDC_GOTOLR: { ptr->gotoAddr(cpu->GetLR()); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } break; case IDC_ALLFUNCTIONS: { symbolMap.FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); break; } default: return FALSE; } return TRUE; } case WM_DEB_MAPLOADED: NotifyMapLoaded(); break; case WM_DEB_GOTOWPARAM: { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); ptr->gotoAddr(wParam); SetFocus(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); break; } case WM_DEB_GOTOADDRESSEDIT: { if (!PSP_IsInited()) { break; } wchar_t szBuffer[256]; CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); GetWindowText(GetDlgItem(m_hDlg,IDC_ADDRESS),szBuffer,256); u32 addr; if (parseExpression(ConvertWStringToUTF8(szBuffer).c_str(),cpu,addr) == false) { displayExpressionError(GetDlgItem(m_hDlg,IDC_ADDRESS)); } else { ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } UpdateDialog(); } break; case WM_DEB_SETDEBUGLPARAM: SetDebugMode(lParam != 0, true); return TRUE; case WM_DEB_UPDATE: Update(); return TRUE; case WM_DEB_TABPRESSED: bottomTabs->NextTab(true); SetFocus(bottomTabs->CurrentTabHandle()); break; case WM_DEB_SETSTATUSBARTEXT: if (!keepStatusBarText) SetWindowText(statusBarWnd, ConvertUTF8ToWString((const char *)lParam).c_str()); break; case WM_DEB_GOTOHEXEDIT: { CtrlMemView *memory = CtrlMemView::getFrom(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW)); memory->gotoAddr(wParam); // display the memory viewer too bottomTabs->ShowTab(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW)); } break; case WM_SIZE: { UpdateSize(LOWORD(lParam), HIWORD(lParam)); SendMessage(statusBarWnd,WM_SIZE,0,10); SavePosition(); return TRUE; } case WM_MOVE: SavePosition(); break; case WM_GETMINMAXINFO: { MINMAXINFO *m = (MINMAXINFO *)lParam; // Reduce the minimum size slightly, so they can size it however they like. m->ptMinTrackSize.x = minWidth; //m->ptMaxTrackSize.x = m->ptMinTrackSize.x; m->ptMinTrackSize.y = minHeight; } return TRUE; case WM_CLOSE: Show(false); return TRUE; case WM_ACTIVATE: if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { g_activeWindow = WINDOW_CPUDEBUGGER; } break; } return FALSE; }
// Run this at startup time. Please use GetSysDirectory if you need to query where folders are. void InitSysDirectories() { if (!g_Config.memCardDirectory.empty() && !g_Config.flash0Directory.empty()) return; const std::string path = ConvertWStringToUTF8(File::GetExeDirectory()); // Mount a filesystem g_Config.flash0Directory = path + "/flash0/"; // Detect the "My Documents"(XP) or "Documents"(on Vista/7/8) folder. wchar_t myDocumentsPath[MAX_PATH]; const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/"; const std::string installedFile = path + "/installed.txt"; const bool installed = File::Exists(installedFile); // If installed.txt exists(and we can determine the Documents directory) if (installed && (result == S_OK)) { std::ifstream inputFile(ConvertUTF8ToWString(installedFile)); if (!inputFile.fail() && inputFile.is_open()) { std::string tempString; std::getline(inputFile, tempString); // Skip UTF-8 encoding bytes if there are any. There are 3 of them. if (tempString.substr(0, 3) == "\xEF\xBB\xBF") tempString = tempString.substr(3); g_Config.memCardDirectory = tempString; } inputFile.close(); // Check if the file is empty first, before appending the slash. if (g_Config.memCardDirectory.empty()) g_Config.memCardDirectory = myDocsPath; size_t lastSlash = g_Config.memCardDirectory.find_last_of("/"); if (lastSlash != (g_Config.memCardDirectory.length() - 1)) g_Config.memCardDirectory.append("/"); } else { g_Config.memCardDirectory = path + "/memstick/"; } // Create the memstickpath before trying to write to it, and fall back on Documents yet again // if we can't make it. if (!File::Exists(g_Config.memCardDirectory)) { if (!File::CreateDir(g_Config.memCardDirectory)) g_Config.memCardDirectory = myDocsPath; } const std::string testFile = "/_writable_test.$$$"; // If any directory is read-only, fall back to the Documents directory. // We're screwed anyway if we can't write to Documents, or can't detect it. if (!File::CreateEmptyFile(g_Config.memCardDirectory + testFile)) g_Config.memCardDirectory = myDocsPath; // Clean up our mess. if (File::Exists(g_Config.memCardDirectory + testFile)) File::Delete(g_Config.memCardDirectory + testFile); if (g_Config.currentDirectory.empty()) { g_Config.currentDirectory = GetSysDirectory(DIRECTORY_GAME); } }
bool DirectoryFileHandle::Open(std::string& basePath, std::string& fileName, FileAccess access) { #if HOST_IS_CASE_SENSITIVE if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE)) { DEBUG_LOG(FILESYS, "Checking case for path %s", fileName.c_str()); if ( ! FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST) ) return false; // or go on and attempt (for a better error code than just 0?) } // else we try fopen first (in case we're lucky) before simulating case insensitivity #endif std::string fullName = GetLocalPath(basePath,fileName); DEBUG_LOG(FILESYS,"Actually opening %s", fullName.c_str()); // On the PSP, truncating doesn't lose data. If you seek later, you'll recover it. // This is abnormal, so we deviate from the PSP's behavior and truncate on write/close. // This means it's incorrectly not truncated before the write. if (access & FILEACCESS_TRUNCATE) { needsTrunc_ = 0; } //TODO: tests, should append seek to end of file? seeking in a file opened for append? #ifdef _WIN32_NO_MINGW // Convert parameters to Windows permissions and access DWORD desired = 0; DWORD sharemode = 0; DWORD openmode = 0; if (access & FILEACCESS_READ) { desired |= GENERIC_READ; sharemode |= FILE_SHARE_READ; } if (access & FILEACCESS_WRITE) { desired |= GENERIC_WRITE; sharemode |= FILE_SHARE_WRITE; } if (access & FILEACCESS_CREATE) { openmode = OPEN_ALWAYS; } else { openmode = OPEN_EXISTING; } //Let's do it! hFile = CreateFile(ConvertUTF8ToWString(fullName).c_str(), desired, sharemode, 0, openmode, 0, 0); bool success = hFile != INVALID_HANDLE_VALUE; #else int flags = 0; if (access & FILEACCESS_APPEND) { flags |= O_APPEND; } if ((access & FILEACCESS_READ) && (access & FILEACCESS_WRITE)) { flags |= O_RDWR; } else if (access & FILEACCESS_READ) { flags |= O_RDONLY; } else if (access & FILEACCESS_WRITE) { flags |= O_WRONLY; } if (access & FILEACCESS_CREATE) { flags |= O_CREAT; } hFile = open(fullName.c_str(), flags, 0666); bool success = hFile != -1; #endif #if HOST_IS_CASE_SENSITIVE if (!success && !(access & FILEACCESS_CREATE)) { if ( ! FixPathCase(basePath,fileName, FPC_PATH_MUST_EXIST) ) return 0; // or go on and attempt (for a better error code than just 0?) fullName = GetLocalPath(basePath,fileName); const char *fullNameC = fullName.c_str(); DEBUG_LOG(FILESYS, "Case may have been incorrect, second try opening %s (%s)", fullNameC, fileName.c_str()); // And try again with the correct case this time #ifdef _WIN32_NO_MINGW hFile = CreateFile(fullNameC, desired, sharemode, 0, openmode, 0, 0); success = hFile != INVALID_HANDLE_VALUE; #else hFile = open(fullNameC, flags, 0666); success = hFile != -1; #endif } #endif #ifndef _WIN32 if (success) { struct stat st; if (fstat(hFile, &st) == 0 && S_ISDIR(st.st_mode)) { close(hFile); errno = EISDIR; success = false; } } #endif return success; }
std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) { std::vector<PSPFileInfo> myVector; #ifdef _WIN32_NO_MINGW WIN32_FIND_DATA findData; HANDLE hFind; std::string w32path = GetLocalPath(path) + "\\*.*"; hFind = FindFirstFile(ConvertUTF8ToWString(w32path).c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return myVector; //the empty list } while (true) { PSPFileInfo entry; if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) entry.type = FILETYPE_DIRECTORY; else entry.type = FILETYPE_NORMAL; // TODO: Make this more correct? entry.access = entry.type == FILETYPE_NORMAL ? 0666 : 0777; // TODO: is this just for .. or all subdirectories? Need to add a directory to the test // to find out. Also why so different than the old test results? if (!wcscmp(findData.cFileName, L"..") ) entry.size = 4096; else entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32); entry.name = ConvertWStringToUTF8(findData.cFileName); tmFromFiletime(entry.atime, findData.ftLastAccessTime); tmFromFiletime(entry.ctime, findData.ftCreationTime); tmFromFiletime(entry.mtime, findData.ftLastWriteTime); myVector.push_back(entry); int retval = FindNextFile(hFind, &findData); if (!retval) break; } FindClose(hFind); #else dirent *dirp; std::string localPath = GetLocalPath(path); DIR *dp = opendir(localPath.c_str()); #if HOST_IS_CASE_SENSITIVE if(dp == NULL && FixPathCase(basePath,path, FPC_FILE_MUST_EXIST)) { // May have failed due to case sensitivity, try again localPath = GetLocalPath(path); dp = opendir(localPath.c_str()); } #endif if (dp == NULL) { ERROR_LOG(FILESYS,"Error opening directory %s\n",path.c_str()); return myVector; } while ((dirp = readdir(dp)) != NULL) { PSPFileInfo entry; struct stat s; std::string fullName = GetLocalPath(path) + "/"+dirp->d_name; stat(fullName.c_str(), &s); if (S_ISDIR(s.st_mode)) entry.type = FILETYPE_DIRECTORY; else entry.type = FILETYPE_NORMAL; entry.access = s.st_mode & 0x1FF; entry.name = dirp->d_name; entry.size = s.st_size; localtime_r((time_t*)&s.st_atime,&entry.atime); localtime_r((time_t*)&s.st_ctime,&entry.ctime); localtime_r((time_t*)&s.st_mtime,&entry.mtime); myVector.push_back(entry); } closedir(dp); #endif return myVector; }
void CtrlThreadList::GetColumnText(wchar_t* dest, int row, int col) { if (row < 0 || row >= (int)threads.size()) { return; } switch (col) { case TL_NAME: wcscpy(dest, ConvertUTF8ToWString(threads[row].name).c_str()); break; case TL_PROGRAMCOUNTER: switch (threads[row].status) { case THREADSTATUS_DORMANT: case THREADSTATUS_DEAD: wcscpy(dest, L"N/A"); break; default: wsprintf(dest, L"0x%08X",threads[row].curPC); break; }; break; case TL_ENTRYPOINT: wsprintf(dest,L"0x%08X",threads[row].entrypoint); break; case TL_PRIORITY: wsprintf(dest,L"%d",threads[row].priority); break; case TL_STATE: switch (threads[row].status) { case THREADSTATUS_RUNNING: wcscpy(dest,L"Running"); break; case THREADSTATUS_READY: wcscpy(dest,L"Ready"); break; case THREADSTATUS_WAIT: wcscpy(dest,L"Waiting"); break; case THREADSTATUS_SUSPEND: wcscpy(dest,L"Suspended"); break; case THREADSTATUS_DORMANT: wcscpy(dest,L"Dormant"); break; case THREADSTATUS_DEAD: wcscpy(dest,L"Dead"); break; case THREADSTATUS_WAITSUSPEND: wcscpy(dest,L"Waiting/Suspended"); break; default: wcscpy(dest,L"Invalid"); break; } break; case TL_WAITTYPE: wcscpy(dest, ConvertUTF8ToWString(getWaitTypeName(threads[row].waitType)).c_str()); break; } }
size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter) { size_t foundEntries = 0; std::set<std::string> filters; std::string tmp; if (filter) { while (*filter) { if (*filter == ':') { filters.insert(tmp); tmp = ""; } else { tmp.push_back(*filter); } filter++; } } if (tmp.size()) filters.insert(tmp); #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; #ifdef UNICODE HANDLE hFind = FindFirstFile((ConvertUTF8ToWString(directory) + L"\\*").c_str(), &ffd); #else HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); #endif if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return 0; } // windows loop do { const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName); #else struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; }; struct dirent_large diren; struct dirent *result = NULL; //std::string directoryWithSlash = directory; //if (directoryWithSlash.back() != '/') // directoryWithSlash += "/"; DIR *dirp = opendir(directory); if (!dirp) return 0; // non windows loop while (!readdir_r(dirp, (dirent*) &diren, &result) && result) { const std::string virtualName(result->d_name); #endif // check for "." and ".." if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; // Remove dotfiles (should be made optional?) if (virtualName[0] == '.') continue; FileInfo info; info.name = virtualName; std::string dir = directory; // Only append a slash if there isn't one on the end. size_t lastSlash = dir.find_last_of("/"); if (lastSlash != (dir.length() - 1)) dir.append("/"); info.fullName = dir + virtualName; info.isDirectory = isDirectory(info.fullName); info.exists = true; info.size = 0; if (!info.isDirectory) { std::string ext = getFileExtension(info.fullName); if (filter) { if (filters.find(ext) == filters.end()) continue; } } if (files) files->push_back(info); foundEntries++; #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif if (files) std::sort(files->begin(), files->end()); return foundEntries; }
void CtrlBreakpointList::GetColumnText(wchar_t* dest, int row, int col) { if (!PSP_IsInited()) { return; } bool isMemory; int index = getBreakpointIndex(row,isMemory); if (index == -1) return; switch (col) { case BPL_TYPE: { if (isMemory) { switch ((int)displayedMemChecks_[index].cond) { case MEMCHECK_READ: wcscpy(dest,L"Read"); break; case MEMCHECK_WRITE: wcscpy(dest,L"Write"); break; case MEMCHECK_READWRITE: wcscpy(dest,L"Read/Write"); break; case MEMCHECK_WRITE | MEMCHECK_WRITE_ONCHANGE: wcscpy(dest,L"Write Change"); break; case MEMCHECK_READWRITE | MEMCHECK_WRITE_ONCHANGE: wcscpy(dest,L"Read/Write Change"); break; } } else { wcscpy(dest,L"Execute"); } } break; case BPL_OFFSET: { if (isMemory) { wsprintf(dest,L"0x%08X",displayedMemChecks_[index].start); } else { wsprintf(dest,L"0x%08X",displayedBreakPoints_[index].addr); } } break; case BPL_SIZELABEL: { if (isMemory) { auto mc = displayedMemChecks_[index]; if (mc.end == 0) wsprintf(dest,L"0x%08X",1); else wsprintf(dest,L"0x%08X",mc.end-mc.start); } else { const std::string sym = g_symbolMap->GetLabelString(displayedBreakPoints_[index].addr); if (!sym.empty()) { std::wstring s = ConvertUTF8ToWString(sym); wcscpy(dest,s.c_str()); } else { wcscpy(dest,L"-"); } } } break; case BPL_OPCODE: { if (isMemory) { wcscpy(dest,L"-"); } else { char temp[256]; disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp, sizeof(temp)); std::wstring s = ConvertUTF8ToWString(temp); wcscpy(dest,s.c_str()); } } break; case BPL_CONDITION: { if (isMemory || displayedBreakPoints_[index].hasCond == false) { wcscpy(dest,L"-"); } else { std::wstring s = ConvertUTF8ToWString(displayedBreakPoints_[index].cond.expressionString); wcscpy(dest,s.c_str()); } } break; case BPL_HITS: { if (isMemory) { wsprintf(dest,L"%d",displayedMemChecks_[index].numHits); } else { wsprintf(dest,L"-"); } } break; case BPL_ENABLED: { wsprintf(dest,L"\xFFFE"); } break; } }
CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent) { cpu = _cpu; lastTicks = PSP_IsInited() ? CoreTiming::GetTicks() : 0; keepStatusBarText = false; hideBottomTabs = false; SetWindowText(m_hDlg, ConvertUTF8ToWString(_cpu->GetName()).c_str()); #ifdef THEMES //if (WTL::CTheme::IsThemingSupported()) //EnableThemeDialogTexture(m_hDlg ,ETDT_ENABLETAB); #endif RECT windowRect; GetWindowRect(m_hDlg,&windowRect); int defaultWidth = windowRect.right-windowRect.left; int defaultHeight = windowRect.bottom-windowRect.top; minWidth = defaultWidth - 100; minHeight = defaultHeight - 200; int x = g_Config.iDisasmWindowX == -1 ? windowRect.left : g_Config.iDisasmWindowX; int y = g_Config.iDisasmWindowY == -1 ? windowRect.top : g_Config.iDisasmWindowY; int w = g_Config.iDisasmWindowW == -1 ? defaultWidth : g_Config.iDisasmWindowW; int h = g_Config.iDisasmWindowH == -1 ? defaultHeight : g_Config.iDisasmWindowH; // init status bar statusBarWnd = CreateWindowEx(0, STATUSCLASSNAME, L"", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, m_hDlg, (HMENU)IDC_DISASMSTATUSBAR, _hInstance, NULL); if (g_Config.bDisplayStatusBar == false) { ShowWindow(statusBarWnd,SW_HIDE); } CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); ptr->setDebugger(cpu); ptr->gotoAddr(0x00000000); CtrlRegisterList *rl = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST)); rl->setCPU(cpu); leftTabs = new TabControl(GetDlgItem(m_hDlg,IDC_LEFTTABS)); leftTabs->SetIgnoreBottomMargin(true); leftTabs->AddTab(GetDlgItem(m_hDlg,IDC_REGLIST),L"Regs"); leftTabs->AddTab(GetDlgItem(m_hDlg,IDC_FUNCTIONLIST),L"Funcs"); leftTabs->ShowTab(0); // subclass the goto edit box HWND editWnd = GetDlgItem(m_hDlg,IDC_ADDRESS); DefGotoEditProc = (WNDPROC)GetWindowLongPtr(editWnd,GWLP_WNDPROC); SetWindowLongPtr(editWnd,GWLP_WNDPROC,(LONG_PTR)GotoEditProc); // subclass the function list HWND funcListWnd = GetDlgItem(m_hDlg,IDC_FUNCTIONLIST); DefFuncListProc = (WNDPROC)GetWindowLongPtr(funcListWnd,GWLP_WNDPROC); SetWindowLongPtr(funcListWnd,GWLP_WNDPROC,(LONG_PTR)FuncListProc); // init bottom tabs bottomTabs = new TabControl(GetDlgItem(m_hDlg,IDC_DEBUG_BOTTOMTABS)); HWND memHandle = GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW); CtrlMemView *mem = CtrlMemView::getFrom(memHandle); mem->setDebugger(_cpu); bottomTabs->AddTab(memHandle,L"Memory"); breakpointList = new CtrlBreakpointList(GetDlgItem(m_hDlg,IDC_BREAKPOINTLIST),cpu,ptr); breakpointList->reloadBreakpoints(); bottomTabs->AddTab(breakpointList->GetHandle(),L"Breakpoints"); threadList = new CtrlThreadList(GetDlgItem(m_hDlg,IDC_THREADLIST)); threadList->reloadThreads(); bottomTabs->AddTab(threadList->GetHandle(),L"Threads"); stackTraceView = new CtrlStackTraceView(GetDlgItem(m_hDlg,IDC_STACKFRAMES),cpu,ptr); stackTraceView->loadStackTrace(); bottomTabs->AddTab(stackTraceView->GetHandle(),L"Stack frames"); moduleList = new CtrlModuleList(GetDlgItem(m_hDlg,IDC_MODULELIST),cpu); moduleList->loadModules(); bottomTabs->AddTab(moduleList->GetHandle(),L"Modules"); bottomTabs->SetShowTabTitles(g_Config.bShowBottomTabTitles); bottomTabs->ShowTab(memHandle); // Actually resize the window to the proper size (after the above setup.) // do it twice so that the window definitely receives a WM_SIZE message with // the correct size (the default from the .rc tends to be off) MoveWindow(m_hDlg,x,y,1,1,FALSE); MoveWindow(m_hDlg,x,y,w,h,TRUE); SetDebugMode(true, true); }
std::string ResolvePath(const std::string &path) { #ifdef _WIN32 typedef DWORD (WINAPI *getFinalPathNameByHandleW_f)(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags); static getFinalPathNameByHandleW_f getFinalPathNameByHandleW = nullptr; #if PPSSPP_PLATFORM(UWP) getFinalPathNameByHandleW = &GetFinalPathNameByHandleW; #else if (!getFinalPathNameByHandleW) { HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); getFinalPathNameByHandleW = (getFinalPathNameByHandleW_f)GetProcAddress(kernel32, "GetFinalPathNameByHandleW"); } #endif static const int BUF_SIZE = 32768; wchar_t *buf = new wchar_t[BUF_SIZE]; memset(buf, 0, BUF_SIZE); std::wstring input = ConvertUTF8ToWString(path); if (getFinalPathNameByHandleW) { #if PPSSPP_PLATFORM(UWP) HANDLE hFile = CreateFile2(input.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); #else HANDLE hFile = CreateFile(input.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); #endif if (hFile == INVALID_HANDLE_VALUE) { wcscpy_s(buf, BUF_SIZE - 1, input.c_str()); } else { int result = getFinalPathNameByHandleW(hFile, buf, BUF_SIZE - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); if (result >= BUF_SIZE || result == 0) wcscpy_s(buf, BUF_SIZE - 1, input.c_str()); CloseHandle(hFile); } } else { wchar_t *longBuf = new wchar_t[BUF_SIZE]; memset(buf, 0, BUF_SIZE); int result = GetLongPathNameW(input.c_str(), longBuf, BUF_SIZE - 1); if (result >= BUF_SIZE || result == 0) wcscpy_s(longBuf, BUF_SIZE - 1, input.c_str()); result = GetFullPathNameW(longBuf, BUF_SIZE - 1, buf, nullptr); if (result >= BUF_SIZE || result == 0) wcscpy_s(buf, BUF_SIZE - 1, input.c_str()); delete [] longBuf; // Normalize slashes just in case. for (int i = 0; i < BUF_SIZE; ++i) { if (buf[i] == '\\') buf[i] = '/'; } } // Undo the \\?\C:\ syntax that's normally returned. std::string output = ConvertWStringToUTF8(buf); if (buf[0] == '\\' && buf[1] == '\\' && buf[2] == '?' && buf[3] == '\\' && isalpha(buf[4]) && buf[5] == ':') output = output.substr(4); delete [] buf; return output; #else std::unique_ptr<char[]> buf(new char[PATH_MAX + 32768]); if (realpath(path.c_str(), buf.get()) == nullptr) return path; return buf.get(); #endif }