diff --git a/Source/Core/Common/Src/DriveUtil.cpp b/Source/Core/Common/Src/DriveUtil.cpp index f5e18904b5..e76b646c31 100644 --- a/Source/Core/Common/Src/DriveUtil.cpp +++ b/Source/Core/Common/Src/DriveUtil.cpp @@ -16,33 +16,31 @@ // http://code.google.com/p/dolphin-emu/ #include - -#include "Common.h" #include "DriveUtil.h" #ifdef _WIN32 #include #include +#elif defined(__GNUC__) // TODO: replace these with real linux / os x functinos +#define GetLogicalDriveStrings(x, y) (int)memcpy(y,"/dev/cdrom\0/dev/cdrom1\0/dev/cdrom2\0/dev/cdrom3\0/dev/cdrom4\0/dev/cdrom5\0/dev/cdrom6\0/dev/cdrom7\0/dev/cdrom8\0/dev/cdrom9\0\0\0", 121); +#else +#define GetLogicalDriveStrings(x, y) (int)memcpy(y,"/dev/disk2\0/dev/disk3\0/dev/disk4\0/dev/disk5\0/dev/disk6\0/dev/disk7\0/dev/disk8\0/dev/disk9\0/dev/disk10\0/dev/disk11\0\0\0",114); #endif void GetAllRemovableDrives(std::vector *drives) { drives->clear(); -#ifdef _WIN32 char drives_string[1024]; int max_drive_pos = GetLogicalDriveStrings(1024, drives_string); + char *p = drives_string; // GetLogicalDriveStrings returns the drives as a a series of null-terminated strings // laid out right after each other in RAM, with a double null at the end. while (*p) { - if (GetDriveType(p) == DRIVE_CDROM) // CD_ROM also applies to DVD. Noone has a plain CDROM without DVD anymore so we should be fine. + if (File::IsDisk(p)) { - drives->push_back(std::string(p).substr(0, 2)); + drives->push_back(std::string(p)); } p += strlen(p) + 1; } -#else - // TODO - // stat("/media/cdrom") or whatever etc etc -#endif } diff --git a/Source/Core/Common/Src/DriveUtil.h b/Source/Core/Common/Src/DriveUtil.h index 675484f247..54d946355d 100644 --- a/Source/Core/Common/Src/DriveUtil.h +++ b/Source/Core/Common/Src/DriveUtil.h @@ -20,6 +20,8 @@ #include #include +#include "Common.h" +#include "FileUtil.h" // Tools to enumerate drives (HDD, DVD, CD) in a platform-independent manner. diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index e371ab78e5..07ffc9d1f3 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #endif #include @@ -72,11 +75,33 @@ bool Exists(const char *filename) bool IsDisk(const char *filename) { #ifdef _WIN32 - std::string copy = filename; - if (copy.size() < 4 && copy.c_str()[1] == ':') + if (GetDriveType(filename) == DRIVE_CDROM) // CD_ROM also applies to DVD. Noone has a plain CDROM without DVD anymore so we should be fine. return true; #else - // TODO: add linux \ osx + struct stat statInfo; + if((stat(filename, &statInfo) > -1) && (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))) + { + int fileHandle; + // try to open the device + fileHandle = open(filename, O_RDONLY | O_NONBLOCK, 0); + if (fileHandle >= 0) + { + cdrom_subchnl cdChannelInfo; + cdChannelInfo.cdsc_format = CDROM_MSF; + + if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) || + (errno == EIO) || (errno == ENOENT) || + (errno == EINVAL) + #ifdef __GNUC__ + || (errno == ENOMEDIUM) + #endif + ) + { + return true; + } + close(fileHandle); + } + } #endif return false; } diff --git a/Source/Core/Common/Src/SConscript b/Source/Core/Common/Src/SConscript index 24b6f68a14..491b47943d 100644 --- a/Source/Core/Common/Src/SConscript +++ b/Source/Core/Common/Src/SConscript @@ -9,6 +9,7 @@ files = [ "ConsoleWindow.cpp", "ColorUtil.cpp", "CPUDetect.cpp", + "DriveUtil.cpp", "DynamicLibrary.cpp", "Hash.cpp", "IniFile.cpp", diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp index 1ebef3af55..7e798e337f 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.cpp +++ b/Source/Core/DiscIO/Src/DriveBlob.cpp @@ -30,14 +30,10 @@ namespace DiscIO hDisc = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); - if (hDisc == INVALID_HANDLE_VALUE) - { - PanicAlert("Load from DVD backup failed"); - } - else + if (hDisc != INVALID_HANDLE_VALUE) { - SectorReader::SetSectorSize(2048); - #ifdef _LOCKDRIVE + + #ifdef _LOCKDRIVE // Do we want to lock the drive? // Lock the compact disc in the CD-ROM drive to prevent accidental // removal while reading from it. pmrLockCDROM.PreventMediaRemoval = TRUE; @@ -45,14 +41,17 @@ namespace DiscIO &pmrLockCDROM, sizeof(pmrLockCDROM), NULL, 0, &dwNotUsed, NULL); #endif - } #else file_ = fopen(drive, "rb"); - if (!file_) - PanicAlert("Load from DVD backup failed"); - else - SetSectorSize(2048); + if (file_) + { #endif + SectorReader::SetSectorSize(2048); + } + else + { + PanicAlert("Load from DVD backup failed or no disc in drive %s",drive); + } } // DriveReader::DriveReader DriveReader::~DriveReader() @@ -65,7 +64,10 @@ namespace DiscIO &pmrLockCDROM, sizeof(pmrLockCDROM), NULL, 0, &dwNotUsed, NULL); #endif - CloseHandle(hDisc); + if (hDisc != INVALID_HANDLE_VALUE) + { + CloseHandle(hDisc); + } #else fclose(file_); #endif @@ -104,10 +106,14 @@ namespace DiscIO LONG off_high = (LONG)(offset >> 32); SetFilePointer(hDisc, off_low, &off_high, FILE_BEGIN); if (!ReadFile(hDisc, out_ptr, (DWORD)(m_blocksize * num_blocks), (LPDWORD)&NotUsed, NULL)) + { PanicAlert("DRE"); + return false; + } #else fseek(file_, m_blocksize*block_num, SEEK_SET); - fread(out_ptr, 1, m_blocksize * num_blocks, file_); + if(fread(out_ptr, 1, m_blocksize * num_blocks, file_) != m_blocksize * num_blocks) + return false; #endif return true; } diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 93cfb97ac6..1d08bc2812 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -99,15 +99,14 @@ void CFrame::CreateMenu() // file menu wxMenu* fileMenu = new wxMenu; m_pMenuItemOpen = fileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl+O")); -// not tested on linux/os x -// works ok on a virtual drive with GC Games, Wii games do not load -// backups take about 60-90 seconds to load from real cd drive -#ifdef _WIN32 + +#if defined(_WIN32) || defined(__GNUC__) // not tested on linux/os x wxMenu *externalDrive = new wxMenu; fileMenu->AppendSubMenu(externalDrive, _T("&Boot from DVD Drive...")); GetAllRemovableDrives(&drives); - for (int i = 0; i < drives.size() && i < 24; i++) { - externalDrive->Append(IDM_DRIVE1 + i, wxString::Format(_T("%s"), drives.at(i).c_str())); + for (int i = 0; i < drives.size() && i < 24; i++) + { + externalDrive->Append(IDM_DRIVE1 + i, wxString::FromAscii(drives.at(i).c_str())); } #endif fileMenu->AppendSeparator(); @@ -490,6 +489,10 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) void CFrame::OnBootDrive(wxCommandEvent& event) { +#ifdef __GNUC__ + if (!PanicYesNo("This function has not been tested on Linux, continue?\nPlease report whether it works or not")) + return; +#endif BootManager::BootCore(drives.at(event.GetId()-IDM_DRIVE1).c_str()); }