📄 ifo_read.c
字号:
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_SRP_SIZE); ptr += PGCI_SRP_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); } free(pgcit->pgci_srp); pgcit->pgci_srp = NULL; 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); pgcit->pgci_srp = NULL; 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[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 = 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 = 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 = 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 = 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 = malloc(sizeof(txtdt_mgi_t)); if(!txtdt_mgi) { return 0; } ifofile->txtdt_mgi = txtdt_mgi; if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { 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 + -