Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ target_sources(redumper
"drive/plextor.ixx"
"drive/mediatek.ixx"
"drive/test.ixx"
"dvd/bd.ixx"
"dvd/bd_scrambler.ixx"
"dvd/css/css.ixx"
"dvd/dvd.ixx"
"dvd/dvd_dump.ixx"
Expand Down
2 changes: 1 addition & 1 deletion cd/protection.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ export int redumper_protection(Context &ctx, Options &options)

auto image_prefix = (std::filesystem::path(options.image_path) / options.image_name).generic_string();

if(std::filesystem::exists(image_prefix + ".iso") || std::filesystem::exists(image_prefix + ".sdram"))
if(std::filesystem::exists(image_prefix + ".iso") || std::filesystem::exists(image_prefix + ".sdram") || std::filesystem::exists(image_prefix + ".sbram"))
return exit_code;

std::vector<uint8_t> toc_buffer = read_vector(image_prefix + ".toc");
Expand Down
59 changes: 59 additions & 0 deletions dvd/bd.ixx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module;
#include <cstddef>
#include <cstdint>
#include <span>

export module bd;

import cd.cdrom;
import bd.scrambler;
import common;
import dvd.edc;
import utils.endian;



namespace gpsxre::bd
{

export constexpr int32_t LBA_START = -0x100000;
export constexpr int32_t LBA_IZ = -0x2000;
export constexpr uint32_t ECC_FRAMES = 0x20;


export struct DataFrame
{
uint8_t main_data[FORM1_DATA_SIZE];
uint32_t edc;


bool valid(int32_t lba) const
{
bool valid = false;

auto df = *this;
df.descramble(lba);

if(endian_swap(df.edc) == DVD_EDC().update((uint8_t *)&df, offsetof(DataFrame, edc)).final())
valid = true;

return valid;
}


void descramble(int32_t lba)
{
Scrambler::get().descramble(std::span((uint8_t *)this, sizeof(DataFrame)), lba - LBA_START);
}
};


#pragma pack(push, 1)
export struct OmniDriveDataFrame
{
DataFrame data_frame;
uint8_t unknown[18];
};
#pragma pack(pop)

}
51 changes: 51 additions & 0 deletions dvd/bd_scrambler.ixx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module;
#include <climits>
#include <cstdint>
#include <span>

export module bd.scrambler;



namespace gpsxre::bd
{

export class Scrambler
{
public:
static const Scrambler &get()
{
static const Scrambler instance;
return instance;
}


void descramble(std::span<uint8_t> data, uint32_t psn) const
{
process(data, psn);
}

private:
Scrambler() = default;


void process(std::span<uint8_t> data, uint32_t psn) const
{
// ISO/IEC 30190

uint16_t shift_register = (1 << 15) | ((psn >> 5) & 0x7FFF);

for(auto &byte : data)
{
byte ^= (uint8_t)shift_register;

for(uint8_t b = 0; b < CHAR_BIT; ++b)
{
auto lsb = ((shift_register >> 15) ^ (shift_register >> 14) ^ (shift_register >> 12) ^ (shift_register >> 3)) & 1;
shift_register = (shift_register << 1) | lsb;
}
}
}
};

}
2 changes: 1 addition & 1 deletion dvd/dvd.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export struct DataFrame
void descramble(std::optional<uint8_t> nintendo_key = std::nullopt)
{
uint32_t psn = endian_swap_from_array<int32_t>(id.id.sector_number);
dvd::Scrambler::get().descramble(std::span(main_data, FORM1_DATA_SIZE), psn, nintendo_key);
Scrambler::get().descramble(std::span(main_data, FORM1_DATA_SIZE), psn, nintendo_key);
}
};

Expand Down
74 changes: 61 additions & 13 deletions dvd/dvd_dump.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module;

export module dvd.dump;

import bd;
import cd.cdrom;
import common;
import drive;
Expand Down Expand Up @@ -69,7 +70,7 @@ static const std::string BOOK_TYPE[] =
"RESERVED4",
"DVD+RW DL",
"DVD+R DL",
"RESERVED5"
"NINTENDO"
};


Expand Down Expand Up @@ -501,9 +502,12 @@ DumpConfig dump_get_config(DiscType disc_type, bool raw)
{
DumpConfig config{ ".iso", FORM1_DATA_SIZE, 0, 0, 0 };

if(disc_type == DiscType::DVD && raw)
if(raw)
{
config = DumpConfig{ ".sdram", sizeof(dvd::RecordingFrame), dvd::LBA_START, 0, 0 };
if(disc_type == DiscType::DVD)
config = DumpConfig{ ".sdram", sizeof(dvd::RecordingFrame), dvd::LBA_START, 0, 0 };
else if((disc_type == DiscType::BLURAY || disc_type == DiscType::BLURAY_R))
config = DumpConfig{ ".sbram", sizeof(bd::DataFrame), bd::LBA_START, bd::LBA_IZ - (int32_t)OVERREAD_COUNT, 0 };
}

return config;
Expand All @@ -514,7 +518,9 @@ SPTD::Status read_dvd_sectors(SPTD &sptd, uint8_t *sectors, uint32_t sector_size
{
SPTD::Status status;

if(disc_type == DiscType::DVD && raw)
if(!raw)
status = cmd_read(sptd, sectors, sector_size, lba, sectors_count, force_unit_access);
else if(disc_type == DiscType::DVD)
{
if(sector_size != sizeof(dvd::RecordingFrame))
throw_line("invalid sector size for raw DVD read (expected: {}, actual: {})", sizeof(dvd::RecordingFrame), sector_size);
Expand All @@ -532,8 +538,24 @@ SPTD::Status read_dvd_sectors(SPTD &sptd, uint8_t *sectors, uint32_t sector_size
}
}
}
else
status = cmd_read(sptd, sectors, sector_size, lba, sectors_count, force_unit_access);
else if(disc_type == DiscType::BLURAY || disc_type == DiscType::BLURAY_R)
{
if(sector_size != sizeof(bd::DataFrame))
throw_line("invalid sector size for raw BD read (expected: {}, actual: {})", sizeof(bd::DataFrame), sector_size);

std::vector<bd::OmniDriveDataFrame> data_frames(sectors_count);
status = cmd_read_omnidrive(sptd, (uint8_t *)data_frames.data(), sizeof(bd::OmniDriveDataFrame), lba, sectors_count, OmniDrive_DiscType::BD, false, force_unit_access, false,
OmniDrive_Subchannels::NONE, false);

if(!status.status_code)
{
for(uint32_t i = 0; i < sectors_count; ++i)
{
auto &df = (bd::DataFrame &)sectors[i * sizeof(bd::DataFrame)];
df = data_frames[i].data_frame;
}
}
}

return status;
}
Expand Down Expand Up @@ -839,9 +861,14 @@ export bool redumper_dump_dvd(Context &ctx, const Options &options, DumpMode dum
}
}

bool raw = (options.dvd_raw || nintendo_key) && omnidrive_firmware;
if(options.dvd_raw && !omnidrive_firmware)
bool dvd_raw = options.dvd_raw && ctx.disc_type == DiscType::DVD;
bool bd_raw = options.bd_raw && (ctx.disc_type == DiscType::BLURAY || ctx.disc_type == DiscType::BLURAY_R);
if(dvd_raw && !omnidrive_firmware)
LOG("warning: drive not compatible with raw DVD dumping");
if(bd_raw && !omnidrive_firmware)
LOG("warning: drive not compatible with raw BD dumping");

bool raw = (dvd_raw || bd_raw || nintendo_key) && omnidrive_firmware;

auto cfg = dump_get_config(ctx.disc_type, raw);

Expand All @@ -854,9 +881,18 @@ export bool redumper_dump_dvd(Context &ctx, const Options &options, DumpMode dum
}
else if(raw && omnidrive_firmware)
{
// ensure default total transfer length is less than 65536 bytes (31 * 2064)
LOG("warning: setting dump read size to 31 for raw dumping");
dump_read_size = 31;
if(ctx.disc_type == DiscType::DVD)
{
// ensure default total transfer length is less than 65536 bytes (31 * 2064)
LOG("warning: setting dump read size to 31 for raw DVD dumping");
dump_read_size = 31;
}
else if(ctx.disc_type == DiscType::BLURAY || ctx.disc_type == DiscType::BLURAY_R)
{
// ensure default total transfer length is less than 16384 (7 * 2072)
LOG("warning: setting dump read size to 7 for raw BD dumping");
dump_read_size = 7;
}
}
else
dump_read_size = DVD_READ_SIZE;
Expand Down Expand Up @@ -1044,9 +1080,9 @@ export bool redumper_dump_dvd(Context &ctx, const Options &options, DumpMode dum
}
else
{
if(options.verbose)
if(options.verbose && raw)
{
if(ctx.disc_type == DiscType::DVD && raw)
if(ctx.disc_type == DiscType::DVD)
{
for(uint32_t i = 0; i < sectors_to_read; ++i)
{
Expand All @@ -1059,6 +1095,18 @@ export bool redumper_dump_dvd(Context &ctx, const Options &options, DumpMode dum
LOG_R("[LBA: {}] invalid data frame", l);
}
}
else if(ctx.disc_type == DiscType::BLURAY || ctx.disc_type == DiscType::BLURAY_R)
{
for(uint32_t i = 0; i < sectors_to_read; ++i)
{
auto &df = (bd::DataFrame &)drive_data[i * sizeof(bd::DataFrame)];

int32_t l = lba + lba_shift + (int32_t)i;

if(!df.valid(l))
LOG_R("[LBA: {}] invalid data frame", l);
}
}
}

store = true;
Expand Down
Loading