📄 ifo_read.c
字号:
if(!ifofile->vmgi_mat) return 0; /* It seems that first_play_pgc is optional after all. */ ifofile->first_play_pgc = 0; if(ifofile->vmgi_mat->first_play_pgc == 0) return 1; ifofile->first_play_pgc = malloc(sizeof(pgc_t)); if(!ifofile->first_play_pgc) return 0; if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, ifofile->vmgi_mat->first_play_pgc)) { free(ifofile->first_play_pgc); ifofile->first_play_pgc = 0; return 0; } return 1;}static void ifoFree_PGC(pgc_t *pgc) { if(pgc) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); if(pgc->program_map) free(pgc->program_map); if(pgc->cell_playback) free(pgc->cell_playback); if(pgc->cell_position) free(pgc->cell_position); }}void ifoFree_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->first_play_pgc) { ifoFree_PGC(ifofile->first_play_pgc); free(ifofile->first_play_pgc); ifofile->first_play_pgc = 0; }}int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { tt_srpt_t *tt_srpt; int i, info_length; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ return 0; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) return 0; tt_srpt = malloc(sizeof(tt_srpt_t)); if(!tt_srpt) return 0; ifofile->tt_srpt = tt_srpt; if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); } free(tt_srpt); return 0; } B2N_16(tt_srpt->nr_of_srpts); B2N_32(tt_srpt->last_byte); info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; tt_srpt->title = malloc(info_length); if(!tt_srpt->title) { free(tt_srpt); ifofile->tt_srpt = 0; return 0; } if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); } ifoFree_TT_SRPT(ifofile); return 0; } for(i = 0; i < tt_srpt->nr_of_srpts; i++) { B2N_16(tt_srpt->title[i].nr_of_ptts); B2N_16(tt_srpt->title[i].parental_id); B2N_32(tt_srpt->title[i].title_set_sector); } CHECK_ZERO(tt_srpt->zero_1); CHECK_VALUE(tt_srpt->nr_of_srpts != 0); CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ?? CHECK_VALUE(tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); //CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); // XXX: this assertion breaks Ghostbusters: CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); // ?? CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); // ?? CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); // ?? //CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); } // Make this a function#if 0 if(memcmp((uint8_t *)tt_srpt->title + tt_srpt->nr_of_srpts * sizeof(title_info_t), my_friendly_zeros, info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { fprintf(stderr, "VMG_PTT_SRPT slack is != 0, "); hexdump((uint8_t *)tt_srpt->title + tt_srpt->nr_of_srpts * sizeof(title_info_t), info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); }#endif return 1;}void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->tt_srpt) { free(ifofile->tt_srpt->title); free(ifofile->tt_srpt); ifofile->tt_srpt = 0; }}int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { vts_ptt_srpt_t *vts_ptt_srpt; int info_length, i, j; uint32_t *data; if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ return 0; if(!DVDFileSeek_(ifofile->file, ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) return 0; vts_ptt_srpt = malloc(sizeof(vts_ptt_srpt_t)); if(!vts_ptt_srpt) return 0; ifofile->vts_ptt_srpt = vts_ptt_srpt; if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); } free(vts_ptt_srpt); return 0; } B2N_16(vts_ptt_srpt->nr_of_srpts); B2N_32(vts_ptt_srpt->last_byte); CHECK_ZERO(vts_ptt_srpt->zero_1); CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); // ?? info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; data = malloc(info_length); if(!data) { free(vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; return 0; } if(!(DVDReadBytes(ifofile->file, data, info_length))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); } free(vts_ptt_srpt); free(data); ifofile->vts_ptt_srpt = 0; return 0; } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { B2N_32(data[i]); /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. They all have a data[i] offsets beyond the end of of the vts_ptt_srpt structure. */ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); } vts_ptt_srpt->ttu_offset = data; vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); if(!vts_ptt_srpt->title) { free(vts_ptt_srpt); free(data); ifofile->vts_ptt_srpt = 0; return 0; } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { int n; if(i < vts_ptt_srpt->nr_of_srpts - 1) n = (data[i+1] - data[i]); else n = (vts_ptt_srpt->last_byte + 1 - data[i]); /* assert(n > 0 && (n % 4) == 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ if(n < 0) n = 0; CHECK_VALUE(n % 4 == 0); vts_ptt_srpt->title[i].nr_of_ptts = n / 4; vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); if(!vts_ptt_srpt->title[i].ptt) { for(n = 0; n < i; n++) free(vts_ptt_srpt->title[n].ptt); free(vts_ptt_srpt); free(data); ifofile->vts_ptt_srpt = 0; return 0; } for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { /* The assert placed here because of Magic Knight Rayearth Daybreak */ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); vts_ptt_srpt->title[i].ptt[j].pgcn = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); vts_ptt_srpt->title[i].ptt[j].pgn = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); } } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); } } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ?? for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ?? CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ?? } } return 1;}void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->vts_ptt_srpt) { int i; for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) free(ifofile->vts_ptt_srpt->title[i].ptt); free(ifofile->vts_ptt_srpt->ttu_offset); free(ifofile->vts_ptt_srpt->title); free(ifofile->vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; }}int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { ptl_mait_t *ptl_mait; int info_length; unsigned int i, j; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; if(ifofile->vmgi_mat->ptl_mait == 0) return 1; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) return 0; ptl_mait = malloc(sizeof(ptl_mait_t)); if(!ptl_mait) return 0; ifofile->ptl_mait = ptl_mait; if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { free(ptl_mait); ifofile->ptl_mait = 0; return 0; } B2N_16(ptl_mait->nr_of_countries); B2N_16(ptl_mait->nr_of_vtss); B2N_32(ptl_mait->last_byte); CHECK_VALUE(ptl_mait->nr_of_countries != 0); CHECK_VALUE(ptl_mait->nr_of_countries < 100); // ?? CHECK_VALUE(ptl_mait->nr_of_vtss != 0); CHECK_VALUE(ptl_mait->nr_of_vtss < 100); // ?? CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); ptl_mait->countries = malloc(info_length); if(!ptl_mait->countries) { free(ptl_mait); ifofile->ptl_mait = 0; return 0; } for(i = 0; i < ptl_mait->nr_of_countries; i++) { if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); } free(ptl_mait->countries); free(ptl_mait); ifofile->ptl_mait = 0; return 0; } } for(i = 0; i < ptl_mait->nr_of_countries; i++) { B2N_16(ptl_mait->countries[i].country_code); B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); } for(i = 0; i < ptl_mait->nr_of_countries; i++) { CHECK_ZERO(ptl_mait->countries[i].zero_1); CHECK_ZERO(ptl_mait->countries[i].zero_2); CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + 16U * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1U); } for(i = 0; i < ptl_mait->nr_of_countries; i++) { uint16_t *pf_temp; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n"); } free(ptl_mait->countries); free(ptl_mait); return 0; } info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); pf_temp = malloc(info_length); if(!pf_temp) { for(j = 0; j < i ; j++) { free(ptl_mait->countries[j].pf_ptl_mai); } free(ptl_mait->countries); free(ptl_mait); return 0; } if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { if(dvdread_verbose(device_of_file(ifofile->file)) >= 1) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); } free(pf_temp); for(j = 0; j < i ; j++) { free(ptl_mait->countries[j].pf_ptl_mai); } free(ptl_mait->countries); free(ptl_mait); return 0; } for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { B2N_16(pf_temp[j]); } ptl_mait->countries[i].pf_ptl_mai = malloc(info_length); if(!ptl_mait->countries[i].pf_ptl_mai) { free(pf_temp); for(j = 0; j < i ; j++) { free(ptl_mait->countries[j].pf_ptl_mai); } free(ptl_mait->countries); free(ptl_mait); return 0; } { /* Transpose the array so we can use C indexing. */ int level, vts; for(level = 0; level < 8; level++) { for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { ptl_mait->countries[i].pf_ptl_mai[vts][level] = pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; } } free(pf_temp); } } return 1;}void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { unsigned int i; if(!ifofile) return; if(ifofile->ptl_mait) { for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -