140 lines
3.0 KiB
C++
140 lines
3.0 KiB
C++
#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;
|
|
static int depth = 0;
|
|
|
|
|
|
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 = 0xFFFFFFFF;
|
|
for (sectorInfo* inf : sectorsList) {
|
|
if (currentSector >= inf->startSector && currentSector < inf->endSector)
|
|
return 0;
|
|
|
|
int32_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;
|
|
|
|
}
|
|
|
|
bool TitleKey::readDir(l9660_dir* dir, int depth=0) {
|
|
|
|
if (depth > 10) return false;
|
|
|
|
bool success = true;
|
|
for(int cnt = 0; cnt < 90000; ++cnt) {
|
|
if (cnt >= 90000) return false;
|
|
|
|
l9660_dirent* dent;
|
|
if (l9660_readdir(dir, &dent) != L9660_OK) return false;
|
|
|
|
if (dent == nullptr)
|
|
break;
|
|
|
|
if (dent->name_len < 2)
|
|
continue;
|
|
|
|
uint32_t cSector = *(uint32_t*)dent->sector.le;
|
|
|
|
if ((dent->flags & DENT_ISDIR) != 0) {
|
|
l9660_dir ndir;
|
|
if (l9660_opendirat(&ndir, dir, dent->name) != L9660_OK) return false;
|
|
success = readDir(&ndir, depth + 1);
|
|
}
|
|
else if (TitleKey::GetSectorInfo(cSector) == nullptr) {
|
|
sectorInfo* file = new sectorInfo();
|
|
file->startSector = cSector;
|
|
|
|
dvdcss_title(drv, file->startSector);
|
|
char* titleKey = dvdcss_get_cur_titlekey(drv);
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return success;
|
|
}
|
|
|
|
bool TitleKey::FindTitleKeys(dvdcss_t drive) {
|
|
drv = drive;
|
|
sectorsList = std::vector<sectorInfo*>();
|
|
|
|
l9660_dir rootDir;
|
|
l9660_fs isoFs;
|
|
l9660_status status;
|
|
|
|
if (l9660_openfs(&isoFs, TitleKey::readSector) == L9660_OK) {
|
|
if (l9660_fs_open_root(&rootDir, &isoFs) == L9660_OK) {
|
|
return TitleKey::readDir(&rootDir);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void TitleKey::FreeMemory() {
|
|
for (sectorInfo* inf : sectorsList) {
|
|
delete inf;
|
|
}
|
|
|
|
sectorsList.clear();
|
|
|
|
}
|
|
} |