add stuff

This commit is contained in:
Li 2023-03-17 19:45:03 +13:00
parent 103bb58da3
commit f83e7addef
7 changed files with 124 additions and 94 deletions

View File

@ -1,4 +1,5 @@
#include "DvdRipper.hpp"
#include <dvdcss.h>
#include <iostream>
#include <fstream>
@ -15,16 +16,10 @@ namespace Li::Dvd {
uint32_t DvdRipper::FileSoFar() {
if (this->inFile)
return this->fileReadSoFar;
else
return this->nonFileReadSoFar;
return this->fileReadSoFar;
}
uint32_t DvdRipper::FileLen() {
if (this->inFile)
return this->fileRemain;
else
return this->nonFileRemain;
return this->fileRemain;
}
float DvdRipper::PercentDone() {
@ -33,13 +28,18 @@ namespace Li::Dvd {
uint32_t DvdRipper::SectorsReadSoFar() {
return this->sectorsReadSoFar;
}
uint32_t DvdRipper::FileReadSoFar() {
return this->fileReadSoFar;
}
std::string DvdRipper::OutputPath() {
return this->outputPath;
}
std::byte* DvdRipper::GetDiscKey() {
return this->discKey;
}
std::byte* DvdRipper::GetTitleKey() {
return this->titleKey;
}
bool DvdRipper::Done() {
return this->done;
}
@ -49,102 +49,96 @@ namespace Li::Dvd {
std::string DvdRipper::ErrorMessage() {
return this->errorMsg;
}
int DvdRipper::read1SectorATimeSkippingBadSectors(int toRead) {
memset(this->tmpBuffer, 0x00, this->sectorsAtOnce * DVDCSS_BLOCK_SIZE);
int DvdRipper::read1SectorATimeSkippingBadSectors(int toRead) {
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);
memset(this->tmpBuffer, 0x00, DVDCSS_BLOCK_SIZE);
int dataRd = dvdcss_read(driveIoCtl->GetDvdCssHandle(), this->tmpBuffer, 1, DVDCSS_READ_DECRYPT);
if (dataRd < 0) {
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar, DVDCSS_SEEK_KEY);
if (retry+1 >= 10)
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar + 1, DVDCSS_SEEK_KEY);
continue; // retry
}
else {
this->iso->write((const char*)this->tmpBuffer, DVDCSS_BLOCK_SIZE * dataRd);
break;
}
}
nmRd += 1;
this->sectorsReadSoFar += 1;
this->fileReadSoFar += 1;
if (this->sectorsReadSoFar > this->drive->Sectors()) // check if we've read the last sector ...
break;
}
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;
void DvdRipper::readSectors() {
do {
int toRead = this->sectorsAtOnce;
if ((this->nonFileReadSoFar + toRead) > this->nonFileRemain) {
toRead = this->nonFileRemain - this->nonFileReadSoFar;
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) {
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), this->sectorsAtOnce, DVDCSS_SEEK_MPEG);
numRead = read1SectorATimeSkippingBadSectors(toRead);
dvdcss_seek(driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar, DVDCSS_SEEK_KEY);
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);
else {
this->iso->write((const char*)this->tmpBuffer, DVDCSS_BLOCK_SIZE * numRead);
this->sectorsReadSoFar += numRead;
this->fileReadSoFar += numRead;
}
} while ( (this->fileReadSoFar < this->fileRemain) &&
(this->sectorsReadSoFar < this->drive->Sectors()) &&
this->keepRunning);
this->inFile = Li::Dvd::TitleKey::IsSectorInFile(this->sectorsReadSoFar);
this->fileReadSoFar = 0;
this->nonFileReadSoFar = 0;
this->fileRemain = 0;
}
void DvdRipper::readFileSectors() {
void DvdRipper::readNonFileSectors() {
dvdcss_title(this->driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar);
this->fileRemain = Li::Dvd::TitleKey::GetDistanceToNextFile(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);
}
this->readSectors();
}
iso->write((const char*)this->tmpBuffer, DVDCSS_BLOCK_SIZE * numRead);
void DvdRipper::readFileSectors() {
dvdcss_title(this->driveIoCtl->GetDvdCssHandle(), this->sectorsReadSoFar);
this->titleKey = (std::byte*)dvdcss_get_cur_titlekey(this->driveIoCtl->GetDvdCssHandle());
sectorInfo* sectorInf = Li::Dvd::TitleKey::GetSectorInfo(this->sectorsReadSoFar);
this->fileRemain = (sectorInf->endSector - sectorInf->startSector);
this->sectorsReadSoFar += numRead;
this->fileReadSoFar += numRead;
if ((this->sectorsReadSoFar + this->fileRemain) > this->drive->Sectors()) {
this->fileRemain = (this->drive->Sectors() - this->sectorsReadSoFar);
}
} while ((this->fileReadSoFar < this->fileRemain) && this->keepRunning);
this->inFile = Li::Dvd::TitleKey::IsSectorInFile(this->sectorsReadSoFar);
this->fileReadSoFar = 0;
this->nonFileReadSoFar = 0;
this->readSectors();
}
void DvdRipper::ripThread() {
this->sectorsReadSoFar = 0;
Li::Dvd::TitleKey::GetTitleKeys(driveIoCtl->GetDvdCssHandle());
@ -153,9 +147,9 @@ namespace Li::Dvd {
do {
if (this->inFile)
this->readFileSectors();
this->readFileSectors(); // read & decrypt all files (including those associated w the filesystem)
else
this->readNonFileSectors();
this->readNonFileSectors(); // read the data not associated with any file on the filesystem.
} while (this->sectorsReadSoFar < this->drive->Sectors() && this->keepRunning);
@ -172,9 +166,6 @@ namespace Li::Dvd {
this->fileReadSoFar = 0;
this->fileRemain = 0;
this->nonFileReadSoFar = 0;
this->nonFileRemain = 0;
this->inFile = false;
this->done = false;
this->error = false;
@ -182,7 +173,8 @@ namespace Li::Dvd {
this->keepRunning = false;
this->ripinThread = nullptr;
this->tmpBuffer = new uint8_t[DVDCSS_BLOCK_SIZE * this->sectorsAtOnce];
this->tmpBuffer = new std::byte[DVDCSS_BLOCK_SIZE * this->sectorsAtOnce];
}
DvdRipper::~DvdRipper() {
@ -204,6 +196,11 @@ namespace Li::Dvd {
this->driveIoCtl->AllowReadingPastDisc();
this->driveIoCtl->SetDriveSpeed(driveSpeed, driveSpeed);
this->driveIoCtl->ExclusiveLockDrive();
this->discKey = (std::byte*)dvdcss_get_cur_disckey(this->driveIoCtl->GetDvdCssHandle());
dvdcss_title(this->driveIoCtl->GetDvdCssHandle(), 0);
this->titleKey = (std::byte*)dvdcss_get_cur_titlekey(this->driveIoCtl->GetDvdCssHandle());
this->iso = new std::ofstream(this->outputPath, std::ios::binary);
this->keepRunning = true;

View File

@ -20,10 +20,6 @@ namespace Li::Dvd {
uint32_t fileReadSoFar;
uint32_t fileRemain;
uint32_t nonFileReadSoFar;
uint32_t nonFileRemain;
uint32_t sectorsAtOnce;
uint32_t sectorsReadSoFar;
@ -33,26 +29,33 @@ namespace Li::Dvd {
bool keepRunning;
std::ofstream* iso;
uint8_t* tmpBuffer;
std::byte* tmpBuffer;
std::byte* titleKey;
std::byte* discKey;
Li::Scsi::IoCtl* driveIoCtl;
Li::Scsi::OpticalDrive* drive;
void ripThread();
void readNonFileSectors();
void readFileSectors();
void readSectors();
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();
std::byte* GetTitleKey();
std::byte* GetDiscKey();
bool Done();
bool Error();
std::string ErrorMessage();

View File

@ -29,12 +29,12 @@ namespace Li::Dvd {
uint32_t TitleKey::GetDistanceToNextFile(uint32_t currentSector) {
uint32_t lowestDistance = -1;
uint32_t lowestDistance = 0xFFFFFFFF;
for (sectorInfo* inf : sectorsList) {
if (currentSector >= inf->startSector && currentSector < inf->endSector)
return 0;
uint32_t distance = inf->startSector - currentSector;
int32_t distance = (inf->startSector - currentSector);
if (distance < 0) continue;
if (distance < lowestDistance) {
@ -69,18 +69,34 @@ namespace Li::Dvd {
if (dent->name_len < 2)
continue;
uint32_t cSector = *(uint32_t*)dent->sector.le;
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) {
else if (TitleKey::GetSectorInfo(cSector) == nullptr) {
sectorInfo* file = new sectorInfo();
file->startSector = cSector;
file->startSector = *(uint32_t*)dent->sector.le;
file->endSector = file->startSector + (*(uint32_t*)dent->size.le / DVDCSS_BLOCK_SIZE);
dvdcss_title(drv, file->startSector);
char* titleKey = dvdcss_get_cur_titlekey(drv);
sectorsList.push_back(file);
// check title is encrypted ...
if (memcmp(titleKey, "\0\0\0\0\0", 5)) {
// Round to sector boundary
uint32_t sz = (*(uint32_t*)dent->size.le);
if((sz % DVDCSS_BLOCK_SIZE) != 0)
sz += (DVDCSS_BLOCK_SIZE - (sz % DVDCSS_BLOCK_SIZE));
file->endSector = (file->startSector + (sz / DVDCSS_BLOCK_SIZE));
sectorsList.push_back(file);
}
else {
delete file;
}
}
}

View File

@ -147,12 +147,24 @@ namespace Li::Gui {
ImGui::ProgressBar(this->dvdRipper->PercentDone());
ImGui::Text("Sector %i / %i", this->dvdRipper->SectorsReadSoFar(), this->GetCurrentSelectedDrive()->Sectors());
ImGui::Text("File: %i / %i", this->dvdRipper->FileReadSoFar(), this->dvdRipper->FileLen());
ImGui::Text("File: %i / %i", this->dvdRipper->FileSoFar(), 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("Content Scrambling System (CSS)");
std::byte* discKey = this->dvdRipper->GetDiscKey();
std::byte* titleKey = this->dvdRipper->GetTitleKey();
if (discKey != nullptr)
ImGui::Text("Disc Key: %02X%02X%02X%02X%02X", discKey[0], discKey[1], discKey[2], discKey[3], discKey[4]);
if (titleKey != nullptr)
ImGui::Text("Title Key: %02X%02X%02X%02X%02X", titleKey[0], titleKey[1], titleKey[2], titleKey[3], titleKey[4]);
ImGui::SeparatorText("Output");
ImGui::Text("Output file: \"%s\"", this->outputFile);

Binary file not shown.

View File

@ -106,6 +106,8 @@ LIBDVDCSS_EXPORT const char *dvdcss_error ( const dvdcss_t );
LIBDVDCSS_EXPORT int dvdcss_is_scrambled ( dvdcss_t );
LIBDVDCSS_EXPORT char* dvdcss_get_cur_disckey(dvdcss_t dvdcss);
LIBDVDCSS_EXPORT char* dvdcss_get_cur_titlekey(dvdcss_t dvdcss);
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);

View File

@ -486,7 +486,16 @@ 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) {
LIBDVDCSS_EXPORT char* dvdcss_get_cur_disckey(dvdcss_t dvdcss) {
return dvdcss->css.p_disc_key;
}
LIBDVDCSS_EXPORT char* dvdcss_get_cur_titlekey(dvdcss_t dvdcss) {
return dvdcss->css.p_title_key;
}
LIBDVDCSS_EXPORT int dvdcss_was_error(dvdcss_t drive)
{
if (drive->b_errors)
{
drive->b_errors = FALSE;
@ -495,18 +504,9 @@ int dvdcss_was_error_common(dvdcss_t drive) {
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);
return drive->i_fd;
}
/**