std::string& GetExeDirectory() { static std::string DolphinPath; if (DolphinPath.empty()) { #ifdef _WIN32 TCHAR Dolphin_exe_Path[2048]; TCHAR Dolphin_exe_Clean_Path[MAX_PATH]; GetModuleFileName(nullptr, Dolphin_exe_Path, 2048); if (_tfullpath(Dolphin_exe_Clean_Path, Dolphin_exe_Path, MAX_PATH) != nullptr) DolphinPath = TStrToUTF8(Dolphin_exe_Clean_Path); else DolphinPath = TStrToUTF8(Dolphin_exe_Path); DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); #else char Dolphin_exe_Path[PATH_MAX]; ssize_t len = ::readlink("/proc/self/exe", Dolphin_exe_Path, sizeof(Dolphin_exe_Path)); if (len == -1 || len == sizeof(Dolphin_exe_Path)) { len = 0; } Dolphin_exe_Path[len] = '\0'; DolphinPath = Dolphin_exe_Path; DolphinPath = DolphinPath.substr(0, DolphinPath.rfind('/')); #endif } return DolphinPath; }
std::string CreateTempDir() { #ifdef _WIN32 TCHAR temp[MAX_PATH]; if (!GetTempPath(MAX_PATH, temp)) return ""; GUID guid; CoCreateGuid(&guid); TCHAR tguid[40]; StringFromGUID2(guid, tguid, 39); tguid[39] = 0; std::string dir = TStrToUTF8(temp) + "/" + TStrToUTF8(tguid); if (!CreateDir(dir)) return ""; dir = ReplaceAll(dir, "\\", DIR_SEP); return dir; #else const char* base = getenv("TMPDIR") ?: "/tmp"; std::string path = std::string(base) + "/DolphinWii.XXXXXX"; if (!mkdtemp(&path[0])) return ""; return path; #endif }
std::string GetExePath() { static std::string dolphin_path; if (dolphin_path.empty()) { #ifdef _WIN32 TCHAR dolphin_exe_path[2048]; TCHAR dolphin_exe_expanded_path[MAX_PATH]; GetModuleFileName(nullptr, dolphin_exe_path, ARRAYSIZE(dolphin_exe_path)); if (_tfullpath(dolphin_exe_expanded_path, dolphin_exe_path, ARRAYSIZE(dolphin_exe_expanded_path)) != nullptr) dolphin_path = TStrToUTF8(dolphin_exe_expanded_path); else dolphin_path = TStrToUTF8(dolphin_exe_path); #elif defined(__APPLE__) dolphin_path = GetBundleDirectory(); dolphin_path = dolphin_path.substr(0, dolphin_path.find_last_of("Dolphin.app/Contents/MacOS")); #else char dolphin_exe_path[PATH_MAX]; ssize_t len = ::readlink("/proc/self/exe", dolphin_exe_path, sizeof(dolphin_exe_path)); if (len == -1 || len == sizeof(dolphin_exe_path)) { len = 0; } dolphin_exe_path[len] = '\0'; dolphin_path = dolphin_exe_path; #endif } return dolphin_path; }
void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) { TCHAR symInfo[BUFFERSIZE] = _T("?"); TCHAR srcInfo[BUFFERSIZE] = _T("?"); GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n"); }
// Create directory and copy contents (does not overwrite existing files) void CopyDir(const std::string& source_path, const std::string& dest_path, bool destructive) { if (source_path == dest_path) return; if (!Exists(source_path)) return; if (!Exists(dest_path)) File::CreateFullPath(dest_path); #ifdef _WIN32 WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(source_path + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return; } do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else DIR* dirp = opendir(source_path.c_str()); if (!dirp) return; while (dirent* result = readdir(dirp)) { const std::string virtualName(result->d_name); #endif // check for "." and ".." if (virtualName == "." || virtualName == "..") continue; std::string source = source_path + DIR_SEP + virtualName; std::string dest = dest_path + DIR_SEP + virtualName; if (IsDirectory(source)) { if (!Exists(dest)) File::CreateFullPath(dest + DIR_SEP); CopyDir(source, dest, destructive); } else if (!destructive && !Exists(dest)) { Copy(source, dest); } else if (destructive) { Rename(source, dest); } #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif }
// Connect to a Wiimote with a known device path. bool WiimoteWindows::ConnectInternal() { if (IsConnected()) return true; if (!IsNewWiimote(UTF16ToUTF8(m_devicepath))) return false; auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; m_dev_handle = CreateFile(m_devicepath.c_str(), GENERIC_READ | GENERIC_WRITE, open_flags, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (m_dev_handle == INVALID_HANDLE_VALUE) { m_dev_handle = nullptr; return false; } #if 0 TCHAR name[128] = {}; pHidD_GetProductString(dev_handle, name, 128); //ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str()); if (!IsValidBluetoothName(TStrToUTF8(name))) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif #if 0 HIDD_ATTRIBUTES attr; attr.Size = sizeof(attr); if (!pHidD_GetAttributes(dev_handle, &attr)) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif // TODO: thread isn't started here now, do this elsewhere // This isn't as drastic as it sounds, since the process in which the threads // reside is normal priority. Needed for keeping audio reports at a decent rate /* if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) { ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority"); } */ return true; }
std::string& GetExeDirectory() { static std::string DolphinPath; if (DolphinPath.empty()) { TCHAR Dolphin_exe_Path[2048]; GetModuleFileName(NULL, Dolphin_exe_Path, 2048); DolphinPath = TStrToUTF8(Dolphin_exe_Path); DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); } return DolphinPath; }
// Create directory and copy contents (does not overwrite existing files) void CopyDir(const std::string &source_path, const std::string &dest_path) { if (source_path == dest_path) return; if (!File::Exists(source_path)) return; if (!File::Exists(dest_path)) File::CreateFullPath(dest_path); #ifdef _WIN32 WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(source_path + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return; } do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(source_path.c_str()); if (!dirp) return; while (!readdir_r(dirp, &dirent, &result) && result) { const std::string virtualName(result->d_name); #endif // check for "." and ".." if (virtualName == "." || virtualName == "..") continue; std::string source, dest; source = source_path + virtualName; dest = dest_path + virtualName; if (IsDirectory(source)) { source += '/'; dest += '/'; if (!File::Exists(dest)) File::CreateFullPath(dest); CopyDir(source, dest); } else if (!File::Exists(dest)) File::Copy(source, dest); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif }
std::string GetTempFilenameForAtomicWrite(const std::string &path) { std::string abs = path; #ifdef _WIN32 TCHAR absbuf[MAX_PATH]; if (_tfullpath(absbuf, UTF8ToTStr(path).c_str(), MAX_PATH) != nullptr) abs = TStrToUTF8(absbuf); #else char absbuf[PATH_MAX]; if (realpath(path.c_str(), absbuf) != nullptr) abs = absbuf; #endif return abs + ".xxx"; }
// Returns a vector with the device names std::vector<std::string> cdio_get_devices() { std::vector<std::string> drives; const DWORD buffsize = GetLogicalDriveStrings(0, nullptr); std::vector<TCHAR> buff(buffsize); if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1) { auto drive = buff.data(); while (*drive) { if (is_cdrom(drive)) { std::string str(TStrToUTF8(drive)); str.pop_back(); // we don't want the final backslash drives.push_back(std::move(str)); } // advance to next drive while (*drive++) {} } } return drives; }
// Deletes the given directory and anything under it. Returns true on success. bool DeleteDirRecursively(const std::string &directory) { INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory.c_str()); #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return false; } // windows loop do { const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); if (!dirp) return false; // non windows loop while (!readdir_r(dirp, &dirent, &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; std::string newPath = directory + DIR_SEP_CHR + virtualName; if (IsDirectory(newPath)) { if (!DeleteDirRecursively(newPath)) { #ifndef _WIN32 closedir(dirp); #endif return false; } } else { if (!File::Delete(newPath)) { #ifndef _WIN32 closedir(dirp); #endif return false; } } #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif File::DeleteDir(directory); return true; }
// Scans the directory tree gets, starting from _Directory and adds the // results into parentEntry. Returns the number of files+directories found u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) { INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str()); // How many files + directories we found u32 foundEntries = 0; #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return foundEntries; } // windows loop do { FSTEntry entry; const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); if (!dirp) return 0; // non windows loop while (!readdir_r(dirp, &dirent, &result) && result) { FSTEntry entry; 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; entry.virtualName = virtualName; entry.physicalName = directory; entry.physicalName += DIR_SEP + entry.virtualName; if (IsDirectory(entry.physicalName.c_str())) { entry.isDirectory = true; // is a directory, lets go inside entry.size = ScanDirectoryTree(entry.physicalName, entry); foundEntries += (u32)entry.size; } else { // is a file entry.isDirectory = false; entry.size = GetSize(entry.physicalName.c_str()); } ++foundEntries; // Push into the tree parentEntry.children.push_back(entry); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif // Return number of entries found. return foundEntries; }
void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath) { std::string GCMSearchPath; BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); #ifdef _WIN32 WIN32_FIND_DATA findData; HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData); if (FindFirst != INVALID_HANDLE_VALUE) { bool bkeepLooping = true; while (bkeepLooping) { if (findData.cFileName[0] != '.') { std::string strFilename; BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName)); m_FileNames.push_back(strFilename); } bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false; } } FindClose(FindFirst); #else // TODO: super lame/broken auto end_match(_searchString); // assuming we have a "*.blah"-like pattern if (!end_match.empty() && end_match[0] == '*') end_match.erase(0, 1); // ugly if (end_match == ".*") end_match.clear(); DIR* dir = opendir(_strPath.c_str()); if (!dir) return; while (auto const dp = readdir(dir)) { std::string found(dp->d_name); if ((found != ".") && (found != "..") && (found.size() >= end_match.size()) && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin())) { std::string full_name; if (_strPath.c_str()[_strPath.size() - 1] == DIR_SEP_CHR) full_name = _strPath + found; else full_name = _strPath + DIR_SEP + found; m_FileNames.push_back(full_name); } } closedir(dir); #endif }
void SetUserDirectory(const std::string& custom_path) { if (!custom_path.empty()) { File::CreateFullPath(custom_path + DIR_SEP); File::SetUserPath(D_USER_IDX, custom_path + DIR_SEP); return; } std::string user_path = ""; #ifdef _WIN32 // Detect where the User directory is. There are five different cases (on top of the // command line flag, which overrides all this): // 1. GetExeDirectory()\portable.txt exists // -> Use GetExeDirectory()\User // 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true // -> Use GetExeDirectory()\User // 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists // -> Use this as the user directory path // 4. My Documents exists // -> Use My Documents\Dolphin Emulator as the User directory path // 5. Default // -> Use GetExeDirectory()\User // Check our registry keys HKEY hkey; DWORD local = 0; TCHAR configPath[MAX_PATH] = {0}; if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { DWORD size = 4; if (RegQueryValueEx(hkey, TEXT("LocalUserConfig"), nullptr, nullptr, reinterpret_cast<LPBYTE>(&local), &size) != ERROR_SUCCESS) local = 0; size = MAX_PATH; if (RegQueryValueEx(hkey, TEXT("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS) configPath[0] = 0; RegCloseKey(hkey); } local = local || File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt"); // Get Program Files path in case we need it. TCHAR my_documents[MAX_PATH]; bool my_documents_found = SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); if (local) // Case 1-2 user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; else if (configPath[0]) // Case 3 user_path = TStrToUTF8(configPath); else if (my_documents_found) // Case 4 user_path = TStrToUTF8(my_documents) + DIR_SEP "Dolphin Emulator" DIR_SEP; else // Case 5 user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; // Prettify the path: it will be displayed in some places, we don't want a mix of \ and /. user_path = ReplaceAll(user_path, "\\", DIR_SEP); // Make sure it ends in DIR_SEP. if (*user_path.rbegin() != DIR_SEP_CHR) user_path += DIR_SEP; #else if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; } else { const char* home = getenv("HOME"); if (!home) home = getenv("PWD"); if (!home) home = ""; std::string home_path = std::string(home) + DIR_SEP; #if defined(__APPLE__) || defined(ANDROID) user_path = home_path + DOLPHIN_DATA_DIR DIR_SEP; #else // We are on a non-Apple and non-Android POSIX system, let's respect XDG basedir. // The only case we don't is when there is an existing ~/.dolphin-emu directory. // See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html user_path = home_path + "." DOLPHIN_DATA_DIR DIR_SEP; if (!File::Exists(user_path)) { const char* data_home = getenv("XDG_DATA_HOME"); std::string data_path = std::string(data_home && data_home[0] == '/' ? data_home : (home_path + ".local" DIR_SEP "share")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; const char* config_home = getenv("XDG_CONFIG_HOME"); std::string config_path = std::string(config_home && config_home[0] == '/' ? config_home : (home_path + ".config")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; const char* cache_home = getenv("XDG_CACHE_HOME"); std::string cache_path = std::string(cache_home && cache_home[0] == '/' ? cache_home : (home_path + ".cache")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; File::SetUserPath(D_USER_IDX, data_path); File::SetUserPath(D_CONFIG_IDX, config_path); File::SetUserPath(D_CACHE_IDX, cache_path); return; } #endif } #endif File::SetUserPath(D_USER_IDX, user_path); }
// Recursive or non-recursive list of files and directories under directory. FSTEntry ScanDirectoryTree(const std::string& directory, bool recursive) { INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory.c_str()); FSTEntry parent_entry; parent_entry.physicalName = directory; parent_entry.isDirectory = true; parent_entry.size = 0; #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return parent_entry; } // Windows loop do { const std::string virtual_name(TStrToUTF8(ffd.cFileName)); #else DIR* dirp = opendir(directory.c_str()); if (!dirp) return parent_entry; // non Windows loop while (dirent* result = readdir(dirp)) { const std::string virtual_name(result->d_name); #endif if (virtual_name == "." || virtual_name == "..") continue; auto physical_name = directory + DIR_SEP + virtual_name; FSTEntry entry; const FileInfo file_info(physical_name); entry.isDirectory = file_info.IsDirectory(); if (entry.isDirectory) { if (recursive) entry = ScanDirectoryTree(physical_name, true); else entry.size = 0; parent_entry.size += entry.size; } else { entry.size = file_info.GetSize(); } entry.virtualName = virtual_name; entry.physicalName = physical_name; ++parent_entry.size; // Push into the tree parent_entry.children.push_back(entry); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else } closedir(dirp); #endif return parent_entry; }
// Returns a string with a Dolphin data dir or file in the user's home // directory. To be used in "multi-user" mode (that is, installed). const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath) { static std::string paths[NUM_PATH_INDICES]; // Set up all paths and files on the first run if (paths[D_USER_IDX].empty()) { #ifdef _WIN32 // Detect where the User directory is. There are five different cases (on top of the // command line flag, which overrides all this): // 1. GetExeDirectory()\portable.txt exists // -> Use GetExeDirectory()\User // 2. HKCU\Software\Dolphin Emulator\LocalUserConfig exists and is true // -> Use GetExeDirectory()\User // 3. HKCU\Software\Dolphin Emulator\UserConfigPath exists // -> Use this as the user directory path // 4. My Documents exists // -> Use My Documents\Dolphin Emulator as the User directory path // 5. Default // -> Use GetExeDirectory()\User // Check our registry keys HKEY hkey; DWORD local = 0; TCHAR configPath[MAX_PATH] = {0}; if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { DWORD size = 4; if (RegQueryValueEx(hkey, TEXT("LocalUserConfig"), nullptr, nullptr, reinterpret_cast<LPBYTE>(&local), &size) != ERROR_SUCCESS) local = 0; size = MAX_PATH; if (RegQueryValueEx(hkey, TEXT("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS) configPath[0] = 0; RegCloseKey(hkey); } local = local || File::Exists(GetExeDirectory() + DIR_SEP "portable.txt"); // Get Program Files path in case we need it. TCHAR my_documents[MAX_PATH]; bool my_documents_found = SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); if (local) // Case 1-2 paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; else if (configPath[0]) // Case 3 paths[D_USER_IDX] = TStrToUTF8(configPath); else if (my_documents_found) // Case 4 paths[D_USER_IDX] = TStrToUTF8(my_documents) + DIR_SEP "Dolphin Emulator" DIR_SEP; else // Case 5 paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; // Prettify the path: it will be displayed in some places, we don't want a mix of \ and /. paths[D_USER_IDX] = ReplaceAll(paths[D_USER_IDX], "\\", DIR_SEP); // Make sure it ends in DIR_SEP. if (*paths[D_USER_IDX].rbegin() != DIR_SEP_CHR) paths[D_USER_IDX] += DIR_SEP; #else if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; else paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD") ? getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; #endif paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP; paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR; paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_GAMESETTINGS_IDX] = paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP; paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; paths[D_HIRESTEXTURES_IDX] = paths[D_USER_IDX] + HIRES_TEXTURES_DIR DIR_SEP; paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; paths[D_DUMPDSP_IDX] = paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP; paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; paths[D_MAILLOGS_IDX] = paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP; paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR DIR_SEP; paths[D_WIIWC24_IDX] = paths[D_WIIUSER_IDX] + WII_WC24CONF_DIR DIR_SEP; paths[D_THEMES_IDX] = paths[D_USER_IDX] + THEMES_DIR DIR_SEP; paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF; paths[F_RAMDUMP_IDX] = paths[D_DUMP_IDX] + RAM_DUMP; paths[F_ARAMDUMP_IDX] = paths[D_DUMP_IDX] + ARAM_DUMP; paths[F_FAKEVMEMDUMP_IDX] = paths[D_DUMP_IDX] + FAKEVMEM_DUMP; paths[F_GCSRAM_IDX] = paths[D_GCUSER_IDX] + GC_SRAM; } if (!newPath.empty()) { if (!File::IsDirectory(newPath)) { WARN_LOG(COMMON, "Invalid path specified %s", newPath.c_str()); return paths[DirIDX]; } else { paths[DirIDX] = newPath; } switch (DirIDX) { case D_WIIROOT_IDX: paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP; paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR + DIR_SEP; paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF; break; case D_USER_IDX: paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP; paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR; paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_GAMESETTINGS_IDX] = paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP; paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; paths[D_HIRESTEXTURES_IDX] = paths[D_USER_IDX] + HIRES_TEXTURES_DIR DIR_SEP; paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; paths[D_DUMPDSP_IDX] = paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP; paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; paths[D_MAILLOGS_IDX] = paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP; paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR DIR_SEP; paths[D_THEMES_IDX] = paths[D_USER_IDX] + THEMES_DIR DIR_SEP; paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF; paths[F_RAMDUMP_IDX] = paths[D_DUMP_IDX] + RAM_DUMP; paths[F_ARAMDUMP_IDX] = paths[D_DUMP_IDX] + ARAM_DUMP; paths[F_FAKEVMEMDUMP_IDX] = paths[D_DUMP_IDX] + FAKEVMEM_DUMP; paths[F_GCSRAM_IDX] = paths[D_GCUSER_IDX] + GC_SRAM; break; case D_CONFIG_IDX: paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; break; case D_GCUSER_IDX: paths[F_GCSRAM_IDX] = paths[D_GCUSER_IDX] + GC_SRAM; break; case D_DUMP_IDX: paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; paths[D_DUMPDSP_IDX] = paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP; paths[F_RAMDUMP_IDX] = paths[D_DUMP_IDX] + RAM_DUMP; paths[F_ARAMDUMP_IDX] = paths[D_DUMP_IDX] + ARAM_DUMP; paths[F_FAKEVMEMDUMP_IDX] = paths[D_DUMP_IDX] + FAKEVMEM_DUMP; break; case D_LOGS_IDX: paths[D_MAILLOGS_IDX] = paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP; paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; } paths[D_WIIUSER_IDX] = paths[D_WIIROOT_IDX] + DIR_SEP; paths[D_WIIWC24_IDX] = paths[D_WIIUSER_IDX] + WII_WC24CONF_DIR DIR_SEP; paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR + DIR_SEP; paths[F_WIISYSCONF_IDX] = paths[D_WIISYSCONF_IDX] + WII_SYSCONF; } return paths[DirIDX]; }
// Connect to a Wiimote with a known device path. bool WiimoteWindows::ConnectInternal() { if (IsConnected()) return false; #ifdef SHARE_WRITE_WIIMOTES std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock); if (g_connected_wiimotes.count(m_devicepath) != 0) return false; auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; #else // Having no FILE_SHARE_WRITE disallows us from connecting to the same Wiimote twice. // (And disallows using Wiimotes in use by other programs) // This is what "WiiYourself" does. // Apparently this doesn't work for everyone. It might be their fault. auto const open_flags = FILE_SHARE_READ; #endif m_dev_handle = CreateFile(m_devicepath.c_str(), GENERIC_READ | GENERIC_WRITE, open_flags, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (m_dev_handle == INVALID_HANDLE_VALUE) { m_dev_handle = 0; return false; } #if 0 TCHAR name[128] = {}; pHidD_GetProductString(dev_handle, name, 128); //ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str()); if (!IsValidBluetoothName(TStrToUTF8(name))) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif #if 0 HIDD_ATTRIBUTES attr; attr.Size = sizeof(attr); if (!pHidD_GetAttributes(dev_handle, &attr)) { CloseHandle(dev_handle); dev_handle = 0; return false; } #endif // TODO: thread isn't started here now, do this elsewhere // This isn't as drastic as it sounds, since the process in which the threads // reside is normal priority. Needed for keeping audio reports at a decent rate /* if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) { ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority"); } */ #ifdef SHARE_WRITE_WIIMOTES g_connected_wiimotes.insert(m_devicepath); #endif return true; }