Add raw blu-ray and aacs tags

This commit is contained in:
Rebecca Wallander
2026-04-10 19:47:34 +02:00
parent 112f53dc3d
commit d6b6accbf5
8 changed files with 180 additions and 64 deletions

View File

@@ -161,6 +161,7 @@ typedef enum
BDRE = 62, ///< BD-RE
BDRXL = 63, ///< BD-R XL
BDREXL = 64, ///< BD-RE XL
UHDBD = 65, ///< Ultra HD Blu-ray
// Standard Blu-ray formats, types 60 to 69
// Rare or uncommon optical standards, types 70 to 79
@@ -211,6 +212,7 @@ typedef enum
PS4BD = 117, ///< Sony PlayStation 4 game Blu-ray
UMD = 118, ///< Sony PlayStation Portable Universal Media Disc (ECMA-365)
PlayStationVitaGameCard = 119, ///< PS Vita NV memory card (proprietary flash)
PS5BD = 120, ///< Sony PlayStation 5 game Blu-ray
// Sony game media, types 110 to 129
// Microsoft game media, types 130 to 149
@@ -977,6 +979,7 @@ typedef enum
kSectorTagDvdSectorEdc = 19, ///< DVD sector EDC, 4 bytes
kSectorTagAppleProfile = 20, ///< Apple's Profile sector tags, 20 bytes
kSectorTagPriamDataTower = 21, ///< Priam DataTower sector tags, 24 bytes
kSectorTagBdSectorEdc = 22, ///< Blu-ray sector EDC, 4 bytes
MaxSectorTag = kSectorTagPriamDataTower
} SectorTagType;
@@ -1082,6 +1085,8 @@ typedef enum
kMediaTagWiiUPartitionKeyMap = 82, ///< Nintendo Wii U partition-to-key mapping with regions
kMediaTagWiiPartitionKeyMap = 83, ///< Nintendo Wii partition-to-key mapping with regions
kMediaTagNgcwJunkMap = 84, ///< Nintendo GameCube/Wii junk region map with LFG seeds
kMediaTagAacsMediaKey = 85, ///< AACS Media Key
kMediaTagAacsVolumeUniqueKey = 86, ///< AACS Volume Unique Key
MaxMediaTag = kMediaTagNgcwJunkMap
} MediaTagType;

View File

@@ -145,6 +145,9 @@ typedef enum
kDataTypeWiiUPartitionKeyMap = 98, ///< Nintendo Wii U partition-to-key mapping with regions
kDataTypeWiiPartitionKeyMap = 99, ///< Nintendo Wii partition-to-key mapping with regions
kDataTypeNgcwJunkMap = 100, ///< Nintendo GameCube/Wii junk region map with LFG seeds
kDataTypeAacsMediaKey = 101, ///< AACS Media Key
kDataTypeAacsVolumeUniqueKey = 102, ///< AACS Volume Unique Key
kDataTypeBdSectorEdc = 103, ///< Blu-ray Sector EDC
} DataType;
/**

View File

@@ -480,6 +480,10 @@ int32_t process_data_block(aaruformat_context *ctx, IndexEntry *entry)
ctx->sector_decrypted_title_key = data;
ctx->readableSectorTags[kSectorTagDvdTitleKeyDecrypted] = true;
break;
case kDataTypeBdSectorEdc:
ctx->sector_edc = data;
ctx->readableSectorTags[kSectorTagBdSectorEdc] = true;
break;
default:
media_tag = (mediaTagEntry *)malloc(sizeof(mediaTagEntry));

View File

@@ -202,6 +202,10 @@ AARU_LOCAL int32_t AARU_CALL aaruf_get_media_tag_type_for_datatype(const int32_t
return kMediaTagWiiPartitionKeyMap;
case kDataTypeNgcwJunkMap:
return kMediaTagNgcwJunkMap;
case kDataTypeAacsMediaKey:
return kMediaTagAacsMediaKey;
case kDataTypeAacsVolumeUniqueKey:
return kMediaTagAacsVolumeUniqueKey;
default:
return -1;
}
@@ -382,6 +386,10 @@ AARU_LOCAL int32_t AARU_CALL aaruf_get_datatype_for_media_tag_type(const int32_t
return kDataTypeWiiPartitionKeyMap;
case kMediaTagNgcwJunkMap:
return kDataTypeNgcwJunkMap;
case kMediaTagAacsMediaKey:
return kDataTypeAacsMediaKey;
case kMediaTagAacsVolumeUniqueKey:
return kDataTypeAacsVolumeUniqueKey;
default:
return -1;
}

View File

@@ -1542,70 +1542,134 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64
}
if(ctx->image_info.MediaType == GOD || ctx->image_info.MediaType == WOD)
{
if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL ||
ctx->sector_edc == NULL)
return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
if(*length < 2064 || data == NULL)
{
*length = 2064;
FATAL("Buffer too small for sector, required %u bytes", *length);
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
bare_length = 0;
query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status);
if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
{
TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
return query_status;
}
if(bare_length == 0)
{
FATAL("Invalid bare sector length (0)");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
return AARUF_ERROR_INCORRECT_DATA_SIZE;
}
TRACE("Allocating memory for bare data");
bare_data = (uint8_t *)malloc(bare_length);
if(bare_data == NULL)
{
FATAL("Could not allocate memory for bare data");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
if(res != AARUF_STATUS_OK)
{
*length = 2064;
free(bare_data);
TRACE("Exiting aaruf_read_sector_long() = %d", res);
return res;
}
memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4);
memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2);
memcpy(data + 6, bare_data, 2048);
memcpy(data + 2054, ctx->sector_cpr_mai + corrected_sector_address * 6, 6);
memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4);
*length = 2064;
free(bare_data);
return AARUF_STATUS_OK;
}
{
if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL ||
ctx->sector_edc == NULL)
return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
if(*length < 2064 || data == NULL)
{
*length = 2064;
FATAL("Buffer too small for sector, required %u bytes", *length);
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
bare_length = 0;
query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status);
if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
{
TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
return query_status;
}
if(bare_length == 0)
{
FATAL("Invalid bare sector length (0)");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
return AARUF_ERROR_INCORRECT_DATA_SIZE;
}
TRACE("Allocating memory for bare data");
bare_data = (uint8_t *)malloc(bare_length);
if(bare_data == NULL)
{
FATAL("Could not allocate memory for bare data");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
if(res != AARUF_STATUS_OK)
{
*length = 2064;
free(bare_data);
TRACE("Exiting aaruf_read_sector_long() = %d", res);
return res;
}
memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4);
memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2);
memcpy(data + 6, bare_data, 2048);
memcpy(data + 2054, ctx->sector_cpr_mai + corrected_sector_address * 6, 6);
memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4);
*length = 2064;
free(bare_data);
return AARUF_STATUS_OK;
}
if(ctx->image_info.MediaType == BDROM || ctx->image_info.MediaType == BDR ||
ctx->image_info.MediaType == BDRE || ctx->image_info.MediaType == BDRXL ||
ctx->image_info.MediaType == BDREXL || ctx->image_info.MediaType == UHDBD ||
ctx->image_info.MediaType == XGD4 || ctx->image_info.MediaType == PS3BD ||
ctx->image_info.MediaType == PS4BD || ctx->image_info.MediaType == PS5BD)
{
if(ctx->sector_edc == NULL) return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
if(*length < 2052 || data == NULL)
{
*length = 2052;
FATAL("Buffer too small for sector, required %u bytes", *length);
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
bare_length = 0;
query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status);
if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
{
TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
return query_status;
}
if(bare_length == 0)
{
FATAL("Invalid bare sector length (0)");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
return AARUF_ERROR_INCORRECT_DATA_SIZE;
}
TRACE("Allocating memory for bare data");
bare_data = (uint8_t *)malloc(bare_length);
if(bare_data == NULL)
{
FATAL("Could not allocate memory for bare data");
TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
if(res != AARUF_STATUS_OK)
{
free(bare_data);
TRACE("Exiting aaruf_read_sector_long() = %d", res);
return res;
}
memcpy(data, bare_data, 2048);
memcpy(data + 2048, ctx->sector_edc + corrected_sector_address * 4, 4);
*length = 2052;
free(bare_data);
return AARUF_STATUS_OK;
}
if(*length < 2352 || data == NULL)
{

View File

@@ -735,6 +735,20 @@ AARU_EXPORT int32_t AARU_CALL aaruf_write_sector_long(void *context, uint64_t se
return aaruf_write_sector(context, sector_address, negative, data + 6, sector_status, 2048);
}
// Blu-ray long sector
if(length == 2052 && (ctx->image_info.MediaType == BDROM || ctx->image_info.MediaType == BDR ||
ctx->image_info.MediaType == BDRE || ctx->image_info.MediaType == BDRXL ||
ctx->image_info.MediaType == BDREXL || ctx->image_info.MediaType == UHDBD ||
ctx->image_info.MediaType == XGD4 || ctx->image_info.MediaType == PS3BD ||
ctx->image_info.MediaType == PS4BD || ctx->image_info.MediaType == PS5BD))
{
if(ctx->sector_edc == NULL) ctx->sector_edc = calloc(1, 4 * total_sectors);
memcpy(ctx->sector_edc + corrected_sector_address * 4, data + 2048, 4);
return aaruf_write_sector(context, sector_address, negative, data, sector_status, 2048);
}
if(length != 2352)
{
FATAL("Incorrect sector size");

View File

@@ -206,6 +206,10 @@ const char *media_tag_type_to_string(int32_t type)
return "DVD Physical Format Information (2nd layer)";
case kMediaTagFloppyWriteProtect:
return "Floppy Write-Protect Status";
case kMediaTagAacsMediaKey:
return "AACS Media Key";
case kMediaTagAacsVolumeUniqueKey:
return "AACS Volume Unique Key";
default:
return "Unknown Media Tag";
}
@@ -391,6 +395,12 @@ const char *data_type_to_string(uint16_t type)
return "DVD Physical Format Info (2nd layer)";
case kDataTypeFloppyWriteProtect:
return "Floppy Write-Protect Status";
case kDataTypeAacsMediaKey:
return "AACS Media Key";
case kDataTypeAacsVolumeUniqueKey:
return "AACS Volume Unique Key";
case kDataTypeBdSectorEdc:
return "Blu-ray Sector EDC";
default:
return "Unknown Data Type";
}
@@ -1587,6 +1597,8 @@ const char *sector_tag_type_to_string(int32_t type)
return "Apple Profile Tag";
case kSectorTagPriamDataTower:
return "Priam DataTower Tag";
case kSectorTagBdSectorEdc:
return "Blu-ray Sector EDC";
default:
return "Unknown Sector Tag";
}

View File

@@ -134,6 +134,8 @@ static const MediaTagTypeMapping media_tag_mappings[] = {
{"kMediaTagDvdDiscKeyDecrypted", kMediaTagDvdDiscKeyDecrypted},
{"kMediaTagDvdPfi2ndLayer", kMediaTagDvdPfi2ndLayer},
{"kMediaTagFloppyWriteProtect", kMediaTagFloppyWriteProtect},
{"kMediaTagAacsMediaKey", kMediaTagAacsMediaKey},
{"kMediaTagAacsVolumeUniqueKey", kMediaTagAacsVolumeUniqueKey},
};
// clang-format on
@@ -290,6 +292,10 @@ static int32_t get_datatype_for_media_tag_type(MediaTagType tag_type)
return kDataTypeDvdDiscKeyDecrypted;
case kMediaTagFloppyWriteProtect:
return kDataTypeFloppyWriteProtect;
case kMediaTagAacsMediaKey:
return kDataTypeAacsMediaKey;
case kMediaTagAacsVolumeUniqueKey:
return kDataTypeAacsVolumeUniqueKey;
default:
return -1;
}