diff options
| author | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
|---|---|---|
| committer | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
| commit | 7dfced21a2e5aac7195e0e1ad76468e30306766b (patch) | |
| tree | bd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/DiscIO/DriveBlob.cpp | |
| parent | c25be031fc1031d795157d8344b87b7841145197 (diff) | |
| parent | 7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff) | |
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/DiscIO/DriveBlob.cpp')
| -rw-r--r-- | Source/Core/DiscIO/DriveBlob.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/Source/Core/DiscIO/DriveBlob.cpp b/Source/Core/DiscIO/DriveBlob.cpp new file mode 100644 index 0000000000..3f0b073945 --- /dev/null +++ b/Source/Core/DiscIO/DriveBlob.cpp @@ -0,0 +1,138 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <cstdio> +#include <cstring> +#include <string> + +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "DiscIO/Blob.h" +#include "DiscIO/DriveBlob.h" + +#ifdef _WIN32 +#include "Common/StringUtil.h" +#endif + +namespace DiscIO +{ + +DriveReader::DriveReader(const std::string& drive) +{ +#ifdef _WIN32 + SectorReader::SetSectorSize(2048); + auto const path = UTF8ToTStr(std::string("\\\\.\\") + drive); + m_disc_handle = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr); + if (m_disc_handle != INVALID_HANDLE_VALUE) + { + // Do a test read to make sure everything is OK, since it seems you can get + // handles to empty drives. + DWORD not_used; + u8 *buffer = new u8[m_blocksize]; + if (!ReadFile(m_disc_handle, buffer, m_blocksize, (LPDWORD)¬_used, nullptr)) + { + delete [] buffer; + // OK, something is wrong. + CloseHandle(m_disc_handle); + m_disc_handle = INVALID_HANDLE_VALUE; + return; + } + delete [] buffer; + + #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. + m_lock_cdrom.PreventMediaRemoval = TRUE; + DeviceIoControl(m_disc_handle, IOCTL_CDROM_MEDIA_REMOVAL, + &m_lock_cdrom, sizeof(m_lock_cdrom), nullptr, + 0, &dwNotUsed, nullptr); + #endif +#else + SectorReader::SetSectorSize(2048); + m_file.Open(drive, "rb"); + if (m_file) + { +#endif + } + else + { + NOTICE_LOG(DISCIO, "Load from DVD backup failed or no disc in drive %s", drive.c_str()); + } +} + +DriveReader::~DriveReader() +{ +#ifdef _WIN32 +#ifdef _LOCKDRIVE // Do we want to lock the drive? + // Unlock the disc in the CD-ROM drive. + m_lock_cdrom.PreventMediaRemoval = FALSE; + DeviceIoControl (m_disc_handle, IOCTL_CDROM_MEDIA_REMOVAL, + &m_lock_cdrom, sizeof(m_lock_cdrom), nullptr, + 0, &dwNotUsed, nullptr); +#endif + if (m_disc_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(m_disc_handle); + m_disc_handle = INVALID_HANDLE_VALUE; + } +#else + m_file.Close(); +#endif +} + +DriveReader* DriveReader::Create(const std::string& drive) +{ + DriveReader* reader = new DriveReader(drive); + + if (!reader->IsOK()) + { + delete reader; + return nullptr; + } + + return reader; +} + +void DriveReader::GetBlock(u64 block_num, u8* out_ptr) +{ + u8* const lpSector = new u8[m_blocksize]; +#ifdef _WIN32 + u32 NotUsed; + u64 offset = m_blocksize * block_num; + LONG off_low = (LONG)offset & 0xFFFFFFFF; + LONG off_high = (LONG)(offset >> 32); + SetFilePointer(m_disc_handle, off_low, &off_high, FILE_BEGIN); + if (!ReadFile(m_disc_handle, lpSector, m_blocksize, (LPDWORD)&NotUsed, nullptr)) + PanicAlertT("Disc Read Error"); +#else + m_file.Seek(m_blocksize * block_num, SEEK_SET); + m_file.ReadBytes(lpSector, m_blocksize); +#endif + memcpy(out_ptr, lpSector, m_blocksize); + delete[] lpSector; +} + +bool DriveReader::ReadMultipleAlignedBlocks(u64 block_num, u64 num_blocks, u8* out_ptr) +{ +#ifdef _WIN32 + u32 NotUsed; + u64 offset = m_blocksize * block_num; + LONG off_low = (LONG)offset & 0xFFFFFFFF; + LONG off_high = (LONG)(offset >> 32); + SetFilePointer(m_disc_handle, off_low, &off_high, FILE_BEGIN); + if (!ReadFile(m_disc_handle, out_ptr, (DWORD)(m_blocksize * num_blocks), (LPDWORD)&NotUsed, nullptr)) + { + PanicAlertT("Disc Read Error"); + return false; + } +#else + fseeko(m_file.GetHandle(), (m_blocksize * block_num), SEEK_SET); + if (fread(out_ptr, 1, (m_blocksize * num_blocks), m_file.GetHandle()) != (m_blocksize * num_blocks)) + return false; +#endif + return true; +} + +} // namespace |
