📄 ifo_read.c
字号:
/* assert(info_length > 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with a VOBS that has no VOBUs. */
CHECK_VALUE(info_length % sizeof(uint32_t) == 0);
vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length);
//if( info_length> 40000 )
//free( vobu_admap->vobu_start_sectors );
if(!vobu_admap->vobu_start_sectors) {
return 0;
}
if(info_length &&
!(DVDReadBytes(ifofile->file,
vobu_admap->vobu_start_sectors, info_length))) {
free(vobu_admap->vobu_start_sectors);
return 0;
}
for(i = 0; i < info_length/sizeof(uint32_t); i++)
B2N_32(vobu_admap->vobu_start_sectors[i]);
return 1;
}
static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) {
if(vobu_admap) {
free(vobu_admap->vobu_start_sectors);
free(vobu_admap);
}
}
void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) {
if(!ifofile)
return;
ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap);
ifofile->menu_vobu_admap = 0;
}
void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
if(!ifofile)
return;
ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap);
ifofile->vts_vobu_admap = 0;
}
int ifoRead_PGCIT(ifo_handle_t *ifofile) {
if(!ifofile)
return 0;
if(!ifofile->vtsi_mat)
return 0;
if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */
return 0;
ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
if(!ifofile->vts_pgcit)
return 0;
if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
free(ifofile->vts_pgcit);
ifofile->vts_pgcit = 0;
return 0;
}
return 1;
}
static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
unsigned int offset) {
int i, info_length;
uint8_t *data, *ptr;
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE)))
return 0;
B2N_16(pgcit->nr_of_pgci_srp);
B2N_32(pgcit->last_byte);
CHECK_ZERO(pgcit->zero_1);
/* assert(pgcit->nr_of_pgci_srp != 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. */
CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338
info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
data = malloc(info_length);
if(!data)
return 0;
if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) {
free(data);
return 0;
}
pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t));
if(!pgcit->pgci_srp) {
free(data);
return 0;
}
ptr = data;
for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
memcpy(&pgcit->pgci_srp[i], ptr, PGCI_LU_SIZE);
ptr += PGCI_LU_SIZE;
B2N_16(pgcit->pgci_srp[i].ptl_id_mask);
B2N_32(pgcit->pgci_srp[i].pgc_start_byte);
CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0);
}
free(data);
for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t));
if(!pgcit->pgci_srp[i].pgc) {
int j;
for(j = 0; j < i; j++) {
ifoFree_PGC(pgcit->pgci_srp[j].pgc);
free(pgcit->pgci_srp[j].pgc);
}
return 0;
}
if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
offset + pgcit->pgci_srp[i].pgc_start_byte)) {
int j;
for(j = 0; j < i; j++) {
ifoFree_PGC(pgcit->pgci_srp[j].pgc);
free(pgcit->pgci_srp[j].pgc);
}
free(pgcit->pgci_srp);
return 0;
}
}
return 1;
}
static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
if(pgcit) {
int i;
for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
ifoFree_PGC(pgcit->pgci_srp[i].pgc);
free(pgcit->pgci_srp);
}
}
void ifoFree_PGCIT(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->vts_pgcit) {
ifoFree_PGCIT_internal(ifofile->vts_pgcit);
free(ifofile->vts_pgcit);
ifofile->vts_pgcit = 0;
}
}
int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
pgci_ut_t *pgci_ut;
unsigned int sector;
unsigned int i;
int info_length;
uint8_t *data, *ptr;
if(!ifofile)
return 0;
if(ifofile->vmgi_mat) {
if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
return 1;
sector = ifofile->vmgi_mat->vmgm_pgci_ut;
} else if(ifofile->vtsi_mat) {
if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
return 1;
sector = ifofile->vtsi_mat->vtsm_pgci_ut;
} else {
return 0;
}
ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t));
if(!ifofile->pgci_ut)
return 0;
if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) {
free(ifofile->pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
free(ifofile->pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
pgci_ut = ifofile->pgci_ut;
B2N_16(pgci_ut->nr_of_lus);
B2N_32(pgci_ut->last_byte);
CHECK_ZERO(pgci_ut->zero_1);
CHECK_VALUE(pgci_ut->nr_of_lus != 0);
CHECK_VALUE(pgci_ut->nr_of_lus < 100); // ?? 3-4 ?
CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
data = malloc(info_length);
if(!data) {
free(pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
if(!(DVDReadBytes(ifofile->file, data, info_length))) {
free(data);
free(pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t));
if(!pgci_ut->lu) {
free(data);
free(pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
ptr = data;
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE);
ptr += PGCI_LU_SIZE;
B2N_16(pgci_ut->lu[i].lang_code);
B2N_32(pgci_ut->lu[i].lang_start_byte);
}
free(data);
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
// Maybe this is only defined for v1.1 and later titles?
/* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
VTS_x_yy.IFO VIDEO_TS.IFO
a == 0x83 "Root" 0x82 "Title"
b == 0x84 "Subpicture"
c == 0x85 "Audio"
d == 0x86 "Angle"
e == 0x87 "PTT"
*/
CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0);
}
for(i = 0; i < pgci_ut->nr_of_lus; i++) {
pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
if(!pgci_ut->lu[i].pgcit) {
unsigned int j;
for(j = 0; j < i; j++) {
ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
free(pgci_ut->lu[j].pgcit);
}
free(pgci_ut->lu);
free(pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
sector * DVD_BLOCK_LEN
+ pgci_ut->lu[i].lang_start_byte)) {
unsigned int j;
for(j = 0; j < i; j++) {
ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
free(pgci_ut->lu[j].pgcit);
}
free(pgci_ut->lu[i].pgcit);
free(pgci_ut->lu);
free(pgci_ut);
ifofile->pgci_ut = 0;
return 0;
}
// FIXME: Iterate and verify that all menus that should exists accordingly
// to pgci_ut->lu[i].exists really do?
}
return 1;
}
void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
unsigned int i;
if(!ifofile)
return;
if(ifofile->pgci_ut) {
for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
free(ifofile->pgci_ut->lu[i].pgcit);
}
free(ifofile->pgci_ut->lu);
free(ifofile->pgci_ut);
ifofile->pgci_ut = 0;
}
}
static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
vts_attributes_t *vts_attributes,
unsigned int offset) {
unsigned int i;
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t))))
return 0;
B2N_32(vts_attributes->last_byte);
B2N_32(vts_attributes->vts_cat);
B2N_16(vts_attributes->vtsm_audio_attr.lang_code);
B2N_16(vts_attributes->vtsm_subp_attr.lang_code);
for(i = 0; i < 8; i++)
B2N_16(vts_attributes->vtstt_audio_attr[i].lang_code);
for(i = 0; i < 32; i++)
B2N_16(vts_attributes->vtstt_subp_attr[i].lang_code);
CHECK_ZERO(vts_attributes->zero_1);
CHECK_ZERO(vts_attributes->zero_2);
CHECK_ZERO(vts_attributes->zero_3);
CHECK_ZERO(vts_attributes->zero_4);
CHECK_ZERO(vts_attributes->zero_5);
CHECK_ZERO(vts_attributes->zero_6);
CHECK_ZERO(vts_attributes->zero_7);
CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1);
CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1);
CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8);
for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++)
CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]);
CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32);
{
unsigned int nr_coded;
CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
// This is often nr_coded = 70, how do you know how many there really are?
if(nr_coded > 32) { // We haven't read more from disk/file anyway
nr_coded = 32;
}
CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++)
CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]);
}
return 1;
}
int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
vts_atrt_t *vts_atrt;
unsigned int i, info_length, sector;
uint32_t *data;
if(!ifofile)
return 0;
if(!ifofile->vmgi_mat)
return 0;
if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */
return 0;
sector = ifofile->vmgi_mat->vts_atrt;
if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
return 0;
vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t));
if(!vts_atrt)
return 0;
ifofile->vts_atrt = vts_atrt;
if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) {
free(vts_atrt);
ifofile->vts_atrt = 0;
return 0;
}
B2N_16(vts_atrt->nr_of_vtss);
B2N_32(vts_atrt->last_byte);
CHECK_ZERO(vts_atrt->zero_1);
CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
CHECK_VALUE(vts_atrt->nr_of_vtss < 100); //??
CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t);
data = (uint32_t *)malloc(info_length);
if(!data) {
free(vts_atrt);
ifofile->vts_atrt = 0;
return 0;
}
vts_atrt->vts_atrt_offsets = data;
if(!(DVDReadBytes(ifofile->file, data, info_length))) {
free(data);
free(vts_atrt);
ifofile->vts_atrt = 0;
return 0;
}
for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
B2N_32(data[i]);
CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
}
info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t);
vts_atrt->vts = (vts_attributes_t *)malloc(info_length);
if(!vts_atrt->vts) {
free(data);
free(vts_atrt);
ifofile->vts_atrt = 0;
return 0;
}
for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
unsigned int offset = data[i];
if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]),
(sector * DVD_BLOCK_LEN) + offset)) {
free(data);
free(vts_atrt);
ifofile->vts_atrt = 0;
return 0;
}
// This assert cant be in ifoRead_VTS_ATTRIBUTES
CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
// Is this check correct?
}
return 1;
}
void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->vts_atrt) {
free(ifofile->vts_atrt->vts);
free(ifofile->vts_atrt->vts_atrt_offsets);
free(ifofile->vts_atrt);
ifofile->vts_atrt = 0;
}
}
int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
txtdt_mgi_t *txtdt_mgi;
if(!ifofile)
return 0;
if(!ifofile->vmgi_mat)
return 0;
/* Return successfully if there is nothing to read. */
if(ifofile->vmgi_mat->txtdt_mgi == 0)
return 1;
if(!DVDFileSeek_(ifofile->file,
ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
return 0;
txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t));
if(!txtdt_mgi) {
return 0;
}
ifofile->txtdt_mgi = txtdt_mgi;
if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
free(txtdt_mgi);
ifofile->txtdt_mgi = 0;
return 0;
}
// fprintf(stderr, "-- Not done yet --\n");
return 1;
}
void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->txtdt_mgi) {
free(ifofile->txtdt_mgi);
ifofile->txtdt_mgi = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -