150 lines
3.3 KiB
C++
150 lines
3.3 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) {
|
|
|
|
uint64_t lowestDistance = 0xffffffffffffffff;
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (lowestDistance == 0xffffffffffffffff)
|
|
return 0;
|
|
|
|
return (uint32_t)lowestDistance;
|
|
|
|
}
|
|
|
|
sectorInfo* TitleKey::GetSectorInfo(uint32_t currentSector) {
|
|
|
|
for (sectorInfo* inf : sectorsList) {
|
|
if (currentSector >= inf->startSector && currentSector < inf->endSector) {
|
|
return inf;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
sectorInfo* TitleKey::getFile(uint32_t start, uint32_t sz) {
|
|
sectorInfo* file = new sectorInfo();
|
|
file->startSector = start;
|
|
|
|
if ((sz % DVDCSS_BLOCK_SIZE) != 0) {
|
|
sz += (DVDCSS_BLOCK_SIZE - (sz % DVDCSS_BLOCK_SIZE));
|
|
}
|
|
|
|
file->endSector = (file->startSector + (sz / DVDCSS_BLOCK_SIZE));
|
|
|
|
return file;
|
|
}
|
|
|
|
void TitleKey::addFileIfExist(sectorInfo* file) {
|
|
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) && GetSectorInfo(file->startSector) == nullptr) {
|
|
sectorsList.push_back(file);
|
|
}
|
|
else {
|
|
delete file;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
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 {
|
|
addFileIfExist(getFile(*(uint32_t*)dent->sector.le, *(uint32_t*)dent->size.le));
|
|
addFileIfExist(getFile(_byteswap_ulong(*(uint32_t*)dent->sector.be), _byteswap_ulong(*(uint32_t*)dent->size.be)));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
} |