diff --git a/DumpDVD/DumpDVD.vcxproj b/DumpDVD/DumpDVD.vcxproj
index 34ee134..ec08c29 100644
--- a/DumpDVD/DumpDVD.vcxproj
+++ b/DumpDVD/DumpDVD.vcxproj
@@ -19,18 +19,24 @@
-
+
+
-
+
+
+
+
-
+
+
+
16.0
@@ -88,9 +94,9 @@
Level3
true
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
- $(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)
+ $(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)
stdcpp20
stdc17
@@ -109,9 +115,9 @@
true
true
false
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
- $(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)
+ $(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)
MultiThreaded
stdcpp20
stdc17
diff --git a/DumpDVD/DumpDVD.vcxproj.filters b/DumpDVD/DumpDVD.vcxproj.filters
index 9e69e3d..893fe00 100644
--- a/DumpDVD/DumpDVD.vcxproj.filters
+++ b/DumpDVD/DumpDVD.vcxproj.filters
@@ -15,10 +15,10 @@
-
+
Source Files
-
+
Source Files
@@ -30,9 +30,18 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
-
+
Header Files
@@ -47,5 +56,14 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/DumpDVD/Gui/DumpDVD.cpp b/DumpDVD/Gui/DumpDVD.cpp
new file mode 100644
index 0000000..f40f8c3
--- /dev/null
+++ b/DumpDVD/Gui/DumpDVD.cpp
@@ -0,0 +1,315 @@
+#include
+#include
+
+#ifdef _WIN32
+#include
+#include
+#endif
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "DumpDVD.hpp"
+
+#include "../Utils.hpp"
+#include "../Scsi/IoCtl.hpp"
+#include "../Scsi/OpticalDrive.hpp"
+
+
+namespace Li::Gui {
+
+ DumpDVD::DumpDVD() {
+ this->keepPolling = true;
+ this->showDemoWindow = true;
+ this->imRippinIt = false;
+ this->error = false;
+ this->done = false;
+
+ this->selectedDrive = 0;
+ this->windowFlags = ImGuiWindowFlags_NoCollapse;
+ this->selectedDriveSpeed = 0;
+ this->counter = 0;
+
+ this->drivesList = Li::Scsi::OpticalDrive::ListOpticalDrives();
+ this->pollDrives = new std::thread(&DumpDVD::pollDrivesThread, this);
+
+ this->sectorsReadSoFar = 0;
+ this->sectorsAtOnce = 0x400;
+
+ this->lock = new std::mutex();
+
+ this->reset();
+ }
+
+ DumpDVD::~DumpDVD() {
+ this->keepPolling = false;
+ this->pollDrives->join();
+ delete this->pollDrives;
+ freeOldDriveList();
+ }
+
+ void DumpDVD::ripDiscThread() {
+ std::ofstream* iso = new std::ofstream(std::string(this->outputFile), std::ios::binary);
+ uint64_t totalSectors = this->GetCurrentSelectedDrive()->Sectors();
+
+ std::vector* speeds = this->GetCurrentSelectedDrive()->SupportedSpeeds();
+ uint32_t speed = 0xFFFF;
+ if (this->selectedDriveSpeed < speeds->size()) {
+ speed = speeds->at(this->selectedDriveSpeed);
+ }
+
+ Li::Scsi::IoCtl* drive = new Li::Scsi::IoCtl(this->GetCurrentSelectedDrive()->DrivePath());
+
+ drive->AllowReadingPastDisc();
+ drive->SetDriveSpeed(speed, speed);
+ this->sectorsReadSoFar = 0;
+ dvdcss_seek(drive->GetDvdCssHandle(), 0, DVDCSS_SEEK_KEY);
+
+ uint8_t* buffer = new uint8_t[DVDCSS_BLOCK_SIZE * this->sectorsAtOnce];
+
+ do {
+ int sectorsToRead = this->sectorsAtOnce;
+ if ((this->sectorsReadSoFar + sectorsToRead) > totalSectors) {
+ sectorsToRead = totalSectors - this->sectorsReadSoFar;
+ }
+
+ int numRead = dvdcss_read(drive->GetDvdCssHandle(), buffer, sectorsToRead, DVDCSS_READ_DECRYPT);
+ if (numRead <= 0) {
+ this->error = true;
+ break;
+ }
+
+ iso->write((const char*)buffer, DVDCSS_BLOCK_SIZE * numRead);
+
+ this->sectorsReadSoFar += numRead;
+
+ } while (this->sectorsReadSoFar < totalSectors);
+ this->done = true;
+
+ delete buffer;
+ delete drive;
+ iso->close();
+ delete iso;
+ }
+
+ void DumpDVD::pollDrivesThread() {
+ while (this->keepPolling) {
+ if ( (this->counter % (60 * 10)) == 0) {
+ this->lock->lock();
+ refreshDriveList();
+ this->lock->unlock();
+ }
+ }
+ }
+
+ void DumpDVD::refreshDriveList() {
+ std::vector* pollDrives = Li::Scsi::OpticalDrive::ListOpticalDrives();
+ freeOldDriveList();
+ this->drivesList = pollDrives;
+
+ }
+ void DumpDVD::freeOldDriveList() {
+ std::vector* prevList = this->drivesList;
+ this->drivesList = nullptr;
+
+ for (Li::Scsi::OpticalDrive* drive : *prevList) {
+ delete drive;
+ }
+ delete prevList;
+ }
+ std::string DumpDVD::getDrivesStr() {
+ std::string drivesComboBox = "";
+ for (Li::Scsi::OpticalDrive* drive : *this->drivesList) {
+ drivesComboBox += drive->DrivePath() + " - " + drive->VolumeName() + '\0';
+ }
+ return drivesComboBox;
+ }
+
+ void DumpDVD::reset() {
+ if (this->GetCurrentSelectedDrive()->DiscInDrive())
+ this->selectedDriveSpeed = this->GetCurrentSelectedDrive()->SupportedSpeeds()->size();
+ else
+ this->selectedDriveSpeed = 0;
+
+ std::string documentsFolder = "";
+
+#ifdef _WIN32
+ WCHAR documents[MAX_PATH];
+ HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documents);
+ std::wstring wDocuments = std::wstring(documents);
+ documentsFolder = std::string(wDocuments.begin(), wDocuments.end());
+#endif
+
+ std::filesystem::path p = std::filesystem::path(documentsFolder);
+ p = p.append(GetCurrentSelectedDrive()->VolumeName()).replace_extension(".iso");
+ strncpy(this->outputFile, p.string().c_str(), sizeof(DumpDVD::outputFile)-1);
+ }
+
+ Li::Scsi::OpticalDrive* DumpDVD::GetCurrentSelectedDrive() {
+ return this->drivesList->at(this->selectedDrive);
+ }
+
+ void DumpDVD::startRip() {
+ refreshDriveList();
+ if (this->GetCurrentSelectedDrive()->DiscInDrive()) {
+ this->keepPolling = false;
+
+ this->pollDrives->join();
+ delete this->pollDrives;
+
+ this->pollDrives = new std::thread(&DumpDVD::ripDiscThread, this);
+
+ this->imRippinIt = true;
+ }
+ }
+
+ void DumpDVD::endRipAndGoBackToMenu() {
+ this->done = false;
+ this->imRippinIt = false;
+ this->reset();
+ this->sectorsReadSoFar = 0;
+ this->pollDrives->join();
+ delete this->pollDrives;
+
+ this->drivesList = Li::Scsi::OpticalDrive::ListOpticalDrives();
+ this->pollDrives = new std::thread(&DumpDVD::pollDrivesThread, this);
+ }
+
+
+
+ void DumpDVD::showRippingStatus() {
+ ImGui::SeparatorText("Status");
+ float percentage = (((float)this->sectorsReadSoFar / (float)this->GetCurrentSelectedDrive()->Sectors()));
+ ImGui::Text("Copying Disc ... ", (int)percentage);
+ ImGui::SameLine();
+ ImGui::ProgressBar(percentage);
+
+ ImGui::Text("Sector %lli / %lli", this->sectorsReadSoFar, this->GetCurrentSelectedDrive()->Sectors());
+
+ uint64_t szSoFar = this->sectorsReadSoFar * DVDCSS_BLOCK_SIZE;
+ uint64_t szTotal = this->GetCurrentSelectedDrive()->Sectors() * DVDCSS_BLOCK_SIZE;
+
+
+ ImGui::Text("Total %s / %s", Utils::HumanReadableByteStr(szSoFar).c_str(), Utils::HumanReadableByteStr(szTotal).c_str());
+
+ if (this->done) {
+ if (!this->error) {
+ ImGui::Begin("Complete", &done, this->windowFlags);
+ ImGui::Text("ISO file was created successfully.");
+ if (ImGui::Button("OK")) {
+ this->endRipAndGoBackToMenu();
+ }
+ ImGui::End();
+ }
+ else {
+ ImGui::Begin("Error", &done, this->windowFlags);
+ ImGui::Text("Error occured when creating an ISO");
+ if (ImGui::Button("OK")) {
+ this->endRipAndGoBackToMenu();
+ }
+ ImGui::End();
+ }
+ }
+ }
+
+ void DumpDVD::showRipMenu() {
+ this->lock->lock();
+
+ ImGui::SeparatorText("Input");
+
+ ImGui::Text("Drive: ");
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
+ if (ImGui::Combo("##driveList", &this->selectedDrive, this->getDrivesStr().c_str())) {
+ this->reset();
+ }
+
+
+ if (!GetCurrentSelectedDrive()->DiscInDrive()) {
+ ImGui::Text("Put a disc in the drive to continue ...");
+ }
+ else {
+ int numDrvSpeeds = GetCurrentSelectedDrive()->SupportedSpeeds()->size() + 1;
+
+ std::string driveSpeedName = "Unknown";
+ if (this->selectedDriveSpeed >= 0 && this->selectedDriveSpeed < GetCurrentSelectedDrive()->SupportedSpeeds()->size()) {
+ uint32_t speed = GetCurrentSelectedDrive()->SupportedSpeeds()->at(this->selectedDriveSpeed);
+ float spdFriendly = ((float)speed / (float)1352.0);
+
+ std::ostringstream xAmt;
+ xAmt.precision(1);
+ xAmt << std::fixed << spdFriendly;
+
+ driveSpeedName = xAmt.str() + "x (" + std::to_string(speed) + " kbps)";
+ }
+ else if (this->selectedDriveSpeed == GetCurrentSelectedDrive()->SupportedSpeeds()->size()) {
+ driveSpeedName = "As Fast as Possible";
+ }
+
+
+ ImGui::Text("Read Speed: ");
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
+ ImGui::SliderInt("##readSpeed", &this->selectedDriveSpeed, 0, numDrvSpeeds - 1, driveSpeedName.c_str());
+
+ ImGui::Text("Buffer Size (in sectors): ");
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
+ ImGui::InputInt("##bufferSize", &this->sectorsAtOnce, 1, 100);
+ if (this->sectorsAtOnce <= 0) this->sectorsAtOnce = 1;
+
+ ImGui::SeparatorText("Output");
+
+ ImGui::Text("Output file: ");
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 60);
+ ImGui::InputTextWithHint("##outputIso", "Output ISO file path", this->outputFile, IM_ARRAYSIZE(DumpDVD::outputFile));
+ ImGui::SameLine();
+ if (ImGui::Button("Browse")) {
+ auto sav = pfd::save_file("Save ISO", std::string(this->outputFile), { "ISO9660 Image Files (.iso)", "*.iso" }, pfd::opt::force_overwrite);
+ strncpy(this->outputFile, sav.result().c_str(), sizeof(DumpDVD::outputFile) - 1);
+ }
+
+ if (ImGui::Button("Create ISO", ImVec2(ImGui::GetContentRegionAvail().x, 20))) {
+ this->startRip();
+ }
+ }
+
+ this->lock->unlock();
+ }
+
+ void DumpDVD::RenderUI() {
+ if (this->drivesList == nullptr) return;
+
+ const ImGuiViewport* mainViewport = ImGui::GetMainViewport();
+ ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Appearing);
+ ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize, ImGuiCond_Appearing);
+
+ ImGui::Begin("DVD Dumper", NULL, windowFlags);
+
+ if (this->imRippinIt)
+ {
+ this->showRippingStatus();
+ }
+ else
+ {
+ this->showRipMenu();
+ }
+
+
+ ImGui::End();
+
+#ifdef _DEBUG
+ if (showDemoWindow)
+ ImGui::ShowDemoWindow(&showDemoWindow);
+#endif
+ this->counter++;
+ }
+
+}
\ No newline at end of file
diff --git a/DumpDVD/Gui/DumpDVD.hpp b/DumpDVD/Gui/DumpDVD.hpp
new file mode 100644
index 0000000..fb8dbe3
--- /dev/null
+++ b/DumpDVD/Gui/DumpDVD.hpp
@@ -0,0 +1,58 @@
+#ifndef _LI_DUMP_DVD_H
+#define _LI_DUMP_DVD_H 1
+#include
+#include
+#include
+#include
+
+#include "../Scsi/IoCtl.hpp"
+#include "../Scsi/OpticalDrive.hpp"
+
+namespace Li::Gui {
+
+ class DumpDVD {
+ private:
+ bool keepPolling;
+ bool showDemoWindow;
+ bool imRippinIt; // dodododo do do!
+
+ std::mutex* lock;
+
+ bool error;
+ bool done;
+ uint64_t sectorsReadSoFar;
+ int sectorsAtOnce;
+
+ int selectedDrive;
+ ImGuiWindowFlags windowFlags;
+ int selectedDriveSpeed;
+ uint32_t counter;
+ char outputFile[0x8000];
+
+
+ std::vector* drivesList;
+ std::thread* pollDrives;
+
+ void ripDiscThread();
+ void pollDrivesThread();
+
+ void freeOldDriveList();
+ void refreshDriveList();
+ std::string getDrivesStr();
+ void reset();
+
+ void startRip();
+ void endRipAndGoBackToMenu();
+
+ void showRipMenu();
+ void showRippingStatus();
+
+ public:
+ Li::Scsi::OpticalDrive* GetCurrentSelectedDrive();
+ DumpDVD();
+ ~DumpDVD();
+ void RenderUI();
+ };
+
+}
+#endif
\ No newline at end of file
diff --git a/DumpDVD/Gui/MainWindow.cpp b/DumpDVD/Gui/MainWindow.cpp
index bb97e4e..b32905c 100644
--- a/DumpDVD/Gui/MainWindow.cpp
+++ b/DumpDVD/Gui/MainWindow.cpp
@@ -11,65 +11,27 @@
#include
#include "SDL.hpp"
-#include "../Scsi/CdRom.hpp"
+#include "DumpDVD.hpp"
namespace Li::Gui {
- std::string getDrivesList() {
- std::vector* drives = Li::Scsi::CdRom::ListOpticalDrives();
-
- std::string drivesComboBox = "";
- for (std::string drive : *drives) {
- drivesComboBox += drive + '\0';
- }
-
- return drivesComboBox;
- }
+
MainWindow::MainWindow() {
this->sdl = new SDL("DumpDVD", 800, 400);
- bool showDemoWindow = true;
- int selectedDrive = 0;
- ImGuiWindowFlags windowFlags = 0;
- windowFlags |= ImGuiWindowFlags_NoCollapse;
- int selectedDriveSpeed = 22;
- std::string drives = getDrivesList();
+ DumpDVD* dumpDvdMenu = new DumpDVD();
while (!this->sdl->IsExiting()) {
this->sdl->PollEvent();
this->sdl->NewFrame();
- const ImGuiViewport* mainViewport = ImGui::GetMainViewport();
- ImGui::SetNextWindowPos(ImVec2(mainViewport->WorkPos.x, mainViewport->WorkPos.y), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
-
- ImGui::Begin("DVD Dumper", NULL, windowFlags);
- ImGui::Text("Select Drive:");
- ImGui::SameLine();
- ImGui::Combo("", &selectedDrive, drives.c_str());
- ImGui::SameLine();
- if (ImGui::Button("Refresh", ImVec2(70, 20))) {
- drives = getDrivesList();
- }
-
- const int numDrvSpeeds = 23;
- const char* driveSepeds[numDrvSpeeds] = { "1x", "2x", "2.4x", "3x", "4x", "5x",
- "6x", "8x", "10x", "12x", "14x", "16x",
- "18x", "20x", "22x", "24x", "32x", "40x",
- "44x", "48x", "52x", "56x", "MAX"};
- const char* driveSpeedName = (selectedDriveSpeed >= 0 && selectedDriveSpeed < numDrvSpeeds) ? driveSepeds[selectedDriveSpeed] : "Unknown";
- ImGui::Text("Read Speed:");
- ImGui::SameLine();
- ImGui::SliderInt("", &selectedDriveSpeed, 0, numDrvSpeeds - 1, driveSpeedName);
-
- ImGui::End();
- if (showDemoWindow)
- ImGui::ShowDemoWindow(&showDemoWindow);
+ dumpDvdMenu->RenderUI();
this->sdl->Render();
}
+ delete dumpDvdMenu;
}
MainWindow::~MainWindow() {
diff --git a/DumpDVD/Gui/SDL.cpp b/DumpDVD/Gui/SDL.cpp
index ad2cfac..1ca386f 100644
--- a/DumpDVD/Gui/SDL.cpp
+++ b/DumpDVD/Gui/SDL.cpp
@@ -33,7 +33,8 @@ namespace Li::Gui {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
+ ImGuiIO& io = ImGui::GetIO();
+ io.IniFilename = nullptr;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
ImGui::StyleColorsDark();
@@ -53,9 +54,9 @@ namespace Li::Gui {
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
- isExiting = true;
+ this->isExiting = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
- isExiting = true;
+ this->isExiting = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
{
// Release all outstanding references to the swap chain's buffers before resizing.
diff --git a/DumpDVD/DumpDVD.cpp b/DumpDVD/Main.cpp
similarity index 96%
rename from DumpDVD/DumpDVD.cpp
rename to DumpDVD/Main.cpp
index ead6496..2243677 100644
--- a/DumpDVD/DumpDVD.cpp
+++ b/DumpDVD/Main.cpp
@@ -1,5 +1,5 @@
#include
-#include "Gui\MainWindow.hpp"
+#include "Gui/MainWindow.hpp"
#ifdef _WIN32
#include
@@ -12,10 +12,6 @@
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow)
{
-#ifdef _WIN32
- AllocConsole();
-#endif
-
Li::Gui::MainWindow* mainWindow = new Li::Gui::MainWindow();
delete mainWindow;
diff --git a/DumpDVD/Scsi/CdRom.cpp b/DumpDVD/Scsi/CdRom.cpp
deleted file mode 100644
index 1163eb2..0000000
--- a/DumpDVD/Scsi/CdRom.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-#include "CdRom.hpp"
-
-#ifdef _WIN32
-
-#define _NTSCSI_USER_MODE_ 1
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#endif
-
-#include
-#include
-#include
-
-namespace Li::Scsi {
- CdRom::CdRom(std::string drive) {
- this->dvdCssHandle = dvdcss_open(drive.c_str());
- this->osFileHandle = dvdcss_get_raw_fd(this->dvdCssHandle);
- }
-
- CdRom::~CdRom() {
- dvdcss_close(this->dvdCssHandle);
- this->dvdCssHandle = NULL;
- this->osFileHandle = NULL;
- }
-
- size_t CdRom::GetTotalSectors() {
-#ifdef _WIN32
- DISK_GEOMETRY_EX geo;
- memset(&geo, 0x00, sizeof(DISK_GEOMETRY_EX));
-
- DWORD unused;
- BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nullptr, 0, &geo, sizeof(DISK_GEOMETRY_EX), &unused, nullptr);
- if (!success) {
- std::cerr << "Error getting geometry: " << std::to_string(GetLastError()) << std::endl;
- }
- return (size_t)(geo.DiskSize.QuadPart / 2048);
-#endif
- }
- bool CdRom::AllowReadingPastDisc() {
-#ifdef _WIN32
- // On windows, you cannot read anything outside the last session of the disc, unless you enable this
- // this means you cannot read the Lead-Out, *or* double densitity DVDs
- DWORD unused;
- BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr, 0, &unused, nullptr);
- if (!success) {
- std::cerr << "Error enabling DASD I/O: " << std::to_string(GetLastError()) << std::endl;
- }
- return success;
-#endif
- }
- bool CdRom::SetDriveSpeed(short readSpeed, short writeSpeed)
- {
-#ifdef _WIN32
- DWORD unused;
- CDROM_SET_SPEED cdromSetSpeed;
- memset(&cdromSetSpeed, 0x00, sizeof(CDROM_SET_SPEED));
-
- cdromSetSpeed.RequestType = CdromSetSpeed;
- cdromSetSpeed.ReadSpeed = readSpeed;
- cdromSetSpeed.WriteSpeed = writeSpeed;
- cdromSetSpeed.RotationControl = CdromDefaultRotation;
-
- BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, IOCTL_CDROM_SET_SPEED, &cdromSetSpeed, sizeof(CDROM_SET_SPEED), nullptr, 0, &unused, nullptr);
- if (!success) {
- std::cerr << "Error setting speed: " << std::to_string(GetLastError()) << std::endl;
- }
- return success;
-#endif
- }
-
- std::vector* CdRom::ListOpticalDrives() {
- std::vector* drives = new std::vector();
-#ifdef _WIN32
- const size_t drivesListSz = 0x1000;
- WCHAR* drivesList = new WCHAR[drivesListSz];
- GetLogicalDriveStrings(drivesListSz, drivesList);
-
- WCHAR* curDrive = drivesList;
- while (*curDrive != '\0') {
-
- UINT driveType = GetDriveType(curDrive);
- if (driveType == DRIVE_CDROM) {
- std::wstring wstr = std::wstring(curDrive);
- std::string cdromDrive = std::string(wstr.begin(), wstr.end());
- cdromDrive = cdromDrive.substr(0, cdromDrive.size() - 1);
- drives->push_back(cdromDrive);
- }
- curDrive += lstrlen(curDrive) + 1;
- }
-#endif
- return drives;
- }
-}
\ No newline at end of file
diff --git a/DumpDVD/Scsi/IoCtl.cpp b/DumpDVD/Scsi/IoCtl.cpp
new file mode 100644
index 0000000..0da2ca2
--- /dev/null
+++ b/DumpDVD/Scsi/IoCtl.cpp
@@ -0,0 +1,140 @@
+#include "IoCtl.hpp"
+
+#ifdef _WIN32
+
+#define _NTSCSI_USER_MODE_ 1
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#endif
+
+#include
+#include
+#include
+
+namespace Li::Scsi {
+ IoCtl::IoCtl(std::string drive) {
+ this->dvdCssHandle = dvdcss_open(drive.c_str());
+ this->osFileHandle = dvdcss_get_raw_fd(this->dvdCssHandle);
+ }
+
+ IoCtl::~IoCtl() {
+ dvdcss_close(this->dvdCssHandle);
+ this->dvdCssHandle = NULL;
+ this->osFileHandle = NULL;
+ }
+
+ std::vector* IoCtl::GetSupportedReadSpeeds() {
+ std::vector* speeds = new std::vector();
+#ifdef _WIN32
+ CDROM_PERFORMANCE_REQUEST perfRequest;
+ memset(&perfRequest, 0x00, sizeof(CDROM_PERFORMANCE_REQUEST));
+ perfRequest.RequestType = CdromPerformanceRequest;
+ perfRequest.PerformanceType = CdromReadPerformance;
+ perfRequest.Exceptions = CdromNominalPerformance;
+ perfRequest.Tolerance = Cdrom10Nominal20Exceptions;
+ perfRequest.StaringLba = 0;
+
+ uint64_t sz = sizeof(CDROM_PERFORMANCE_HEADER) * 0x1000;
+ byte* buffer = new byte[sz];
+ memset(buffer, 0x00, sz);
+
+ CDROM_PERFORMANCE_HEADER* perfHeader = (CDROM_PERFORMANCE_HEADER*)buffer;
+
+
+ DWORD unused;
+ BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, IOCTL_CDROM_GET_PERFORMANCE, &perfRequest, sizeof(CDROM_PERFORMANCE_REQUEST), perfHeader, sz, &unused, nullptr);
+ if (!success) {
+ std::cerr << "Error getting supported read speeds: " << std::to_string(GetLastError()) << std::endl;
+ }
+
+ uint64_t dataLen = _byteswap_ulong(*(uint32_t*)perfHeader->DataLength);
+ uint64_t count = dataLen / sizeof(CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR);
+ CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR* pptr = (CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR*)perfHeader->Data;
+ for (uint64_t i = 0; i < count; i++) {
+ CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR perfDesc = pptr[i];
+ uint32_t startPerf = _byteswap_ulong(*(uint32_t*)perfDesc.StartPerformance);
+ uint32_t endPerf = _byteswap_ulong(*(uint32_t*)perfDesc.EndPerformance);
+
+ bool startAlreadyInList = false;
+ bool endAlreadyInList = false;
+
+ for (uint32_t speed : *speeds) {
+ if (speed == startPerf) {
+ startAlreadyInList = true;
+ }
+ if (speed == startPerf) {
+ endAlreadyInList = true;
+ }
+ }
+
+ if(!startAlreadyInList)
+ speeds->push_back(startPerf);
+
+ if(!endAlreadyInList)
+ speeds->push_back(endPerf);
+ }
+
+ delete buffer;
+#endif
+ return speeds;
+ }
+
+ uint64_t IoCtl::GetTotalSectors() {
+#ifdef _WIN32
+ DISK_GEOMETRY_EX geometry;
+ memset(&geometry, 0x00, sizeof(DISK_GEOMETRY_EX));
+
+ DWORD unused;
+ BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, nullptr, 0, &geometry, sizeof(DISK_GEOMETRY_EX), &unused, nullptr);
+ if (!success) {
+ std::cerr << "Error getting geometry: " << std::to_string(GetLastError()) << std::endl;
+ }
+ return (uint64_t)(geometry.DiskSize.QuadPart / DVDCSS_BLOCK_SIZE);
+#endif
+ }
+ bool IoCtl::AllowReadingPastDisc() {
+#ifdef _WIN32
+ // On windows, you cannot read anything outside the last session of the disc, unless you enable this
+ // this means you cannot read the Lead-Out, *or* double densitity DVDs
+ DWORD unused;
+ BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr, 0, &unused, nullptr);
+ if (!success) {
+ std::cerr << "Error enabling DASD I/O: " << std::to_string(GetLastError()) << std::endl;
+ }
+ return success;
+#endif
+ }
+ bool IoCtl::SetDriveSpeed(int readSpeed, int writeSpeed)
+ {
+#ifdef _WIN32
+ DWORD unused;
+ CDROM_SET_SPEED cdromSetSpeed;
+ memset(&cdromSetSpeed, 0x00, sizeof(CDROM_SET_SPEED));
+
+ cdromSetSpeed.RequestType = CdromSetSpeed;
+ cdromSetSpeed.ReadSpeed = (uint16_t)readSpeed;
+ cdromSetSpeed.WriteSpeed = (uint16_t)writeSpeed;
+ cdromSetSpeed.RotationControl = CdromDefaultRotation;
+
+ BOOL success = DeviceIoControl((HANDLE)this->osFileHandle, IOCTL_CDROM_SET_SPEED, &cdromSetSpeed, sizeof(CDROM_SET_SPEED), nullptr, 0, &unused, nullptr);
+ if (!success) {
+ std::cerr << "Error setting speed: " << std::to_string(GetLastError()) << std::endl;
+ }
+ return success;
+#endif
+ }
+
+
+ dvdcss_t IoCtl::GetDvdCssHandle() {
+ return this->dvdCssHandle;
+ }
+
+}
\ No newline at end of file
diff --git a/DumpDVD/Scsi/CdRom.hpp b/DumpDVD/Scsi/IoCtl.hpp
similarity index 51%
rename from DumpDVD/Scsi/CdRom.hpp
rename to DumpDVD/Scsi/IoCtl.hpp
index bb2c729..74e43e2 100644
--- a/DumpDVD/Scsi/CdRom.hpp
+++ b/DumpDVD/Scsi/IoCtl.hpp
@@ -6,18 +6,20 @@
#include
namespace Li::Scsi {
- class CdRom {
+ class IoCtl {
private:
dvdcss_t dvdCssHandle;
int osFileHandle;
public:
- CdRom(std::string drive);
- ~CdRom();
+ IoCtl(std::string drive);
+ ~IoCtl();
- size_t GetTotalSectors();
- bool SetDriveSpeed(short readSpeed, short writeSpeed);
+ dvdcss_t GetDvdCssHandle();
+ uint64_t GetTotalSectors();
+ bool SetDriveSpeed(int readSpeed, int writeSpeed);
bool AllowReadingPastDisc();
- static std::vector* ListOpticalDrives();
+ std::vector* GetSupportedReadSpeeds();
+
};
}
#endif
\ No newline at end of file
diff --git a/DumpDVD/Scsi/OpticalDrive.cpp b/DumpDVD/Scsi/OpticalDrive.cpp
new file mode 100644
index 0000000..d18a63a
--- /dev/null
+++ b/DumpDVD/Scsi/OpticalDrive.cpp
@@ -0,0 +1,95 @@
+#include "OpticalDrive.hpp"
+#include "IoCtl.hpp"
+
+#ifdef _WIN32
+#include
+#endif
+
+#define BUFFER_SIZE (0x1000)
+#define NODISC ("NO DISC")
+
+namespace Li::Scsi {
+
+
+ void OpticalDrive::getDriveInformation(std::string drv) {
+#ifdef _WIN32
+ this->drivePath = drv.substr(0, drv.size() - 1);
+
+ std::wstring wdrive = std::wstring(this->drivePath.begin(), this->drivePath.end());
+ WCHAR* wChrVolumeName = new WCHAR[BUFFER_SIZE];
+
+ if (!GetVolumeInformation(wdrive.c_str(), wChrVolumeName, BUFFER_SIZE, NULL, NULL, NULL, NULL, NULL))
+ {
+ this->volumeName = NODISC;
+ this->discInDrive = false;
+ }
+ else {
+ std::wstring wVolumeName = std::wstring(wChrVolumeName);
+ this->volumeName = std::string(wVolumeName.begin(), wVolumeName.end());
+ this->discInDrive = true;
+ }
+
+ delete wChrVolumeName;
+#endif
+ }
+
+ OpticalDrive::OpticalDrive(std::string drv) {
+ this->getDriveInformation(drv);
+
+ if (this->discInDrive) {
+ IoCtl* ctl = new IoCtl(this->drivePath);
+ this->supportedSpeeds = ctl->GetSupportedReadSpeeds();
+ this->sectors = ctl->GetTotalSectors();
+ delete ctl;
+ }
+ }
+ OpticalDrive::~OpticalDrive() {
+ if(this->discInDrive)
+ delete this->supportedSpeeds;
+ }
+
+ std::vector* OpticalDrive::SupportedSpeeds() {
+ return this->supportedSpeeds;
+ }
+
+ std::string OpticalDrive::VolumeName() {
+ return this->volumeName;
+ }
+
+ std::string OpticalDrive::DrivePath() {
+ return this->drivePath;
+ }
+
+ uint64_t OpticalDrive::Sectors() {
+ return this->sectors;
+ }
+
+ bool OpticalDrive::DiscInDrive() {
+ return this->discInDrive;
+ }
+
+ std::vector* OpticalDrive::ListOpticalDrives() {
+ std::vector* drives = new std::vector();
+#ifdef _WIN32
+ WCHAR* drivesList = new WCHAR[BUFFER_SIZE];
+ GetLogicalDriveStrings(BUFFER_SIZE, drivesList);
+
+ WCHAR* curDrive = drivesList;
+ while (*curDrive != '\0') {
+
+ UINT driveType = GetDriveType(curDrive);
+ if (driveType == DRIVE_CDROM) {
+ std::wstring wDrive = std::wstring(curDrive);
+ std::string drive = std::string(wDrive.begin(), wDrive.end());
+ OpticalDrive* opticalDrive = new OpticalDrive(drive);
+ drives->push_back(opticalDrive);
+ }
+ curDrive += lstrlen(curDrive) + 1;
+ }
+
+ delete drivesList;
+#endif
+ return drives;
+ }
+
+}
\ No newline at end of file
diff --git a/DumpDVD/Scsi/OpticalDrive.hpp b/DumpDVD/Scsi/OpticalDrive.hpp
new file mode 100644
index 0000000..e81983d
--- /dev/null
+++ b/DumpDVD/Scsi/OpticalDrive.hpp
@@ -0,0 +1,30 @@
+#ifndef _LI_OPTICAL_DRIVE_H
+#define _LI_OPTICAL_DRIVE_H 1
+#include
+#include
+namespace Li::Scsi {
+ class OpticalDrive {
+ private:
+ std::string drivePath;
+ std::string volumeName;
+
+ bool discInDrive;
+ std::vector* supportedSpeeds;
+ uint64_t sectors;
+
+ void getDriveInformation(std::string drv);
+ public:
+ OpticalDrive(std::string drv);
+ ~OpticalDrive();
+
+ std::vector* SupportedSpeeds();
+ std::string DrivePath();
+ std::string VolumeName();
+ uint64_t Sectors();
+ bool DiscInDrive();
+
+ static std::vector* ListOpticalDrives();
+ };
+
+}
+#endif
\ No newline at end of file
diff --git a/DumpDVD/Utils.cpp b/DumpDVD/Utils.cpp
new file mode 100644
index 0000000..9621b31
--- /dev/null
+++ b/DumpDVD/Utils.cpp
@@ -0,0 +1,23 @@
+#include "Utils.hpp"
+#include
+#include
+
+namespace Li {
+ std::string Utils::HumanReadableByteStr(uint64_t bytes)
+ {
+ const char* suffix[5] = { "B", "KB", "MB", "GB", "TB" };
+ char length = sizeof(suffix) / sizeof(suffix[0]);
+
+ int i = 0;
+ double dblBytes = bytes;
+
+ if (bytes > 1024) {
+ for (i = 0; (bytes / 1024) > 0 && i < length - 1; i++, bytes /= 1024)
+ dblBytes = bytes / 1024.0;
+ }
+
+ static char output[0x8000];
+ std::snprintf(output, sizeof(output), "%.02lf %s", dblBytes, suffix[i]);
+ return std::string(output);
+ }
+}
\ No newline at end of file
diff --git a/DumpDVD/Utils.hpp b/DumpDVD/Utils.hpp
new file mode 100644
index 0000000..d899781
--- /dev/null
+++ b/DumpDVD/Utils.hpp
@@ -0,0 +1,9 @@
+#ifndef _LI_UTILS
+#include
+namespace Li {
+ class Utils {
+ public:
+ static std::string HumanReadableByteStr(uint64_t bytes);
+ };
+}
+#endif
\ No newline at end of file
diff --git a/DumpDVD/imgui.ini b/DumpDVD/imgui.ini
deleted file mode 100644
index d995f46..0000000
--- a/DumpDVD/imgui.ini
+++ /dev/null
@@ -1,45 +0,0 @@
-[Window][Debug##Default]
-Pos=122,92
-Size=400,400
-Collapsed=0
-
-[Window][Dear ImGui Demo]
-Pos=476,67
-Size=550,679
-Collapsed=0
-
-[Window][Hello, world!]
-Pos=60,60
-Size=339,180
-Collapsed=0
-
-[Window][DVD Dumper]
-Pos=71,27
-Size=1333,735
-Collapsed=0
-
-[Window][Example: Console]
-Pos=345,114
-Size=520,600
-Collapsed=0
-
-[Window][Example: Custom rendering]
-Pos=60,60
-Size=485,414
-Collapsed=0
-
-[Window][Same title as another window##2]
-Pos=491,274
-Size=451,61
-Collapsed=0
-
-[Window][###AnimatedTitle]
-Pos=489,380
-Size=247,48
-Collapsed=0
-
-[Window][Same title as another window##1]
-Pos=473,190
-Size=451,61
-Collapsed=0
-
diff --git a/include/PFD/portable-file-dialogs.h b/include/PFD/portable-file-dialogs.h
new file mode 100644
index 0000000..1fc79a2
--- /dev/null
+++ b/include/PFD/portable-file-dialogs.h
@@ -0,0 +1,1887 @@
+//
+// Portable File Dialogs
+//
+// Copyright © 2018–2022 Sam Hocevar
+//
+// This library is free software. It comes without any warranty, to
+// the extent permitted by applicable law. You can redistribute it
+// and/or modify it under the terms of the Do What the Fuck You Want
+// to Public License, Version 2, as published by the WTFPL Task Force.
+// See http://www.wtfpl.net/ for more details.
+//
+
+#pragma once
+
+#if _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+#include
+#include
+#include
+#include // IFileDialog
+#include
+#include
+#include // std::async
+#include // GetUserProfileDirectory()
+
+#elif __EMSCRIPTEN__
+#include
+
+#else
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 2 // for popen()
+#endif
+#ifdef __APPLE__
+# ifndef _DARWIN_C_SOURCE
+# define _DARWIN_C_SOURCE
+# endif
+#endif
+#include // popen()
+#include // std::getenv()
+#include // fcntl()
+#include // read(), pipe(), dup2(), getuid()
+#include // ::kill, std::signal
+#include // stat()
+#include // waitpid()
+#include // getpwnam()
+#endif
+
+#include // std::string
+#include // std::shared_ptr
+#include // std::ostream
+#include