📄 ifo_read.c
字号:
unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size); if(!cmd_tbl->post_cmds) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); return 0; } if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); free(cmd_tbl->post_cmds); return 0; } } if(cmd_tbl->nr_of_cell != 0) { unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size); if(!cmd_tbl->cell_cmds) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); return 0; } if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); free(cmd_tbl->cell_cmds); return 0; } } /* * Make a run over all the commands and see that we can interpret them all? */ return 1;}static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { if(cmd_tbl) { if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds) free(cmd_tbl->cell_cmds); free(cmd_tbl); }}static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, pgc_program_map_t *program_map, unsigned int nr, unsigned int offset) { unsigned int size = nr * sizeof(pgc_program_map_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, program_map, size))) return 0; return 1;}static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, cell_playback_t *cell_playback, unsigned int nr, unsigned int offset) { unsigned int i; unsigned int size = nr * sizeof(cell_playback_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, cell_playback, size))) return 0; for(i = 0; i < nr; i++) { B2N_32(cell_playback[i].first_sector); B2N_32(cell_playback[i].first_ilvu_end_sector); B2N_32(cell_playback[i].last_vobu_start_sector); B2N_32(cell_playback[i].last_sector); /* Changed < to <= because this was false in the movie 'Pi'. */ CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= cell_playback[i].last_sector); CHECK_VALUE(cell_playback[i].first_sector <= cell_playback[i].last_vobu_start_sector); } return 1;}static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, cell_position_t *cell_position, unsigned int nr, unsigned int offset) { unsigned int i; unsigned int size = nr * sizeof(cell_position_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, cell_position, size))) return 0; for(i = 0; i < nr; i++) { B2N_16(cell_position[i].vob_id_nr); CHECK_ZERO(cell_position[i].zero_1); } return 1;}static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { unsigned int i; if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE))) return 0; B2N_16(pgc->next_pgc_nr); B2N_16(pgc->prev_pgc_nr); B2N_16(pgc->goup_pgc_nr); B2N_16(pgc->command_tbl_offset); B2N_16(pgc->program_map_offset); B2N_16(pgc->cell_playback_offset); B2N_16(pgc->cell_position_offset); for(i = 0; i < 8; i++) B2N_16(pgc->audio_control[i]); for(i = 0; i < 32; i++) B2N_32(pgc->subp_control[i]); for(i = 0; i < 16; i++) B2N_32(pgc->palette[i]); CHECK_ZERO(pgc->zero_1); CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); /* verify time (look at print_time) */ for(i = 0; i < 8; i++) if(!pgc->audio_control[i] & 0x8000) /* The 'is present' bit */ CHECK_ZERO(pgc->audio_control[i]); for(i = 0; i < 32; i++) if(!pgc->subp_control[i] & 0x80000000) /* The 'is present' bit */ CHECK_ZERO(pgc->subp_control[i]); /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ if(pgc->nr_of_programs == 0) { CHECK_ZERO(pgc->still_time); CHECK_ZERO(pgc->pg_playback_mode); // ?? CHECK_VALUE(pgc->program_map_offset == 0); CHECK_VALUE(pgc->cell_playback_offset == 0); CHECK_VALUE(pgc->cell_position_offset == 0); } else { CHECK_VALUE(pgc->program_map_offset != 0); CHECK_VALUE(pgc->cell_playback_offset != 0); CHECK_VALUE(pgc->cell_position_offset != 0); } if(pgc->command_tbl_offset != 0) { pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t)); if(!pgc->command_tbl) return 0; if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, offset + pgc->command_tbl_offset)) { free(pgc->command_tbl); return 0; } } else { pgc->command_tbl = NULL; } if(pgc->program_map_offset != 0) { pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); if(!pgc->program_map) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); return 0; } if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, offset + pgc->program_map_offset)) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); free(pgc->program_map); return 0; } } else { pgc->program_map = NULL; } if(pgc->cell_playback_offset != 0) { pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); if(!pgc->cell_playback) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); if(pgc->program_map) free(pgc->program_map); return 0; } if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, pgc->nr_of_cells, offset + pgc->cell_playback_offset)) { ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); if(pgc->program_map) free(pgc->program_map); free(pgc->cell_playback); return 0; } } else { pgc->cell_playback = NULL; } if(pgc->cell_position_offset != 0) { pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); if(!pgc->cell_position) { ifoFree_PGC(pgc); return 0; } if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, pgc->nr_of_cells, offset + pgc->cell_position_offset)) { ifoFree_PGC(pgc); return 0; } } else { pgc->cell_position = NULL; } return 1;}int ifoRead_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile) return 0; 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 = (pgc_t *)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 = (tt_srpt_t *)malloc(sizeof(tt_srpt_t)); if(!tt_srpt) return 0; ifofile->tt_srpt = tt_srpt; if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { 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 = (title_info_t *)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))) { 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((int)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 = (vts_ptt_srpt_t *)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))) { 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 = (uint32_t *)malloc(info_length); if(!data) { free(vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; return 0; } if(!(DVDReadBytes(ifofile->file, data, info_length))) { 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); // ?? } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -