Fix decryption
This commit is contained in:
parent
7eeee60df5
commit
103bb58da3
|
@ -6,6 +6,10 @@ libdvdcss/msvc/Debug/*
|
|||
libdvdcss/msvc/Release/*
|
||||
libdvdcss/msvc/.vs/*
|
||||
|
||||
Lib9660/Release/*
|
||||
Lib9660/Debug/*
|
||||
|
||||
|
||||
ImGui/Release/*
|
||||
ImGui/Debug/*
|
||||
|
||||
|
|
29
DumpDVD.sln
29
DumpDVD.sln
|
@ -4,29 +4,58 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
VisualStudioVersion = 17.4.33205.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DumpDVD", "DumpDVD\DumpDVD.vcxproj", "{A9A5F041-541F-47EA-B583-DE84B59D9B62}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04} = {50F2BF62-8520-4B37-97DD-578EA282EC04}
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2} = {7F404DED-08FF-4092-97EF-0F63C5788DD2}
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732} = {B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libdvdcss", "libdvdcss\msvc\libdvdcss.vcxproj", "{50F2BF62-8520-4B37-97DD-578EA282EC04}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImGui", "ImGui\ImGui.vcxproj", "{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lib9660", "Lib9660\Lib9660.vcxproj", "{7F404DED-08FF-4092-97EF-0F63C5788DD2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Debug|x64.Build.0 = Debug|x64
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Release|x64.ActiveCfg = Release|x64
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Release|x64.Build.0 = Release|x64
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A9A5F041-541F-47EA-B583-DE84B59D9B62}.Release|x86.Build.0 = Release|Win32
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Debug|x64.Build.0 = Debug|x64
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Debug|x86.ActiveCfg = Release|Win32
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Debug|x86.Build.0 = Release|Win32
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Release|x64.ActiveCfg = Release|x64
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Release|x64.Build.0 = Release|x64
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Release|x86.ActiveCfg = Release|Win32
|
||||
{50F2BF62-8520-4B37-97DD-578EA282EC04}.Release|x86.Build.0 = Release|Win32
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Debug|x64.Build.0 = Debug|x64
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Debug|x86.ActiveCfg = Release|Win32
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Debug|x86.Build.0 = Release|Win32
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Release|x64.ActiveCfg = Release|x64
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Release|x64.Build.0 = Release|x64
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B2BCCCDA-BDB0-4FBE-84A3-EA1E8429F732}.Release|x86.Build.0 = Release|Win32
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Debug|x64.Build.0 = Debug|x64
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Debug|x86.ActiveCfg = Release|Win32
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Debug|x86.Build.0 = Release|Win32
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Release|x64.ActiveCfg = Release|x64
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Release|x64.Build.0 = Release|x64
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7F404DED-08FF-4092-97EF-0F63C5788DD2}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Dvd\DvdRipper.cpp" />
|
||||
<ClCompile Include="Dvd\TitleKey.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Gui\D3D.cpp" />
|
||||
<ClCompile Include="Gui\DumpDVD.cpp" />
|
||||
|
@ -29,6 +31,8 @@
|
|||
<ClCompile Include="Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Dvd\DvdRipper.hpp" />
|
||||
<ClInclude Include="Dvd\TitleKey.hpp" />
|
||||
<ClInclude Include="Gui\D3D.hpp" />
|
||||
<ClInclude Include="Gui\DumpDVD.hpp" />
|
||||
<ClInclude Include="Gui\MainWindow.hpp" />
|
||||
|
@ -96,7 +100,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)Lib9660;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
|
@ -104,7 +108,7 @@
|
|||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d11.lib;winmm.lib;version.lib;Imm32.lib;Setupapi.lib;SDL2.lib;ImGui.lib;libdvdcss.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d11.lib;winmm.lib;version.lib;Imm32.lib;Setupapi.lib;SDL2.lib;ImGui.lib;Lib9660.lib;libdvdcss.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<EntryPointSymbol>
|
||||
</EntryPointSymbol>
|
||||
</Link>
|
||||
|
@ -117,7 +121,7 @@
|
|||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)include\PFD;$(SolutionDir)include\SDL;$(SolutionDir)Lib9660;$(SolutionDir)ImGui;$(SolutionDir)libdvdcss\src\dvdcss;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
|
@ -128,7 +132,7 @@
|
|||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d11.lib;winmm.lib;version.lib;Imm32.lib;Setupapi.lib;SDL2.lib;ImGui.lib;libdvdcss.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d11.lib;winmm.lib;version.lib;Imm32.lib;Setupapi.lib;SDL2.lib;ImGui.lib;Lib9660.lib;libdvdcss.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
<ClCompile Include="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Dvd\TitleKey.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Dvd\DvdRipper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Scsi\IoCtl.hpp">
|
||||
|
@ -65,5 +71,11 @@
|
|||
<ClInclude Include="Utils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Dvd\TitleKey.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Dvd\DvdRipper.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,233 @@
|
|||
#include "DvdRipper.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../Scsi/IoCtl.hpp"
|
||||
#include "../Scsi/OpticalDrive.hpp"
|
||||
#include "../Dvd/TitleKey.hpp"
|
||||
|
||||
namespace Li::Dvd {
|
||||
|
||||
|
||||
|
||||
uint32_t DvdRipper::FileSoFar() {
|
||||
if (this->inFile)
|
||||
return this->fileReadSoFar;
|
||||
else
|
||||
return this->nonFileReadSoFar;
|
||||
}
|
||||
uint32_t DvdRipper::FileLen() {
|
||||
if (this->inFile)
|
||||
return this->fileRemain;
|
||||
else
|
||||
return this->nonFileRemain;
|
||||
}
|
||||
|
||||
float DvdRipper::PercentDone() {
|
||||
return (((float)this->sectorsReadSoFar / (float)this->drive->Sectors()));
|
||||
}
|
||||
uint32_t DvdRipper::SectorsReadSoFar() {
|
||||
return this->sectorsReadSoFar;
|
||||
}
|
||||
uint32_t DvdRipper::FileReadSoFar() {
|
||||
return this->fileReadSoFar;
|
||||
}
|
||||
std::string DvdRipper::OutputPath() {
|
||||
return this->outputPath;
|
||||
}
|
||||
|
||||
bool DvdRipper::Done() {
|
||||
return this->done;
|
||||
}
|
||||
bool DvdRipper::Error() {
|
||||
return this->error;
|
||||
}
|
||||
std::string DvdRipper::ErrorMessage() {
|
||||
return this->errorMsg;
|
||||
}
|
||||
int DvdRipper::read1SectorATimeSkippingBadSectors(int toRead) {
|
||||
memset(this->tmpBuffer, 0x00, this->sectorsAtOnce * DVDCSS_BLOCK_SIZE);
|
||||
int nmRd = 0;
|
||||
for (int i = 0; i < toRead; i++) {
|
||||
for (int retry = 0; retry < 10; retry++) {
|
||||
int dataRd = dvdcss_read(driveIoCtl->GetDvdCssHandle(), this->tmpBuffer + (i * DVDCSS_BLOCK_SIZE), 1, DVDCSS_READ_DECRYPT);
|
||||
if (dataRd < 0) {
|
||||
continue; // retry
|
||||
}
|
||||
}
|
||||
nmRd += 1;
|
||||
}
|
||||
|
||||
return nmRd;
|
||||
|
||||
}
|
||||
void DvdRipper::readNonFileSectors() {
|
||||
dvdcss_title(this->driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar);
|
||||
|
||||
this->nonFileRemain = Li::Dvd::TitleKey::GetDistanceToNextFile(this->sectorsReadSoFar);
|
||||
if (this->nonFileRemain == (uint32_t)-1) {
|
||||
this->nonFileRemain = (this->drive->Sectors() - this->sectorsReadSoFar);
|
||||
}
|
||||
if ((this->sectorsReadSoFar + this->nonFileRemain) > this->drive->Sectors()) {
|
||||
this->nonFileRemain = (this->drive->Sectors() - this->sectorsReadSoFar);
|
||||
}
|
||||
this->nonFileReadSoFar = 0;
|
||||
|
||||
do {
|
||||
int toRead = this->sectorsAtOnce;
|
||||
if ((this->nonFileReadSoFar + toRead) > this->nonFileRemain) {
|
||||
toRead = this->nonFileRemain - this->nonFileReadSoFar;
|
||||
}
|
||||
int numRead = dvdcss_read(driveIoCtl->GetDvdCssHandle(), this->tmpBuffer, toRead, DVDCSS_READ_DECRYPT);
|
||||
|
||||
if (dvdcss_was_error(driveIoCtl->GetDvdCssHandle())) {
|
||||
this->errorMsg = std::string(dvdcss_error(driveIoCtl->GetDvdCssHandle()));
|
||||
}
|
||||
if (numRead < 0) {
|
||||
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), this->sectorsAtOnce, DVDCSS_SEEK_MPEG);
|
||||
numRead = read1SectorATimeSkippingBadSectors(toRead);
|
||||
}
|
||||
|
||||
this->iso->write((const char*)this->tmpBuffer, DVDCSS_BLOCK_SIZE * numRead);
|
||||
|
||||
this->sectorsReadSoFar += numRead;
|
||||
this->nonFileReadSoFar += numRead;
|
||||
|
||||
} while (this->nonFileReadSoFar < this->nonFileRemain && this->keepRunning);
|
||||
|
||||
this->inFile = Li::Dvd::TitleKey::IsSectorInFile(this->sectorsReadSoFar);
|
||||
this->fileReadSoFar = 0;
|
||||
this->nonFileReadSoFar = 0;
|
||||
}
|
||||
|
||||
void DvdRipper::readFileSectors() {
|
||||
dvdcss_title(this->driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar);
|
||||
|
||||
sectorInfo* sectorInf = Li::Dvd::TitleKey::GetSectorInfo(this->sectorsReadSoFar);
|
||||
this->fileRemain = (sectorInf->endSector - sectorInf->startSector);
|
||||
|
||||
if ((this->sectorsReadSoFar + this->fileRemain) > this->drive->Sectors()) {
|
||||
this->fileRemain = (this->drive->Sectors() - this->sectorsReadSoFar);
|
||||
}
|
||||
|
||||
this->fileReadSoFar = 0;
|
||||
|
||||
do {
|
||||
int toRead = this->sectorsAtOnce;
|
||||
if ((this->fileReadSoFar + toRead) > this->fileRemain) {
|
||||
toRead = this->fileRemain - this->fileReadSoFar;
|
||||
}
|
||||
int numRead = dvdcss_read(driveIoCtl->GetDvdCssHandle(), this->tmpBuffer, toRead, DVDCSS_READ_DECRYPT);
|
||||
|
||||
if (dvdcss_was_error(driveIoCtl->GetDvdCssHandle())) {
|
||||
this->errorMsg = std::string(dvdcss_error(driveIoCtl->GetDvdCssHandle()));
|
||||
}
|
||||
if (numRead <= 0) {
|
||||
numRead = read1SectorATimeSkippingBadSectors(toRead);
|
||||
}
|
||||
|
||||
iso->write((const char*)this->tmpBuffer, DVDCSS_BLOCK_SIZE * numRead);
|
||||
|
||||
this->sectorsReadSoFar += numRead;
|
||||
this->fileReadSoFar += numRead;
|
||||
|
||||
} while ((this->fileReadSoFar < this->fileRemain) && this->keepRunning);
|
||||
|
||||
this->inFile = Li::Dvd::TitleKey::IsSectorInFile(this->sectorsReadSoFar);
|
||||
this->fileReadSoFar = 0;
|
||||
this->nonFileReadSoFar = 0;
|
||||
}
|
||||
|
||||
void DvdRipper::ripThread() {
|
||||
|
||||
|
||||
this->sectorsReadSoFar = 0;
|
||||
|
||||
Li::Dvd::TitleKey::GetTitleKeys(driveIoCtl->GetDvdCssHandle());
|
||||
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), 0, DVDCSS_SEEK_KEY);
|
||||
this->inFile = Li::Dvd::TitleKey::IsSectorInFile(this->sectorsReadSoFar);
|
||||
|
||||
do {
|
||||
if (this->inFile)
|
||||
this->readFileSectors();
|
||||
else
|
||||
this->readNonFileSectors();
|
||||
|
||||
} while (this->sectorsReadSoFar < this->drive->Sectors() && this->keepRunning);
|
||||
|
||||
this->done = true;
|
||||
}
|
||||
|
||||
DvdRipper::DvdRipper(Li::Scsi::OpticalDrive* opticalDrive, std::string outputISO, uint32_t sectorsAtOnce) {
|
||||
this->drive = opticalDrive;
|
||||
this->outputPath = outputISO;
|
||||
this->sectorsAtOnce = sectorsAtOnce;
|
||||
|
||||
this->sectorsReadSoFar = 0;
|
||||
|
||||
this->fileReadSoFar = 0;
|
||||
this->fileRemain = 0;
|
||||
|
||||
this->nonFileReadSoFar = 0;
|
||||
this->nonFileRemain = 0;
|
||||
|
||||
this->inFile = false;
|
||||
this->done = false;
|
||||
this->error = false;
|
||||
this->errorMsg = "";
|
||||
this->keepRunning = false;
|
||||
|
||||
this->ripinThread = nullptr;
|
||||
this->tmpBuffer = new uint8_t[DVDCSS_BLOCK_SIZE * this->sectorsAtOnce];
|
||||
}
|
||||
|
||||
DvdRipper::~DvdRipper() {
|
||||
delete this->tmpBuffer;
|
||||
|
||||
if (this->ripinThread != nullptr) {
|
||||
this->EndRip();
|
||||
}
|
||||
if (this->iso != nullptr) {
|
||||
if (this->iso->is_open())
|
||||
this->iso->close();
|
||||
delete this->iso;
|
||||
}
|
||||
}
|
||||
|
||||
void DvdRipper::StartRip(uint32_t driveSpeed) {
|
||||
|
||||
this->driveIoCtl = new Li::Scsi::IoCtl(this->drive->DrivePath());
|
||||
this->driveIoCtl->AllowReadingPastDisc();
|
||||
this->driveIoCtl->SetDriveSpeed(driveSpeed, driveSpeed);
|
||||
this->driveIoCtl->ExclusiveLockDrive();
|
||||
this->iso = new std::ofstream(this->outputPath, std::ios::binary);
|
||||
this->keepRunning = true;
|
||||
|
||||
this->ripinThread = new std::thread(&DvdRipper::ripThread, this);
|
||||
|
||||
}
|
||||
|
||||
void DvdRipper::EndRip() {
|
||||
this->done = false;
|
||||
this->error = false;
|
||||
this->errorMsg = "";
|
||||
|
||||
this->sectorsReadSoFar = 0;
|
||||
this->fileReadSoFar = 0;
|
||||
this->keepRunning = false;
|
||||
this->ripinThread->join();
|
||||
|
||||
delete this->driveIoCtl;
|
||||
delete this->ripinThread;
|
||||
this->ripinThread = nullptr;
|
||||
iso->close();
|
||||
delete iso;
|
||||
|
||||
this->iso = nullptr;
|
||||
this->driveIoCtl->ExclusiveUnlockDrive();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef _LI_DVDRIPPER
|
||||
#define _LI_DVDRIPPER 1
|
||||
#include <iostream>
|
||||
#include <dvdcss.h>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "../Scsi/IoCtl.hpp"
|
||||
#include "../Scsi/OpticalDrive.hpp"
|
||||
|
||||
namespace Li::Dvd {
|
||||
class DvdRipper {
|
||||
private:
|
||||
bool error;
|
||||
bool done;
|
||||
std::string errorMsg;
|
||||
|
||||
bool inFile;
|
||||
uint32_t fileReadSoFar;
|
||||
uint32_t fileRemain;
|
||||
|
||||
uint32_t nonFileReadSoFar;
|
||||
uint32_t nonFileRemain;
|
||||
|
||||
|
||||
uint32_t sectorsAtOnce;
|
||||
uint32_t sectorsReadSoFar;
|
||||
|
||||
std::string outputPath;
|
||||
std::thread* ripinThread;
|
||||
|
||||
bool keepRunning;
|
||||
|
||||
std::ofstream* iso;
|
||||
uint8_t* tmpBuffer;
|
||||
|
||||
Li::Scsi::IoCtl* driveIoCtl;
|
||||
Li::Scsi::OpticalDrive* drive;
|
||||
void ripThread();
|
||||
void readNonFileSectors();
|
||||
void readFileSectors();
|
||||
int read1SectorATimeSkippingBadSectors(int toRead);
|
||||
public:
|
||||
DvdRipper(Li::Scsi::OpticalDrive* opticalDrive, std::string outputISO, uint32_t sectorsAtOnce);
|
||||
~DvdRipper();
|
||||
|
||||
uint32_t SectorsReadSoFar();
|
||||
uint32_t FileReadSoFar();
|
||||
float PercentDone();
|
||||
std::string OutputPath();
|
||||
|
||||
uint32_t FileSoFar();
|
||||
uint32_t FileLen();
|
||||
|
||||
bool Done();
|
||||
bool Error();
|
||||
std::string ErrorMessage();
|
||||
|
||||
void StartRip(uint32_t driveSpeed);
|
||||
void EndRip();
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
#include "TitleKey.hpp"
|
||||
#include <lib9660.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../Utils.hpp"
|
||||
|
||||
namespace Li::Dvd {
|
||||
|
||||
|
||||
static std::vector<sectorInfo*> sectorsList;
|
||||
static dvdcss_t drv;
|
||||
|
||||
bool TitleKey::readSector(l9660_fs* fs, void* buf, uint32_t sector) {
|
||||
dvdcss_seek(drv, sector, DVDCSS_SEEK_KEY);
|
||||
dvdcss_read(drv, buf, 1, DVDCSS_READ_DECRYPT);
|
||||
|
||||
return !dvdcss_was_error(drv);
|
||||
}
|
||||
|
||||
bool TitleKey::IsSectorInFile(uint32_t currentSector) {
|
||||
for (sectorInfo* inf : sectorsList) {
|
||||
if (currentSector >= inf->startSector && currentSector < inf->endSector)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t TitleKey::GetDistanceToNextFile(uint32_t currentSector) {
|
||||
|
||||
uint32_t lowestDistance = -1;
|
||||
for (sectorInfo* inf : sectorsList) {
|
||||
if (currentSector >= inf->startSector && currentSector < inf->endSector)
|
||||
return 0;
|
||||
|
||||
uint32_t distance = inf->startSector - currentSector;
|
||||
if (distance < 0) continue;
|
||||
|
||||
if (distance < lowestDistance) {
|
||||
lowestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return lowestDistance;
|
||||
|
||||
}
|
||||
|
||||
sectorInfo* TitleKey::GetSectorInfo(uint32_t currentSector) {
|
||||
|
||||
for (sectorInfo* inf : sectorsList) {
|
||||
if (currentSector >= inf->startSector && currentSector < inf->endSector) {
|
||||
return inf;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
void readDir(l9660_dir* dir) {
|
||||
while (true) {
|
||||
l9660_dirent* dent;
|
||||
l9660_status status = l9660_readdir(dir, &dent);
|
||||
|
||||
if (dent == nullptr)
|
||||
break;
|
||||
|
||||
if (dent->name_len < 2)
|
||||
continue;
|
||||
|
||||
if ((dent->flags & DENT_ISDIR) != 0) {
|
||||
l9660_dir ndir;
|
||||
l9660_opendirat(&ndir, dir, dent->name);
|
||||
readDir(&ndir);
|
||||
}
|
||||
else if (TitleKey::GetSectorInfo(*(uint32_t*)dent->size.le) == nullptr) {
|
||||
sectorInfo* file = new sectorInfo();
|
||||
|
||||
file->startSector = *(uint32_t*)dent->sector.le;
|
||||
file->endSector = file->startSector + (*(uint32_t*)dent->size.le / DVDCSS_BLOCK_SIZE);
|
||||
|
||||
sectorsList.push_back(file);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<sectorInfo*> TitleKey::GetTitleKeys(dvdcss_t drive) {
|
||||
drv = drive;
|
||||
sectorsList = std::vector<sectorInfo*>();
|
||||
|
||||
l9660_dir rootDir;
|
||||
l9660_fs isoFs;
|
||||
l9660_status status;
|
||||
|
||||
status = l9660_openfs(&isoFs, TitleKey::readSector);
|
||||
status = l9660_fs_open_root(&rootDir, &isoFs);
|
||||
readDir(&rootDir);
|
||||
|
||||
return sectorsList;
|
||||
}
|
||||
|
||||
void TitleKey::FreeMemory() {
|
||||
for (sectorInfo* inf : sectorsList) {
|
||||
delete inf;
|
||||
}
|
||||
|
||||
sectorsList.clear();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _LI_TITLEKEY
|
||||
#define _LI_TITLEKEY 1
|
||||
#include <dvdcss.h>
|
||||
#include <lib9660.h>
|
||||
#include <vector>
|
||||
|
||||
typedef struct sectorInfo {
|
||||
uint32_t startSector;
|
||||
uint32_t endSector;
|
||||
} sectorInfo;
|
||||
|
||||
namespace Li::Dvd {
|
||||
class TitleKey {
|
||||
private:
|
||||
static bool readSector(l9660_fs* fs, void* buf, uint32_t sector);
|
||||
public:
|
||||
static std::vector<sectorInfo*> GetTitleKeys(dvdcss_t drive);
|
||||
static uint32_t GetDistanceToNextFile(uint32_t currentSector);
|
||||
static bool IsSectorInFile(uint32_t currentSector);
|
||||
static sectorInfo* GetSectorInfo(uint32_t currentSector);
|
||||
static void FreeMemory();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,3 +1,4 @@
|
|||
#include "DumpDVD.hpp"
|
||||
#include <imgui.h>
|
||||
#include <SDL.h>
|
||||
|
||||
|
@ -8,18 +9,17 @@
|
|||
|
||||
#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"
|
||||
#include "../Dvd/DvdRipper.hpp"
|
||||
#include "../Dvd/TitleKey.hpp"
|
||||
|
||||
|
||||
namespace Li::Gui {
|
||||
|
@ -29,20 +29,14 @@ namespace Li::Gui {
|
|||
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();
|
||||
|
@ -56,54 +50,6 @@ namespace Li::Gui {
|
|||
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);
|
||||
drive->ExclusiveLockDrive();
|
||||
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;
|
||||
this->errorMsg = std::string(dvdcss_error(drive->GetDvdCssHandle()));
|
||||
break;
|
||||
}
|
||||
|
||||
iso->write((const char*)buffer, DVDCSS_BLOCK_SIZE * numRead);
|
||||
this->sectorsReadSoFar += numRead;
|
||||
|
||||
} while (this->sectorsReadSoFar < totalSectors && this->imRippinIt);
|
||||
|
||||
|
||||
drive->ExclusiveUnlockDrive();
|
||||
iso->close();
|
||||
this->done = true;
|
||||
delete buffer;
|
||||
delete drive;
|
||||
delete iso;
|
||||
}
|
||||
|
||||
void DumpDVD::pollDrivesThread() {
|
||||
while (this->keepPolling) {
|
||||
if ( (this->counter % (60 * 10)) == 0) {
|
||||
|
@ -167,18 +113,25 @@ namespace Li::Gui {
|
|||
this->pollDrives->join();
|
||||
delete this->pollDrives;
|
||||
|
||||
this->pollDrives = new std::thread(&DumpDVD::ripDiscThread, this);
|
||||
std::vector<uint32_t>* speeds = this->GetCurrentSelectedDrive()->SupportedSpeeds();
|
||||
uint32_t speed = 0xFFFF;
|
||||
if (this->selectedDriveSpeed < speeds->size()) {
|
||||
speed = speeds->at(this->selectedDriveSpeed);
|
||||
}
|
||||
|
||||
this->dvdRipper = new Li::Dvd::DvdRipper(this->GetCurrentSelectedDrive(), std::string(this->outputFile), this->sectorsAtOnce);
|
||||
this->dvdRipper->StartRip(speed);
|
||||
|
||||
this->imRippinIt = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDVD::endRipAndGoBackToMenu() {
|
||||
this->done = false;
|
||||
this->dvdRipper->EndRip();
|
||||
delete this->dvdRipper;
|
||||
|
||||
this->imRippinIt = false;
|
||||
this->reset();
|
||||
this->sectorsReadSoFar = 0;
|
||||
this->counter = 0;
|
||||
this->pollDrives->join();
|
||||
|
||||
this->keepPolling = true;
|
||||
this->drivesList = Li::Scsi::OpticalDrive::ListOpticalDrives();
|
||||
|
@ -189,28 +142,29 @@ namespace Li::Gui {
|
|||
|
||||
void DumpDVD::showRippingStatus() {
|
||||
ImGui::SeparatorText("Status");
|
||||
float percentage = (((float)this->sectorsReadSoFar / (float)this->GetCurrentSelectedDrive()->Sectors()));
|
||||
ImGui::Text("Copying Disc ... ", (int)percentage);
|
||||
ImGui::Text("Copying Disc ... ");
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar(percentage);
|
||||
ImGui::ProgressBar(this->dvdRipper->PercentDone());
|
||||
|
||||
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("Sector %i / %i", this->dvdRipper->SectorsReadSoFar(), this->GetCurrentSelectedDrive()->Sectors());
|
||||
ImGui::Text("File: %i / %i", this->dvdRipper->FileReadSoFar(), this->dvdRipper->FileLen());
|
||||
|
||||
uint64_t szSoFar = (uint64_t)(this->dvdRipper->SectorsReadSoFar()) * (uint64_t)(DVDCSS_BLOCK_SIZE);
|
||||
uint64_t szTotal = (uint64_t)(this->GetCurrentSelectedDrive()->Sectors()) * (uint64_t)(DVDCSS_BLOCK_SIZE);
|
||||
|
||||
ImGui::Text("Total %s / %s", Utils::HumanReadableByteStr(szSoFar).c_str(), Utils::HumanReadableByteStr(szTotal).c_str());
|
||||
ImGui::SeparatorText("Output");
|
||||
ImGui::Text("Output file: \"%s\"", this->outputFile);
|
||||
|
||||
if (ImGui::Button("Cancel")) {
|
||||
this->endRipAndGoBackToMenu();
|
||||
std::filesystem::remove(std::string(this->outputFile));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->done) {
|
||||
if (!this->error) {
|
||||
ImGui::Begin("Complete", &done, this->windowFlags);
|
||||
if (this->dvdRipper->Done()) {
|
||||
if (!this->dvdRipper->Error()) {
|
||||
ImGui::Begin("Complete", &this->imRippinIt, ImGuiWindowFlags_NoCollapse);
|
||||
ImGui::Text("ISO file was created successfully.");
|
||||
if (ImGui::Button("OK")) {
|
||||
this->endRipAndGoBackToMenu();
|
||||
|
@ -218,8 +172,8 @@ namespace Li::Gui {
|
|||
ImGui::End();
|
||||
}
|
||||
else {
|
||||
ImGui::Begin("Error", &done, this->windowFlags);
|
||||
ImGui::Text("Error occured when creating an ISO\n\"%s\"", this->errorMsg.c_str());
|
||||
ImGui::Begin("Error", &this->imRippinIt, ImGuiWindowFlags_NoCollapse);
|
||||
ImGui::Text("Error occured when creating an ISO\n\"%s\"", this->dvdRipper->ErrorMessage().c_str());
|
||||
if (ImGui::Button("OK")) {
|
||||
this->endRipAndGoBackToMenu();
|
||||
std::filesystem::remove(std::string(this->outputFile));
|
||||
|
@ -309,7 +263,7 @@ namespace Li::Gui {
|
|||
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Appearing);
|
||||
ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize, ImGuiCond_Appearing);
|
||||
|
||||
ImGui::Begin("DVD Dumper", NULL, windowFlags);
|
||||
ImGui::Begin("DVD Dumper", NULL, ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
if (this->imRippinIt)
|
||||
{
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
#define _LI_DUMP_DVD_H 1
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include "../Scsi/IoCtl.hpp"
|
||||
#include "../Scsi/OpticalDrive.hpp"
|
||||
#include "../Dvd/DvdRipper.hpp"
|
||||
|
||||
namespace Li::Gui {
|
||||
|
||||
|
@ -18,22 +19,17 @@ namespace Li::Gui {
|
|||
|
||||
std::mutex* lock;
|
||||
|
||||
bool error;
|
||||
bool done;
|
||||
std::string errorMsg;
|
||||
uint64_t sectorsReadSoFar;
|
||||
int sectorsAtOnce;
|
||||
|
||||
bool discInserted;
|
||||
int selectedDrive;
|
||||
ImGuiWindowFlags windowFlags;
|
||||
int selectedDriveSpeed;
|
||||
uint32_t counter;
|
||||
char outputFile[0x8000];
|
||||
|
||||
|
||||
std::vector<Li::Scsi::OpticalDrive*>* drivesList;
|
||||
std::thread* pollDrives;
|
||||
|
||||
Li::Dvd::DvdRipper* dvdRipper;
|
||||
|
||||
void ripDiscThread();
|
||||
void pollDrivesThread();
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace Li::Scsi {
|
|||
return this->drivePath;
|
||||
}
|
||||
|
||||
uint64_t OpticalDrive::Sectors() {
|
||||
uint32_t OpticalDrive::Sectors() {
|
||||
return this->sectors;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Li::Scsi {
|
|||
|
||||
bool discInDrive;
|
||||
std::vector<uint32_t>* supportedSpeeds;
|
||||
uint64_t sectors;
|
||||
uint32_t sectors;
|
||||
|
||||
void getDriveInformation(std::string drv);
|
||||
public:
|
||||
|
@ -20,7 +20,7 @@ namespace Li::Scsi {
|
|||
std::vector<uint32_t>* SupportedSpeeds();
|
||||
std::string DrivePath();
|
||||
std::string VolumeName();
|
||||
uint64_t Sectors();
|
||||
uint32_t Sectors();
|
||||
bool DiscInDrive();
|
||||
|
||||
static std::vector<OpticalDrive*>* ListOpticalDrives();
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
#include <string>
|
||||
|
||||
namespace Li {
|
||||
bool Utils::CompareStringCaseInsensitive(std::string input, std::string compare) {
|
||||
unsigned int sz = input.size();
|
||||
if (compare.size() != sz)
|
||||
return false;
|
||||
for (unsigned int i = 0; i < sz; ++i)
|
||||
if (tolower(input[i]) != tolower(compare[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string Utils::HumanReadableByteStr(uint64_t bytes)
|
||||
{
|
||||
const char* suffix[5] = { "B", "KB", "MB", "GB", "TB" };
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Li {
|
|||
class Utils {
|
||||
public:
|
||||
static std::string HumanReadableByteStr(uint64_t bytes);
|
||||
static bool CompareStringCaseInsensitive(std::string input, std::string compare);
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
SubDir LIB9660_TOP ;
|
||||
SubDirCcFlags -std=c99 $(LIB9660_OPTS) ;
|
||||
|
||||
Library lib9660 : lib9660.c ;
|
|
@ -0,0 +1,158 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="lib9660.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lib9660.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{7f404ded-08ff-4092-97ef-0f63c5788dd2}</ProjectGuid>
|
||||
<RootNamespace>Lib9660</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)lib\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<OutputFile>$(SolutionDir)lib\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="lib9660.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lib9660.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>true</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,28 @@
|
|||
.POSIX:
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .c
|
||||
.PHONY: all clean install
|
||||
|
||||
PREFIX = /usr/local
|
||||
CFLAGS = -DL9660_HAVE_STDIO -g -DDEBUG
|
||||
|
||||
OBJS := lib9660.o
|
||||
ALL := lib9660.a tb9660
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
lib9660.a: $(OBJS)
|
||||
ar cru lib9660.a $(OBJS)
|
||||
|
||||
tb9660: tb9660.c lib9660.a
|
||||
$(CC) -g -o tb9660 tb9660.c lib9660.a $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm $(ALL) $(OBJS)
|
||||
|
||||
install:
|
||||
install -m644 lib9660.a $(DESTDIR)$(PREFIX)/lib
|
||||
install -m644 lib9660.h $(DESTDIR)$(PREFIX)/include
|
|
@ -0,0 +1,53 @@
|
|||
# lib9660 - a simple implementation of the ISO 9660 file system
|
||||
|
||||
lib9660 is a simple implementation of the ISO 9660 file system, as used on CD.
|
||||
It does not perform any dynamic memory allocations or depend upon any
|
||||
complicated standard library routines (actually all it requires is memcmp and
|
||||
memcpy). It provides a reasonable facsimilie of the standard POSIX file
|
||||
descriptor I/O API.
|
||||
|
||||
lib9660 is re-entrant; it is safe to use it from multiple threads, provided you
|
||||
do not access the same file from multiple threads (note that for these purposes
|
||||
the openat and opendirat functions count as accessing the passed parent file)
|
||||
|
||||
## Usage notes
|
||||
l9660_dir is simply a wrapper for l9660_file. You may use them interchangably if
|
||||
necessary to save memory (note that this will require casting). The distinct
|
||||
types are provided purely for type checking.
|
||||
|
||||
You can pass the same file/directory pointer for both child and parent
|
||||
parameters of l9660_open(dir)at. This can be useful in memory constrained
|
||||
environments.
|
||||
|
||||
l9660_read will not perform a read from the underlying device as long as the
|
||||
request can be answered from its' internal buffer. Be prepared for short reads.
|
||||
|
||||
lib9660_open(dir)at use lib9660_readdir internally. Remember to save and
|
||||
restore your seek position if that will be necessary.
|
||||
|
||||
## Tuning parameters
|
||||
### L9660_SINGLEBUFFER
|
||||
By default, lib9660 maintains a buffer per open file. This means each file (and
|
||||
directory) consumes just over 2kB of RAM for the buffer and state information.
|
||||
|
||||
If you are memory constrained, you can build with L9660_SINGLEBUFFER (make sure
|
||||
it is also defined in any files which include lib9660.h), which causes lib9660
|
||||
to instead use a single common buffer. lib9660 will now consume a constant
|
||||
2kB of RAM for this buffer, instead of 2kB per file.
|
||||
|
||||
The cost of this is slightly reduced performance; if you alternate between
|
||||
reading multiple files, then each time you change file that file's buffer must
|
||||
be reloaded. Additionally, this makes lib9660 no longer thread safe.
|
||||
|
||||
### L9660_HAVE_STDIO
|
||||
If your system has stdio.h and it defines SEEK_[SET,CUR,END], then lib9660 will
|
||||
use those definitions for l9660_seek. Otherwise, it will use its' own
|
||||
definitions of L9660_SEEK_[SET,CUR,END].
|
||||
|
||||
### DEBUG
|
||||
If you build l9660.c with DEBUG defined, then this will enable some library
|
||||
debugging features. Most notably, if L9660_DEBUG is set in the environment,
|
||||
then all directory entries processed (by the open[dir]at functions) will be
|
||||
dumped to stdout.
|
||||
|
||||
This requires a functioning printf and getenv. You probably don't need it
|
|
@ -0,0 +1,336 @@
|
|||
/* lib9660: a simple ISO9660 reader library especially suited to embedded
|
||||
* systems
|
||||
*
|
||||
* Copyright © 2014, Owen Shepherd
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice appears in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "lib9660.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef L9660_HAVE_STDIO
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#define SEEK_END L9660_SEEK_END
|
||||
#define SEEK_SET L9660_SEEK_SET
|
||||
#define SEEK_CUR L9660_SEEK_CUR
|
||||
#endif
|
||||
|
||||
#define DENT_EXISTS (1 << 0)
|
||||
#define DENT_ISDIR (1 << 1)
|
||||
#define DENT_ASSOCIATED (1 << 2)
|
||||
#define DENT_RECORD (1 << 3)
|
||||
#define DENT_PROTECTION (1 << 4)
|
||||
#define DENT_MULTIEXTENT (1 << 5)
|
||||
|
||||
#define PVD(vdesc) ((l9660_vdesc_primary*)(vdesc))
|
||||
|
||||
#ifdef L9660_BIG_ENDIAN
|
||||
#define READ16(v) (((v).be[1]) | ((v).be[0] << 8))
|
||||
#define READ32(v) (((v).be[3]) | ((v).be[2] << 8) | ((v).be[1]) << 16 | ((v).be[0] << 24))
|
||||
#else
|
||||
#define READ16(v) (((v).le[0]) | ((v).le[1] << 8))
|
||||
#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24))
|
||||
#endif
|
||||
|
||||
#ifndef L9660_SINGLEBUFFER
|
||||
#define HAVEBUFFER(f) (true)
|
||||
#define BUF(f) ((f)->buf)
|
||||
#else
|
||||
#define HAVEBUFFER(f) ((f) == last_file)
|
||||
#define BUF(f) (gbuf)
|
||||
static l9660_file *last_file;
|
||||
static char gbuf[2048];
|
||||
#endif
|
||||
|
||||
static char *strchrnul(const char *s, int c)
|
||||
{
|
||||
while (*s) {
|
||||
if((*s++) == c)
|
||||
break;
|
||||
}
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
static inline uint16_t fsectoff(l9660_file *f)
|
||||
{
|
||||
return f->position % 2048;
|
||||
}
|
||||
|
||||
static inline uint32_t fsector(l9660_file *f)
|
||||
{
|
||||
return f->position / 2048;
|
||||
}
|
||||
|
||||
static inline uint32_t fnextsectpos(l9660_file *f)
|
||||
{
|
||||
return (f->position + 2047) & ~2047;
|
||||
}
|
||||
|
||||
l9660_status l9660_openfs(
|
||||
l9660_fs *fs,
|
||||
bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector))
|
||||
{
|
||||
fs->read_sector = read_sector;
|
||||
|
||||
#ifndef L9660_SINGLEBUFFER
|
||||
l9660_vdesc_primary *pvd = PVD(&fs->pvd);
|
||||
#else
|
||||
last_file = NULL;
|
||||
l9660_vdesc_primary *pvd = PVD(gbuf);
|
||||
#endif
|
||||
uint32_t idx = 0x10;
|
||||
for (;;) {
|
||||
// Read next sector
|
||||
if (!read_sector(fs, pvd, idx))
|
||||
return L9660_EIO;
|
||||
|
||||
// Validate magic
|
||||
if (memcmp(pvd->hdr.magic, "CD001", 5) != 0)
|
||||
return L9660_EBADFS;
|
||||
|
||||
if (pvd->hdr.type == 1)
|
||||
break; // Found PVD
|
||||
else if(pvd->hdr.type == 255)
|
||||
return L9660_EBADFS;
|
||||
}
|
||||
|
||||
#ifdef L9660_SINGLEBUFFER
|
||||
memcpy(&fs->root_dir_ent, &pvd->root_dir_ent, pvd->root_dir_ent.length);
|
||||
#endif
|
||||
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs)
|
||||
{
|
||||
l9660_file *f = &dir->file;
|
||||
#ifndef L9660_SINGLEBUFFER
|
||||
l9660_dirent *dirent = &PVD(&fs->pvd)->root_dir_ent;
|
||||
#else
|
||||
l9660_dirent *dirent = &fs->root_dir_ent;
|
||||
#endif
|
||||
|
||||
f->fs = fs;
|
||||
f->first_sector = READ32(dirent->sector);
|
||||
f->length = READ32(dirent->size);
|
||||
f->position = 0;
|
||||
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
static l9660_status buffer(l9660_file *f)
|
||||
{
|
||||
#ifdef L9660_SINGLEBUFFER
|
||||
last_file = f;
|
||||
#endif
|
||||
if (!f->fs->read_sector(f->fs, BUF(f), f->first_sector + f->position / 2048))
|
||||
return L9660_EIO;
|
||||
else
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
static l9660_status prebuffer(l9660_file *f)
|
||||
{
|
||||
if (!HAVEBUFFER(f) || (f->position % 2048) == 0)
|
||||
return buffer(f);
|
||||
else return L9660_OK;
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
static void print_dirent(l9660_dirent *dent)
|
||||
{
|
||||
if (!getenv("L9660_DEBUG"))
|
||||
return;
|
||||
|
||||
printf("| ---- dirent\n");
|
||||
printf("| length %d\n", dent->length);
|
||||
printf("| xattr_length %d\n", dent->xattr_length);
|
||||
printf("| sector %u\n", READ32(dent->sector));
|
||||
printf("| size %u\n", READ32(dent->size));
|
||||
printf("| name \"%.*s\"\n", dent->name_len, dent->name);
|
||||
printf("| ---- end dirent\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char *name, bool isdir)
|
||||
{
|
||||
l9660_status rv;
|
||||
l9660_dirent *dent = NULL;
|
||||
if ((rv = l9660_seekdir(parent, 0))) return rv;
|
||||
|
||||
do {
|
||||
const char *seg = name;
|
||||
name = strchrnul(name, '/');
|
||||
size_t seglen = name - seg;
|
||||
|
||||
/* ISO9660 stores '.' as '\0' */
|
||||
if (seglen == 1 && *seg == '.')
|
||||
seg = "\0";
|
||||
|
||||
/* ISO9660 stores ".." as '\1' */
|
||||
if (seglen == 2 && seg[0] == '.' && seg[1] == '.') {
|
||||
seg = "\1";
|
||||
seglen = 1;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if ((rv = l9660_readdir(parent, &dent)))
|
||||
return rv;
|
||||
|
||||
/* EOD */
|
||||
if (!dent)
|
||||
return L9660_ENOENT;
|
||||
|
||||
#ifdef DEBUG
|
||||
print_dirent(dent);
|
||||
#endif
|
||||
|
||||
/* wrong length */
|
||||
if (seglen > dent->name_len)
|
||||
continue;
|
||||
|
||||
/* check name */
|
||||
if (memcmp(seg, dent->name, seglen) != 0)
|
||||
continue;
|
||||
|
||||
/* check for a revision tag */
|
||||
if (dent->name_len > seglen && dent->name[seglen] != ';')
|
||||
continue;
|
||||
|
||||
/* all tests pass */
|
||||
break;
|
||||
}
|
||||
|
||||
child->fs = parent->file.fs;
|
||||
child->first_sector = READ32(dent->sector) + dent->xattr_length;
|
||||
child->length = READ32(dent->size);
|
||||
child->position = 0;
|
||||
|
||||
if (*name && (dent->flags & DENT_ISDIR) != 0)
|
||||
return L9660_ENOTDIR;
|
||||
|
||||
parent = (l9660_dir*) child;
|
||||
} while(*name);
|
||||
|
||||
if (isdir) {
|
||||
if ((dent->flags & DENT_ISDIR) == 0)
|
||||
return L9660_ENOTDIR;
|
||||
} else {
|
||||
if ((dent->flags & DENT_ISDIR) != 0)
|
||||
return L9660_ENOTFILE;
|
||||
}
|
||||
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
l9660_status l9660_opendirat(l9660_dir *dir, l9660_dir *parent, const char *path)
|
||||
{
|
||||
return openat_raw(&dir->file, parent, path, true);
|
||||
}
|
||||
|
||||
static inline unsigned aligneven(unsigned v) {
|
||||
return v + (v & 1);
|
||||
}
|
||||
|
||||
l9660_status l9660_readdir(l9660_dir *dir, l9660_dirent **pdirent)
|
||||
{
|
||||
l9660_status rv;
|
||||
l9660_file *f = &dir->file;
|
||||
|
||||
rebuffer:
|
||||
if(f->position >= f->length) {
|
||||
*pdirent = NULL;
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
if ((rv = prebuffer(f)))
|
||||
return rv;
|
||||
|
||||
char *off = BUF(f) + fsectoff(f);
|
||||
if (*off == 0) {
|
||||
// Padded end of sector
|
||||
f->position = fnextsectpos(f);
|
||||
goto rebuffer;
|
||||
}
|
||||
|
||||
l9660_dirent *dirent = (l9660_dirent*) off;
|
||||
f->position += aligneven(dirent->length);
|
||||
|
||||
*pdirent = dirent;
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
l9660_status l9660_openat(l9660_file *child, l9660_dir *parent, const char * name)
|
||||
{
|
||||
return openat_raw(child, parent, name, false);
|
||||
}
|
||||
|
||||
/*! Seek the file to \p offset from \p whence */
|
||||
l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset)
|
||||
{
|
||||
l9660_status rv;
|
||||
uint32_t cursect = fsector(f);
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
f->position = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
f->position = f->position + offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
f->position = f->length - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fsector(f) != cursect && fsectoff(f) != 0) {
|
||||
if ((rv = buffer(f)))
|
||||
return rv;
|
||||
}
|
||||
|
||||
return L9660_OK;
|
||||
}
|
||||
|
||||
uint32_t l9660_tell(l9660_file *f)
|
||||
{
|
||||
return f->position;
|
||||
}
|
||||
|
||||
l9660_status l9660_read(l9660_file *f, void* buf, size_t size, size_t *read)
|
||||
{
|
||||
l9660_status rv;
|
||||
|
||||
if ((rv = prebuffer(f)))
|
||||
return rv;
|
||||
|
||||
uint16_t rem = 2048 - fsectoff(f);
|
||||
if (rem > f->length - f->position)
|
||||
rem = f->length - f->position;
|
||||
if (rem < size)
|
||||
size = rem;
|
||||
|
||||
memcpy(buf, BUF(f) + fsectoff(f), size);
|
||||
|
||||
*read = size;
|
||||
f->position += size;
|
||||
|
||||
return L9660_OK;
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
/* lib9660: a simple ISO9660 reader library especially suited to embedded
|
||||
* systems
|
||||
*
|
||||
* Copyright © 2014, Owen Shepherd
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice appears in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef LIB9660_H
|
||||
#define LIB9660_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef L9660_HAVE_STDIO
|
||||
#include <stdio.h>
|
||||
#define L9660_SEEK_END SEEK_END
|
||||
#define L9660_SEEK_SET SEEK_SET
|
||||
#define L9660_SEEK_CUR SEEK_CUR
|
||||
#else
|
||||
#define L9660_SEEK_END -1
|
||||
#define L9660_SEEK_SET 0
|
||||
#define L9660_SEEK_CUR +1
|
||||
#endif
|
||||
|
||||
#define DENT_EXISTS (1 << 0)
|
||||
#define DENT_ISDIR (1 << 1)
|
||||
#define DENT_ASSOCIATED (1 << 2)
|
||||
#define DENT_RECORD (1 << 3)
|
||||
#define DENT_PROTECTION (1 << 4)
|
||||
#define DENT_MULTIEXTENT (1 << 5)
|
||||
|
||||
/* Our error return format */
|
||||
typedef enum {
|
||||
/*! Success! */
|
||||
L9660_OK = 0,
|
||||
/*! read_sector callback returned false */
|
||||
L9660_EIO,
|
||||
/*! file system is bad */
|
||||
L9660_EBADFS,
|
||||
/*! specified name does not exist */
|
||||
L9660_ENOENT,
|
||||
/*! attempted to open a non-file (e.g. a directory) as a file */
|
||||
L9660_ENOTFILE,
|
||||
/*! attempted to open a non-directory (e.g. a file) as a directory
|
||||
* may be returned by l9660_openat if e.g. you pass path "a/b" and
|
||||
* "a" is a file
|
||||
*/
|
||||
L9660_ENOTDIR,
|
||||
} l9660_status;
|
||||
|
||||
/* ISO9660 uses big/little/dual endian integers */
|
||||
typedef struct { uint8_t le[2]; } l9660_luint16;
|
||||
typedef struct { uint8_t be[2]; } l9660_buint16;
|
||||
typedef struct { uint8_t le[2], be[2]; } l9660_duint16;
|
||||
typedef struct { uint8_t le[4]; } l9660_luint32;
|
||||
typedef struct { uint8_t be[4]; } l9660_buint32;
|
||||
typedef struct { uint8_t le[4], be[4]; } l9660_duint32;
|
||||
|
||||
/* Descriptor time format */
|
||||
typedef struct {
|
||||
char d[17];
|
||||
} l9660_desctime;
|
||||
|
||||
/* File time format */
|
||||
typedef struct {
|
||||
char d[7];
|
||||
} l9660_filetime;
|
||||
|
||||
/* Directory entry */
|
||||
typedef struct {
|
||||
uint8_t length;
|
||||
uint8_t xattr_length;
|
||||
l9660_duint32 sector;
|
||||
l9660_duint32 size;
|
||||
l9660_filetime time;
|
||||
uint8_t flags;
|
||||
uint8_t unit_size;
|
||||
uint8_t gap_size;
|
||||
l9660_duint16 vol_seq_number;
|
||||
uint8_t name_len;
|
||||
char name[/*name_len*/];
|
||||
} l9660_dirent;
|
||||
|
||||
/* Volume descriptor header */
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
char magic[5];
|
||||
uint8_t version;
|
||||
} l9660_vdesc_header;
|
||||
|
||||
/* Primary volume descriptor */
|
||||
typedef struct {
|
||||
l9660_vdesc_header hdr;
|
||||
char pad0[1];
|
||||
char system_id[32];
|
||||
char volume_id[32];
|
||||
char pad1[8];
|
||||
l9660_duint32 volume_space_size;
|
||||
char pad2[32];
|
||||
l9660_duint16 volume_set_size;
|
||||
l9660_duint16 volume_seq_number;
|
||||
l9660_duint16 logical_block_size;
|
||||
l9660_duint32 path_table_size;
|
||||
l9660_luint32 path_table_le;
|
||||
l9660_luint32 path_table_opt_le;
|
||||
l9660_buint32 path_table_be;
|
||||
l9660_buint32 path_table_opt_be;
|
||||
union {
|
||||
l9660_dirent root_dir_ent;
|
||||
char pad3[34];
|
||||
};
|
||||
char volume_set_id[128];
|
||||
char data_preparer_id[128];
|
||||
char app_id[128];
|
||||
char copyright_file[38];
|
||||
char abstract_file[36];
|
||||
char bibliography_file[37];
|
||||
l9660_desctime volume_created,
|
||||
volume_modified,
|
||||
volume_expires,
|
||||
volume_effective;
|
||||
uint8_t file_structure_version;
|
||||
char pad4[1];
|
||||
char app_reserved[512];
|
||||
char reserved[653];
|
||||
} l9660_vdesc_primary;
|
||||
|
||||
/* A generic volume descriptor (i.e. 2048 bytes) */
|
||||
typedef union {
|
||||
l9660_vdesc_header hdr;
|
||||
char _bits[2048];
|
||||
} l9660_vdesc;
|
||||
|
||||
/* File system structure.
|
||||
* Stick this inside your own structure and cast/offset as appropriate to store
|
||||
* private data
|
||||
*/
|
||||
typedef struct l9660_fs {
|
||||
#ifdef L9660_SINGLEBUFFER
|
||||
union {
|
||||
l9660_dirent root_dir_ent;
|
||||
char root_dir_pad[34];
|
||||
};
|
||||
#else
|
||||
/* Sector buffer to hold the PVD */
|
||||
l9660_vdesc pvd;
|
||||
#endif
|
||||
|
||||
/* read_sector func */
|
||||
bool (*read_sector)(struct l9660_fs* fs, void* buf, uint32_t sector);
|
||||
} l9660_fs;
|
||||
|
||||
typedef struct {
|
||||
#ifndef L9660_SINGLEBUFFER
|
||||
/* single sector buffer */
|
||||
char buf[2048];
|
||||
#endif
|
||||
l9660_fs* fs;
|
||||
uint32_t first_sector;
|
||||
uint32_t position;
|
||||
uint32_t length;
|
||||
} l9660_file;
|
||||
|
||||
typedef struct {
|
||||
/* directories are mostly just files with special accessors, but we like type safetey */
|
||||
l9660_file file;
|
||||
} l9660_dir;
|
||||
|
||||
/* Open a file system, initialising *fs. */
|
||||
l9660_status l9660_openfs(
|
||||
l9660_fs* fs,
|
||||
bool (*read_sector)(l9660_fs* fs, void* buf, uint32_t sector));
|
||||
|
||||
/*void l9660_closefs(l9660_fs *fs); (nop) */
|
||||
|
||||
/*! Open the root directory */
|
||||
l9660_status l9660_fs_open_root(l9660_dir* dir, l9660_fs* fs);
|
||||
|
||||
/*! Open the subdirectory given by \p path */
|
||||
l9660_status l9660_opendirat(l9660_dir* dir, l9660_dir* parent, const char* path);
|
||||
/*! Returns the next directory entry. If end-of-directory is reached, *dirent is
|
||||
* set to NULL. */
|
||||
l9660_status l9660_readdir(l9660_dir* dir, l9660_dirent** dirent);
|
||||
|
||||
#define l9660_seekdir(dir, pos) (l9660_seek(&(dir)->file, L9660_SEEK_SET, (pos)))
|
||||
#define l9660_telldir(dir) (l9660_tell(&(dir)->file))
|
||||
|
||||
/*! Open the file given by \p path in \p parent */
|
||||
l9660_status l9660_openat(l9660_file* file, l9660_dir* parent, const char* path);
|
||||
|
||||
/*! Read \p size bytes into \p buf. The number of bytes read will be returned in
|
||||
* \p *read. May be less than \p size (but only 0 on EOF)
|
||||
*/
|
||||
l9660_status l9660_read(l9660_file* file, void* buf, size_t size, size_t* read);
|
||||
/*! Seek the file to \p offset from \p whence */
|
||||
l9660_status l9660_seek(l9660_file* file, int whence, int32_t offset);
|
||||
/*! Return the current position (suitable for passing to l9660_seek(file, SEEK_SET, ...)) */
|
||||
uint32_t l9660_tell(l9660_file* file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
BIN
lib/ImGui.lib
BIN
lib/ImGui.lib
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -112,7 +112,7 @@
|
|||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>$(SolutionDir)lib\</OutputFile>
|
||||
<OutputFile>$(SolutionDir)lib\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
@ -148,7 +148,7 @@
|
|||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
|
@ -172,7 +172,7 @@
|
|||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>$(SolutionDir)lib\</OutputFile>
|
||||
<OutputFile>$(SolutionDir)lib\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
|
|
|
@ -106,7 +106,9 @@ LIBDVDCSS_EXPORT const char *dvdcss_error ( const dvdcss_t );
|
|||
|
||||
LIBDVDCSS_EXPORT int dvdcss_is_scrambled ( dvdcss_t );
|
||||
|
||||
LIBDVDCSS_EXPORT int dvdcss_title(dvdcss_t dvdcss, int i_block);
|
||||
LIBDVDCSS_EXPORT int dvdcss_get_raw_fd(dvdcss_t);
|
||||
LIBDVDCSS_EXPORT int dvdcss_was_error(dvdcss_t);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -486,11 +486,24 @@ static void init_cache( dvdcss_t dvdcss )
|
|||
/* If the cache is enabled, create a DVD-specific subdirectory. */
|
||||
create_cache_subdir( dvdcss );
|
||||
}
|
||||
int dvdcss_was_error_common(dvdcss_t drive) {
|
||||
if (drive->b_errors)
|
||||
{
|
||||
drive->b_errors = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int dvdcss_get_fd_common(dvdcss_t drive) {
|
||||
return drive->i_fd;
|
||||
}
|
||||
|
||||
LIBDVDCSS_EXPORT int dvdcss_was_error(dvdcss_t drive)
|
||||
{
|
||||
return dvdcss_was_error_common(drive);
|
||||
}
|
||||
|
||||
LIBDVDCSS_EXPORT int dvdcss_get_raw_fd(dvdcss_t drive)
|
||||
{
|
||||
return dvdcss_get_fd_common(drive);
|
||||
|
|
Loading…
Reference in New Issue