Remove Boot from DVD Backup

This should be a fairly easy merge, assuming I didn’t mess anything up. TL:DR no one uses it and it’s not great.

Boot from DVD Backup is an ancient feature with origins in the Megacommit. Back then, GameCube and Wii games were quite large relative to drives of the time. For example, in 2008, the most common hard drive sizes were 320GB and 512GB. On the 320GB drive I personally had at the time, as little as 42 Wii ISOs could have filled it entirely! And that’s ignoring any other files one might want to put onto a drive. Backup DVDs allowed users to burn relatively cheap DVD media and store their GameCube and Wii dumps in a Dolphin accessible way that didn’t eat into their precious HDD space. It had compromises, even then, but in 2008… I mean honestly users probably wouldn’t even notice those compromises with how Dolphin barely even worked at all back then.

Obviously, today the storage space concerns are not as big of an issue. According to seagate the average hard drive it sells today is 8TB. For typical laptops purchased now, the -minimum- selection for storage is usually 1TB. You can even buy a name brand 4TB external hard drive for $100. GC and Wii ISOs are not as big as they once were, relatively anyway. Plus flash drives and SD cards are super cheap and way faster than disc drives ever were. For anyone that has limited drive space, removable flash media can fulfill this offloading role far better than backup DVD media ever could.

Also no one has DVD drives anymore. That’s kind of an important detail.

But to see if Booting from DVD Backup even still worked, I decided to give it a try. I have an ASUS BW-16D1HT, a badass Bluray XL reading and burning drive, connected to my Windows 11 Threadripper 5975WX machine. A super fast drive on a super fast machine is as good as it possibly can get for this feature. So I bought a spindle of DVD-Rs, burned a couple of discs and gave it a try. Surprisingly, it does still work. However, as expected, it introduces a lot of stuttering. Testing Prime 1 and Prime 3, in both games stuttering was introduced whenever the DVD Drive had to suddenly seek. Spikes of 50ms occurred constantly, but I observed 150ms and even over 1000ms stutters! The worst was a three second stutter, when loading Elysia in Prime 3. I could even hear the stutters - any time the drive suddenly made a harsh seeking noise, the game would have a hard stutter. It worked but, it has some serious compromises.

Boot from DVD Backup isn’t great, using removable flash media or external hard drives is a FAR better option for anyone with limited storage space today, and no one can even use this feature anymore because their computers don’t even have disc drives. It’s time for Boot from DVD Backup to go!

So I did my best on the cleanup but I’m bound to have left some bits. Especially in translation - I didn’t get any warnings or anything there that could help point me to where to clean that up. Please review!
This commit is contained in:
MayImilae 2023-01-16 18:32:43 -08:00
parent aacd66bd5b
commit dcc10cff11
8 changed files with 0 additions and 242 deletions

View File

@ -18,7 +18,6 @@
#include "DiscIO/CISOBlob.h"
#include "DiscIO/CompressedBlob.h"
#include "DiscIO/DirectoryBlob.h"
#include "DiscIO/DriveBlob.h"
#include "DiscIO/FileBlob.h"
#include "DiscIO/NFSBlob.h"
#include "DiscIO/TGCBlob.h"
@ -215,9 +214,6 @@ u32 SectorReader::ReadChunk(u8* buffer, u64 chunk_num)
std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
{
if (Common::IsCDROMDevice(filename))
return DriveReader::Create(filename);
File::IOFile file(filename, "rb");
u32 magic;
if (!file.ReadArray(&magic, 1))

View File

@ -13,8 +13,6 @@ add_library(discio
DiscScrubber.h
DiscUtils.cpp
DiscUtils.h
DriveBlob.cpp
DriveBlob.h
Enums.cpp
Enums.h
FileBlob.cpp

View File

@ -1,161 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DiscIO/DriveBlob.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
#include "DiscIO/Blob.h"
#ifdef _WIN32
#include "Common/StringUtil.h"
#else
#include <stdio.h> // fileno
#include <sys/ioctl.h>
#if defined __linux__
#include <linux/fs.h> // BLKGETSIZE64
#elif defined __FreeBSD__
#include <sys/disk.h> // DIOCGMEDIASIZE
#elif defined __APPLE__
#include <sys/disk.h> // DKIOCGETBLOCKCOUNT / DKIOCGETBLOCKSIZE
#endif
#endif
namespace DiscIO
{
DriveReader::DriveReader(const std::string& drive)
{
// 32 sectors is roughly the optimal amount a CD Drive can read in
// a single IO cycle. Larger values yield no performance improvement
// and just cause IO stalls from the read delay. Smaller values allow
// the OS IO and seeking overhead to ourstrip the time actually spent
// transferring bytes from the media.
SetChunkSize(32); // 32*2048 = 64KiB
SetSectorSize(2048);
#ifdef _WIN32
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 (IsOK())
{
// Do a test read to make sure everything is OK, since it seems you can get
// handles to empty drives.
DWORD not_used;
std::vector<u8> buffer(GetSectorSize());
if (!ReadFile(m_disc_handle, buffer.data(), GetSectorSize(), &not_used, nullptr))
{
// OK, something is wrong.
CloseHandle(m_disc_handle);
m_disc_handle = INVALID_HANDLE_VALUE;
}
}
if (IsOK())
{
// Initialize m_size by querying the volume capacity.
STORAGE_READ_CAPACITY storage_size;
storage_size.Version = sizeof(storage_size);
DWORD bytes = 0;
DeviceIoControl(m_disc_handle, IOCTL_STORAGE_READ_CAPACITY, nullptr, 0, &storage_size,
sizeof(storage_size), &bytes, nullptr);
m_size = bytes ? storage_size.DiskLength.QuadPart : 0;
#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
m_file.Open(drive, "rb");
if (m_file)
{
int fd = fileno(m_file.GetHandle());
#if defined __linux__
// NOTE: Doesn't matter if it fails, m_size was initialized to zero
ioctl(fd, BLKGETSIZE64, &m_size); // u64*
#elif defined __FreeBSD__
off_t size = 0;
ioctl(fd, DIOCGMEDIASIZE, &size); // off_t*
m_size = size;
#elif defined __APPLE__
u64 count = 0;
u32 block_size = 0;
ioctl(fd, DKIOCGETBLOCKCOUNT, &count); // u64*
ioctl(fd, DKIOCGETBLOCKSIZE, &block_size); // u32*
m_size = count * block_size;
#endif
#endif
}
else
{
NOTICE_LOG_FMT(DISCIO, "Load from DVD backup failed or no disc in drive {}", drive);
}
}
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
}
std::unique_ptr<DriveReader> DriveReader::Create(const std::string& drive)
{
auto reader = std::unique_ptr<DriveReader>(new DriveReader(drive));
if (!reader->IsOK())
reader.reset();
return reader;
}
bool DriveReader::GetBlock(u64 block_num, u8* out_ptr)
{
return DriveReader::ReadMultipleAlignedBlocks(block_num, 1, out_ptr);
}
bool DriveReader::ReadMultipleAlignedBlocks(u64 block_num, u64 num_blocks, u8* out_ptr)
{
#ifdef _WIN32
LARGE_INTEGER offset;
offset.QuadPart = GetSectorSize() * block_num;
DWORD bytes_read;
if (!SetFilePointerEx(m_disc_handle, offset, nullptr, FILE_BEGIN) ||
!ReadFile(m_disc_handle, out_ptr, static_cast<DWORD>(GetSectorSize() * num_blocks),
&bytes_read, nullptr))
{
ERROR_LOG_FMT(DISCIO, "Disc Read Error");
return false;
}
return bytes_read == GetSectorSize() * num_blocks;
#else
m_file.Seek(GetSectorSize() * block_num, File::SeekOrigin::Begin);
if (m_file.ReadBytes(out_ptr, num_blocks * GetSectorSize()))
return true;
m_file.ClearError();
return false;
#endif
}
} // namespace DiscIO

View File

@ -1,54 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <string>
#include "Common/CommonTypes.h"
#include "Common/IOFile.h"
#include "DiscIO/Blob.h"
#ifdef _WIN32
#include <windows.h>
#include <winioctl.h>
#endif
namespace DiscIO
{
class DriveReader : public SectorReader
{
public:
static std::unique_ptr<DriveReader> Create(const std::string& drive);
~DriveReader();
BlobType GetBlobType() const override { return BlobType::DRIVE; }
u64 GetRawSize() const override { return m_size; }
u64 GetDataSize() const override { return m_size; }
DataSizeType GetDataSizeType() const override { return DataSizeType::Accurate; }
u64 GetBlockSize() const override { return ECC_BLOCK_SIZE; }
bool HasFastRandomAccessInBlock() const override { return false; }
std::string GetCompressionMethod() const override { return {}; }
std::optional<int> GetCompressionLevel() const override { return std::nullopt; }
private:
DriveReader(const std::string& drive);
bool GetBlock(u64 block_num, u8* out_ptr) override;
bool ReadMultipleAlignedBlocks(u64 block_num, u64 num_blocks, u8* out_ptr) override;
#ifdef _WIN32
HANDLE m_disc_handle = INVALID_HANDLE_VALUE;
PREVENT_MEDIA_REMOVAL m_lock_cdrom;
bool IsOK() const { return m_disc_handle != INVALID_HANDLE_VALUE; }
#else
File::IOFile m_file;
bool IsOK() const { return m_file.IsOpen() && m_file.IsGood(); }
#endif
static constexpr u64 ECC_BLOCK_SIZE = 0x8000;
u64 m_size = 0;
};
} // namespace DiscIO

View File

@ -438,7 +438,6 @@
<ClInclude Include="DiscIO\DiscExtractor.h" />
<ClInclude Include="DiscIO\DiscScrubber.h" />
<ClInclude Include="DiscIO\DiscUtils.h" />
<ClInclude Include="DiscIO\DriveBlob.h" />
<ClInclude Include="DiscIO\Enums.h" />
<ClInclude Include="DiscIO\FileBlob.h" />
<ClInclude Include="DiscIO\Filesystem.h" />
@ -1051,7 +1050,6 @@
<ClCompile Include="DiscIO\DiscExtractor.cpp" />
<ClCompile Include="DiscIO\DiscScrubber.cpp" />
<ClCompile Include="DiscIO\DiscUtils.cpp" />
<ClCompile Include="DiscIO\DriveBlob.cpp" />
<ClCompile Include="DiscIO\Enums.cpp" />
<ClCompile Include="DiscIO\FileBlob.cpp" />
<ClCompile Include="DiscIO\Filesystem.cpp" />

View File

@ -479,8 +479,6 @@ void MainWindow::ConnectMenuBar()
connect(m_menu_bar, &MenuBar::Exit, this, &MainWindow::close);
connect(m_menu_bar, &MenuBar::EjectDisc, this, &MainWindow::EjectDisc);
connect(m_menu_bar, &MenuBar::ChangeDisc, this, &MainWindow::ChangeDisc);
connect(m_menu_bar, &MenuBar::BootDVDBackup, this,
[this](const QString& drive) { StartGame(drive, ScanForSecondDisc::No); });
connect(m_menu_bar, &MenuBar::OpenUserFolder, this, &MainWindow::OpenUserFolder);
// Emulation

View File

@ -189,19 +189,6 @@ void MenuBar::OnDebugModeToggled(bool enabled)
}
}
void MenuBar::AddDVDBackupMenu(QMenu* file_menu)
{
m_backup_menu = file_menu->addMenu(tr("&Boot from DVD Backup"));
const std::vector<std::string> drives = Common::GetCDDevices();
// Windows Limitation of 24 character drives
for (size_t i = 0; i < drives.size() && i < 24; i++)
{
auto drive = QString::fromStdString(drives[i]);
m_backup_menu->addAction(drive, this, [this, drive] { emit BootDVDBackup(drive); });
}
}
void MenuBar::AddFileMenu()
{
QMenu* file_menu = addMenu(tr("&File"));
@ -212,8 +199,6 @@ void MenuBar::AddFileMenu()
m_change_disc = file_menu->addAction(tr("Change &Disc..."), this, &MenuBar::ChangeDisc);
m_eject_disc = file_menu->addAction(tr("&Eject Disc"), this, &MenuBar::EjectDisc);
AddDVDBackupMenu(file_menu);
file_menu->addSeparator();
m_open_user_folder =

View File

@ -54,7 +54,6 @@ signals:
void Open();
void Exit();
void ChangeDisc();
void BootDVDBackup(const QString& backup);
void EjectDisc();
void OpenUserFolder();
@ -127,7 +126,6 @@ private:
void OnEmulationStateChanged(Core::State state);
void AddFileMenu();
void AddDVDBackupMenu(QMenu* file_menu);
void AddEmulationMenu();
void AddStateLoadMenu(QMenu* emu_menu);