// Dolwin file utilities #include "pch.h" #include namespace UI { bool FileExists(const TCHAR* filename) { FILE* f = nullptr; _tfopen_s(&f, filename, _T("rb")); if (f == NULL) return false; fclose(f); return true; } // Get file size size_t FileSize(const TCHAR * filename) { FILE* f = nullptr; _tfopen_s (&f, filename, _T("rb")); if (f == NULL) return 0; fseek(f, 0, SEEK_END); size_t size = ftell(f); fclose(f); return size; } // Load data from file void* FileLoad(const TCHAR * filename, size_t * size) { FILE* f; uint8_t* buffer; size_t filesize; if (size) *size = 0; f = nullptr; _tfopen_s(&f, filename, _T("rb")); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); filesize = ftell(f); fseek(f, 0, SEEK_SET); buffer = (uint8_t *)malloc(filesize + 1); if (buffer == NULL) { fclose(f); return NULL; } fread(buffer, filesize, 1, f); fclose(f); buffer[filesize] = 0; if (size) *size = filesize; return buffer; } // Load data from file void* FileLoad(const char* filename, size_t* size) { FILE* f; uint8_t* buffer; size_t filesize; if (size) *size = 0; f = nullptr; fopen_s(&f, filename, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); filesize = ftell(f); fseek(f, 0, SEEK_SET); buffer = (uint8_t*)malloc(filesize + 1); if (buffer == NULL) { fclose(f); return NULL; } fread(buffer, filesize, 1, f); fclose(f); buffer[filesize] = 0; if (size) *size = filesize; return buffer; } // Save data in file bool FileSave(const TCHAR * filename, void* data, size_t size) { FILE* f = nullptr; _tfopen_s (&f, filename, _T("wb")); if (f == NULL) return FALSE; fwrite(data, size, 1, f); fclose(f); return TRUE; } bool FileSave(const char* filename, void* data, size_t size) { FILE* f = nullptr; fopen_s(&f, filename, "wb"); if (f == NULL) return FALSE; fwrite(data, size, 1, f); fclose(f); return TRUE; } // Open file/directory dialog TCHAR * FileOpen(HWND hwnd, FileType type) { static TCHAR tempBuf[0x1000] = { 0 }; OPENFILENAME ofn; TCHAR szFileName[1024]; TCHAR szFileTitle[1024]; TCHAR lastDir[1024], prevDir[1024]; BOOL result; GetCurrentDirectory(sizeof(prevDir), prevDir); switch (type) { case FileType::All: _tcscpy_s(lastDir, _countof(lastDir) - 1, GetConfigString(USER_LASTDIR_ALL, USER_UI)); break; case FileType::Dvd: _tcscpy_s(lastDir, _countof(lastDir) - 1, GetConfigString(USER_LASTDIR_DVD, USER_UI)); break; case FileType::Map: _tcscpy_s(lastDir, _countof(lastDir) - 1, GetConfigString(USER_LASTDIR_MAP, USER_UI)); break; case FileType::Patch: _tcscpy_s(lastDir, _countof(lastDir) - 1, GetConfigString(USER_LASTDIR_PATCH, USER_UI)); break; } memset(szFileName, 0, sizeof(szFileName)); memset(szFileTitle, 0, sizeof(szFileTitle)); if (type == FileType::Directory) { BROWSEINFO bi; LPTSTR lpBuffer = NULL; LPITEMIDLIST pidlRoot = NULL; // PIDL for root folder LPITEMIDLIST pidlBrowse = NULL; // PIDL selected by user LPMALLOC g_pMalloc; // Get the shell's allocator. if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) return NULL; // Allocate a buffer to receive browse information. lpBuffer = (LPTSTR)g_pMalloc->Alloc(MAX_PATH); if (lpBuffer == NULL) return NULL; // Get the PIDL for the root folder. if (!SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_DRIVES, &pidlRoot))) { g_pMalloc->Free(lpBuffer); return NULL; } // Fill in the BROWSEINFO structure. bi.hwndOwner = hwnd; bi.pidlRoot = pidlRoot; bi.pszDisplayName = lpBuffer; bi.lpszTitle = _T("Choose Directory"); bi.ulFlags = 0; bi.lpfn = NULL; bi.lParam = 0; // Browse for a folder and return its PIDL. pidlBrowse = SHBrowseForFolder(&bi); result = (pidlBrowse != NULL); if (result) { SHGetPathFromIDList(pidlBrowse, lpBuffer); _tcscpy_s(szFileName, _countof(szFileName) - 1, lpBuffer); // Free the PIDL returned by SHBrowseForFolder. g_pMalloc->Free(pidlBrowse); } // Clean up. if (pidlRoot) g_pMalloc->Free(pidlRoot); if (lpBuffer) g_pMalloc->Free(lpBuffer); // Release the shell's allocator. g_pMalloc->Release(); } else { ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; switch (type) { case FileType::All: ofn.lpstrFilter = _T("All Supported Files (*.dol, *.elf, *.bin, *.gcm, *.iso)\0*.dol;*.elf;*.bin;*.gcm;*.iso\0") _T("GameCube Executable Files (*.dol, *.elf)\0*.dol;*.elf\0") _T("Binary Files (*.bin)\0*.bin\0") _T("GameCube DVD Images (*.gcm, *.iso)\0*.gcm;*.iso\0") _T("All Files (*.*)\0*.*\0"); break; case FileType::Dvd: ofn.lpstrFilter = _T("GameCube DVD Images (*.gcm, *.iso)\0*.gcm;*.iso\0") _T("All Files (*.*)\0*.*\0"); break; case FileType::Map: ofn.lpstrFilter = _T("Symbolic information files (*.map)\0*.map\0") _T("All Files (*.*)\0*.*\0"); break; case FileType::Patch: ofn.lpstrFilter = _T("Patch files (*.patch)\0*.patch\0") _T("All Files (*.*)\0*.*\0"); break; } ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = szFileName; ofn.nMaxFile = sizeof(szFileName); ofn.lpstrInitialDir = lastDir; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrTitle = _T("Open File\0"); ofn.lpstrDefExt = _T(""); ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; result = GetOpenFileName(&ofn); } if (result) { _tcscpy_s(tempBuf, _countof(tempBuf) - 1, szFileName); // save last directory _tcscpy_s(lastDir, _countof(lastDir) - 1, tempBuf); int i = (int)_tcslen(lastDir) - 1; while (lastDir[i] != _T('\\')) i--; lastDir[i + 1] = _T('\0'); switch (type) { case FileType::All: SetConfigString(USER_LASTDIR_ALL, lastDir, USER_UI); break; case FileType::Dvd: SetConfigString(USER_LASTDIR_DVD, lastDir, USER_UI); break; case FileType::Map: SetConfigString(USER_LASTDIR_MAP, lastDir, USER_UI); break; case FileType::Patch: SetConfigString(USER_LASTDIR_PATCH, lastDir, USER_UI); break; } SetCurrentDirectory(prevDir); return tempBuf; } else { SetCurrentDirectory(prevDir); return NULL; } } // make path to file shorter for "lvl" levels. TCHAR * FileShortName(const TCHAR * filename, int lvl) { static TCHAR tempBuf[1024] = { 0 }; int c = 0; size_t i = 0; TCHAR * ptr = (TCHAR *)filename; tempBuf[0] = ptr[0]; tempBuf[1] = ptr[1]; tempBuf[2] = ptr[2]; ptr += 3; for (i = _tcslen(ptr) - 1; i; i--) { if (ptr[i] == _T('\\')) c++; if (c == lvl) break; } if (c == lvl) { _stprintf_s(&tempBuf[3], _countof(tempBuf) - 3, _T("...%s"), &ptr[i]); } else return ptr - 3; return tempBuf; } // nice value of KB, MB or GB, for output TCHAR * FileSmartSize(size_t size) { static TCHAR tempBuf[1024] = { 0 }; if (size < 1024) { _stprintf_s(tempBuf, sizeof(tempBuf), _T("%zi byte"), size); } else if (size < 1024 * 1024) { _stprintf_s(tempBuf, sizeof(tempBuf), _T("%zi KB"), size / 1024); } else if (size < 1024 * 1024 * 1024) { _stprintf_s(tempBuf, sizeof(tempBuf), _T("%zi MB"), size / 1024 / 1024); } else _stprintf_s(tempBuf, sizeof(tempBuf), _T("%1.1f GB"), (float)size / 1024 / 1024 / 1024); return tempBuf; } char* FileSmartSizeA(size_t size) { static char tempBuf[1024] = { 0 }; if (size < 1024) { sprintf_s(tempBuf, sizeof(tempBuf), "%zi byte", size); } else if (size < 1024 * 1024) { sprintf_s(tempBuf, sizeof(tempBuf), "%zi KB", size / 1024); } else if (size < 1024 * 1024 * 1024) { sprintf_s(tempBuf, sizeof(tempBuf), "%zi MB", size / 1024 / 1024); } else sprintf_s(tempBuf, sizeof(tempBuf), "%1.1f GB", (float)size / 1024 / 1024 / 1024); return tempBuf; } void* FileLoad(std::wstring filename, size_t& size) { FILE* f; uint8_t* buffer; size_t filesize; size = 0; f = nullptr; _wfopen_s(&f, filename.c_str(), L"rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); filesize = ftell(f); fseek(f, 0, SEEK_SET); buffer = new uint8_t[filesize + 1]; if (buffer == NULL) { fclose(f); return NULL; } fread(buffer, filesize, 1, f); fclose(f); buffer[filesize] = 0; size = filesize; return buffer; } bool FileSave(std::wstring filename, void* data, size_t size) { FILE* f = nullptr; _wfopen_s(&f, filename.c_str(), L"wb"); if (f == NULL) return FALSE; fwrite(data, size, 1, f); fclose(f); return TRUE; } }