upload changes

This commit is contained in:
Li 2023-03-15 19:59:59 +13:00
parent cf46d4693e
commit b6f21843d0
16 changed files with 2609 additions and 213 deletions

View File

@ -19,18 +19,24 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DumpDVD.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="Gui\D3D.cpp" />
<ClCompile Include="Gui\DumpDVD.cpp" />
<ClCompile Include="Gui\MainWindow.cpp" />
<ClCompile Include="Gui\SDL.cpp" />
<ClCompile Include="Scsi\CdRom.cpp" />
<ClCompile Include="Scsi\IoCtl.cpp" />
<ClCompile Include="Scsi\OpticalDrive.cpp" />
<ClCompile Include="Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Gui\D3D.hpp" />
<ClInclude Include="Gui\DumpDVD.hpp" />
<ClInclude Include="Gui\MainWindow.hpp" />
<ClInclude Include="Gui\Renderer.hpp" />
<ClInclude Include="Gui\SDL.hpp" />
<ClInclude Include="Scsi\CdRom.hpp" />
<ClInclude Include="Utils.hpp" />
<ClInclude Include="Scsi\IoCtl.hpp" />
<ClInclude Include="Scsi\OpticalDrive.hpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
@ -88,9 +94,9 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
</ClCompile>
@ -109,9 +115,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>

View File

@ -15,10 +15,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DumpDVD.cpp">
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Scsi\CdRom.cpp">
<ClCompile Include="Scsi\IoCtl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Gui\MainWindow.cpp">
@ -30,9 +30,18 @@
<ClCompile Include="Gui\SDL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Scsi\OpticalDrive.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Gui\DumpDVD.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Scsi\CdRom.hpp">
<ClInclude Include="Scsi\IoCtl.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Gui\MainWindow.hpp">
@ -47,5 +56,14 @@
<ClInclude Include="Gui\Renderer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Scsi\OpticalDrive.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Gui\DumpDVD.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

315
DumpDVD/Gui/DumpDVD.cpp Normal file
View File

@ -0,0 +1,315 @@
#include <imgui.h>
#include <SDL.h>
#ifdef _WIN32
#include <Windows.h>
#include <shlobj.h>
#endif
#include <portable-file-dialogs.h>
#include <iostream>
#include <fstream>
#include <mutex>
#include <thread>
#include <sstream>
#include <filesystem>
#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<uint32_t>* 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<Li::Scsi::OpticalDrive*>* pollDrives = Li::Scsi::OpticalDrive::ListOpticalDrives();
freeOldDriveList();
this->drivesList = pollDrives;
}
void DumpDVD::freeOldDriveList() {
std::vector<Li::Scsi::OpticalDrive*>* 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++;
}
}

58
DumpDVD/Gui/DumpDVD.hpp Normal file
View File

@ -0,0 +1,58 @@
#ifndef _LI_DUMP_DVD_H
#define _LI_DUMP_DVD_H 1
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#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<Li::Scsi::OpticalDrive*>* 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

View File

@ -11,65 +11,27 @@
#include <vector>
#include "SDL.hpp"
#include "../Scsi/CdRom.hpp"
#include "DumpDVD.hpp"
namespace Li::Gui {
std::string getDrivesList() {
std::vector<std::string>* 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() {

View File

@ -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.

View File

@ -1,5 +1,5 @@
#include <iostream>
#include "Gui\MainWindow.hpp"
#include "Gui/MainWindow.hpp"
#ifdef _WIN32
#include <Windows.h>
@ -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;

View File

@ -1,101 +0,0 @@
#include "CdRom.hpp"
#ifdef _WIN32
#define _NTSCSI_USER_MODE_ 1
#include <windows.h>
#include <winioctl.h>
#include <ntddcdrm.h>
#include <ntddcdvd.h>
#include <ntddmmc.h>
#include <ntddscsi.h>
#include <stddef.h>
#include <stdint.h>
#include <scsi.h>
#endif
#include <dvdcss.h>
#include <iostream>
#include <string>
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<std::string>* CdRom::ListOpticalDrives() {
std::vector<std::string>* drives = new std::vector<std::string>();
#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;
}
}

140
DumpDVD/Scsi/IoCtl.cpp Normal file
View File

@ -0,0 +1,140 @@
#include "IoCtl.hpp"
#ifdef _WIN32
#define _NTSCSI_USER_MODE_ 1
#include <windows.h>
#include <winioctl.h>
#include <ntddcdrm.h>
#include <ntddcdvd.h>
#include <ntddmmc.h>
#include <ntddscsi.h>
#include <stddef.h>
#include <stdint.h>
#include <scsi.h>
#endif
#include <dvdcss.h>
#include <iostream>
#include <string>
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<uint32_t>* IoCtl::GetSupportedReadSpeeds() {
std::vector<uint32_t>* speeds = new std::vector<uint32_t>();
#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;
}
}

View File

@ -6,18 +6,20 @@
#include <dvdcss.h>
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<std::string>* ListOpticalDrives();
std::vector<uint32_t>* GetSupportedReadSpeeds();
};
}
#endif

View File

@ -0,0 +1,95 @@
#include "OpticalDrive.hpp"
#include "IoCtl.hpp"
#ifdef _WIN32
#include <Windows.h>
#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<uint32_t>* 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*>* OpticalDrive::ListOpticalDrives() {
std::vector<OpticalDrive*>* drives = new std::vector<OpticalDrive*>();
#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;
}
}

View File

@ -0,0 +1,30 @@
#ifndef _LI_OPTICAL_DRIVE_H
#define _LI_OPTICAL_DRIVE_H 1
#include <vector>
#include <iostream>
namespace Li::Scsi {
class OpticalDrive {
private:
std::string drivePath;
std::string volumeName;
bool discInDrive;
std::vector<uint32_t>* supportedSpeeds;
uint64_t sectors;
void getDriveInformation(std::string drv);
public:
OpticalDrive(std::string drv);
~OpticalDrive();
std::vector<uint32_t>* SupportedSpeeds();
std::string DrivePath();
std::string VolumeName();
uint64_t Sectors();
bool DiscInDrive();
static std::vector<OpticalDrive*>* ListOpticalDrives();
};
}
#endif

23
DumpDVD/Utils.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "Utils.hpp"
#include <iostream>
#include <string>
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);
}
}

9
DumpDVD/Utils.hpp Normal file
View File

@ -0,0 +1,9 @@
#ifndef _LI_UTILS
#include <string>
namespace Li {
class Utils {
public:
static std::string HumanReadableByteStr(uint64_t bytes);
};
}
#endif

View File

@ -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

File diff suppressed because it is too large Load Diff