📄 vm.c
字号:
return do_nothing; } break; case LinkPGCN: if(get_PGC(link_values.data1)) assert(0); link_values = play_PGC(); break; case LinkPTTN: assert(state.domain == VTS_DOMAIN); if(get_VTS_PTT(state.vtsN, state.VTS_TTN_REG, link_values.data1) == -1) assert(0); // not play_PGC(); Fixes Men In Black delux set / sepcial edition link_values = play_PG(); break; case LinkPGN: /* Update any other state, PTTN perhaps? */ state.pgN = link_values.data1; link_values = play_PG(); break; case LinkCN: /* Update any other state, pgN, PTTN perhaps? */ state.cellN = link_values.data1; link_values = play_Cell(); break; case Exit: exit(1); // What should we do here?? case JumpTT: assert(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN); if(get_TT(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case JumpVTS_TT: assert(state.domain == VTSM_DOMAIN || state.domain == VTS_DOMAIN); //?? if(get_VTS_TT(state.vtsN, link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case JumpVTS_PTT: assert(state.domain == VTSM_DOMAIN || state.domain == VTS_DOMAIN); //?? if(get_VTS_PTT(state.vtsN, link_values.data1, link_values.data2) == -1) assert(0); link_values = play_PGC(); break; case JumpSS_FP: assert(state.domain == VMGM_DOMAIN || state.domain == VTSM_DOMAIN); //?? get_FP_PGC(); link_values = play_PGC(); break; case JumpSS_VMGM_MENU: assert(state.domain == VMGM_DOMAIN || state.domain == VTSM_DOMAIN || state.domain == FP_DOMAIN); //?? state.domain = VMGM_DOMAIN; if(get_MENU(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case JumpSS_VTSM: if(link_values.data1 == 0) { // 'The Fifth Element' region 2 has data1 == 0. assert(state.domain == VTSM_DOMAIN); } else if(link_values.data1 == state.vtsN) { // "Captain Scarlet & the Mysterons" has data1 == state.vtsN i VTSM assert(state.domain == VTSM_DOMAIN || state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN); //?? state.domain = VTSM_DOMAIN; } else { // Normal case. assert(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN); //?? state.domain = VTSM_DOMAIN; ifoOpenNewVTSI(dvd, link_values.data1); // Also sets state.vtsN } // I don't really know what title is supposed to be used for. // Alien or Aliens has this != 1, I think. //assert(link_values.data2 == 1); assert(link_values.data2 != 0); state.VTS_TTN_REG = link_values.data2; if(get_MENU(link_values.data3) == -1) assert(0); link_values = play_PGC(); break; case JumpSS_VMGM_PGC: assert(state.domain == VMGM_DOMAIN || state.domain == VTSM_DOMAIN || state.domain == FP_DOMAIN); //?? state.domain = VMGM_DOMAIN; if(get_PGC(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case CallSS_FP: assert(state.domain == VTS_DOMAIN); //?? // Must be called before domain is changed saveRSMinfo(link_values.data1, /* We dont have block info */ 0); get_FP_PGC(); link_values = play_PGC(); break; case CallSS_VMGM_MENU: assert(state.domain == VTS_DOMAIN); //?? // Must be called before domain is changed saveRSMinfo(link_values.data2, /* We dont have block info */ 0); state.domain = VMGM_DOMAIN; if(get_MENU(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case CallSS_VTSM: assert(state.domain == VTS_DOMAIN); //?? // Must be called before domain is changed saveRSMinfo(link_values.data2, /* We dont have block info */ 0); state.domain = VTSM_DOMAIN; if(get_MENU(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case CallSS_VMGM_PGC: assert(state.domain == VTS_DOMAIN); //?? // Must be called before domain is changed saveRSMinfo(link_values.data2, /* We dont have block info */ 0); state.domain = VMGM_DOMAIN; if(get_PGC(link_values.data1) == -1) assert(0); link_values = play_PGC(); break; case PlayThis: /* Should never happen. */ break; } } return link_values;}static int get_TT(int tt){ assert(tt <= vmgi->tt_srpt->nr_of_srpts); state.TTN_REG = tt; return get_VTS_TT(vmgi->tt_srpt->title[tt - 1].title_set_nr, vmgi->tt_srpt->title[tt - 1].vts_ttn);}static int get_TT_PTT(int tt, int ptt){ assert(tt <= vmgi->tt_srpt->nr_of_srpts); state.TTN_REG = tt; // Add this check for use call of this code. //assert(part <= vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts); return get_VTS_PTT(vmgi->tt_srpt->title[tt - 1].title_set_nr, vmgi->tt_srpt->title[tt - 1].vts_ttn, ptt);}static int get_VTS_TT(int vtsN, int vts_ttn){ int pgcN; state.domain = VTS_DOMAIN; if(vtsN != state.vtsN) ifoOpenNewVTSI(dvd, vtsN); // Also sets state.vtsN pgcN = get_ID(vts_ttn); // This might return -1 assert(pgcN != -1); //assert(pgcN == vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn); ?? //state.TTN_REG = ?? Must search tt_srpt for a matching entry... state.VTS_TTN_REG = vts_ttn; /* Any other registers? */ return get_PGC(pgcN);}static int get_VTS_PTT(int vtsN, int /* is this really */ vts_ttn, int part){ int pgcN, pgN, res; state.domain = VTS_DOMAIN; if(vtsN != state.vtsN) ifoOpenNewVTSI(dvd, vtsN); // Also sets state.vtsN assert(vts_ttn <= vtsi->vts_ptt_srpt->nr_of_srpts); assert(part <= vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts); pgcN = vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgcn; pgN = vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn; //assert(pgcN == get_ID(vts_ttn); ?? //state.TTN_REG = ?? Must search tt_srpt for a matchhing entry... state.VTS_TTN_REG = vts_ttn; /* Any other registers? */ res = get_PGC(pgcN); // This clobbers state.pgN (sets it to 1). state.pgN = pgN; return res;}static int get_FP_PGC(void){ state.domain = FP_DOMAIN; /* 'DVD Authoring & Production' claim that first_play_pgc is optional. */ if(vmgi->first_play_pgc) { state.pgc = vmgi->first_play_pgc; state.pgN = 1; } else { if(get_TT(1) == -1) assert(0); } return 0;}static int get_MENU(int menu){ assert(state.domain == VMGM_DOMAIN || state.domain == VTSM_DOMAIN); return get_PGC(get_ID(menu));}/*** * Search PGCIT for a PGC that has entry_id == id and return the PGCN of that. */static int get_ID(int id){ int pgcN, i; pgcit_t *pgcit; /* Relies on state to get the correct pgcit. */ pgcit = get_PGCIT(); assert(pgcit != NULL); /* Get menu/title */ for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { int entry_id = pgcit->pgci_srp[i].entry_id & 0x7F; int entryPGC = pgcit->pgci_srp[i].entry_id & 0x80; // Only 'enter' the one that has the entry flag set and is a match. if(entryPGC && (entry_id == id)) { pgcN = i + 1; return pgcN; } } DNOTE("** No such id/menu (%d) entry PGC\n", id); return -1; // error}/*** * Update the state so that pgcN is the current PGC. Sets PGN to 1 and * if we are in VTS_DOMAIN (really TT_DOM) updates the TT_PGC_REG. */static int get_PGC(int pgcN){ pgcit_t *pgcit; pgcit = get_PGCIT(); assert(pgcit != NULL); // ?? Make this return -1 instead if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) return -1; // error //state.pgcN = pgcN; state.pgc = pgcit->pgci_srp[pgcN - 1].pgc; state.pgN = 1; if(state.domain == VTS_DOMAIN) state.TT_PGCN_REG = pgcN; return 0;}static int get_PGCN(){ pgcit_t *pgcit; int pgcN = 1; pgcit = get_PGCIT(); assert(pgcit != NULL); while(pgcN <= pgcit->nr_of_pgci_srp) { if(pgcit->pgci_srp[pgcN - 1].pgc == state.pgc) return pgcN; pgcN++; } return -1; // error}//scan the cell table?static int get_cellN_for_vobu(uint32_t vobu_addr){ unsigned int i, j, entries; c_adt_t *c_adt = vtsi->vts_c_adt; //nr_of_vobs = c_adt->nr_of_vobs; entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t); fprintf(stderr, "VOBU addr: 0x%x\n", vobu_addr); for(i = 0; i < entries; i++) { if(c_adt->cell_adr_table[i].start_sector <= vobu_addr && vobu_addr <= c_adt->cell_adr_table[i].last_sector) { uint16_t vob_id = c_adt->cell_adr_table[i].vob_id; uint8_t cell_id = c_adt->cell_adr_table[i].cell_id; fprintf(stderr, "start_sector: 0x%x\n", c_adt->cell_adr_table[i].start_sector); fprintf(stderr, "last_sector: 0x%x\n", c_adt->cell_adr_table[i].last_sector); fprintf(stderr, "VOBID: %d CELLID: %d\n", vob_id, cell_id); for(j = 0; j < state.pgc->nr_of_cells; j++) { if(state.pgc->cell_position[j].vob_id_nr == vob_id && state.pgc->cell_position[j].cell_nr == cell_id) { fprintf(stderr, "VOBID: %d CELLID: %d, CellN: %d\n", vob_id, cell_id, j + 1); return j + 1; // cellN is 1 based } } // Something crazy has happened!! // The VOB / CELL id wasn't part of this PGC! assert(0 & 13); } } // Something crazy has happened!! // Unable to find the VOB / CELL id for the VOBU! assert(0 & 14); return 1;}static int get_video_aspect(void){ int aspect = 0; if(state.domain == VTS_DOMAIN) { aspect = vtsi->vtsi_mat->vts_video_attr.display_aspect_ratio; } else if(state.domain == VTSM_DOMAIN) { aspect = vtsi->vtsi_mat->vtsm_video_attr.display_aspect_ratio; } else if(state.domain == VMGM_DOMAIN) { aspect = vmgi->vmgi_mat->vmgm_video_attr.display_aspect_ratio; } assert(aspect == 0 || aspect == 3); state.registers.SPRM[14] &= ~(0x3 << 10); state.registers.SPRM[14] |= aspect << 10; return aspect;}static void ifoOpenNewVTSI(dvd_reader_t *dvd, int vtsN) { if(state.vtsN == vtsN) { return; // We alread have it } if(vtsi != NULL) ifoClose(vtsi); vtsi = ifoOpenVTSI(dvd, vtsN); if(vtsi == NULL) { FATAL("%s", "ifoOpenVTSI failed\n"); exit(1); } if(!ifoRead_VTS_PTT_SRPT(vtsi)) { FATAL("%s", "ifoRead_VTS_PTT_SRPT failed\n"); exit(1); } if(!ifoRead_PGCIT(vtsi)) { FATAL("%s", "ifoRead_PGCIT failed\n"); exit(1); } if(!ifoRead_PGCI_UT(vtsi)) { FATAL("%s", "ifoRead_PGCI_UT failed\n"); exit(1); } if(!ifoRead_VTS_TMAPT(vtsi)) { FATAL("%s", "ifoRead_VTS_TMAPT failed\n"); exit(1); } if(!ifoRead_TITLE_C_ADT(vtsi)) { FATAL("%s", "ifoRead_TITLE_C_ADT failed\n"); exit(1); } state.vtsN = vtsN;}static pgcit_t* get_MENU_PGCIT(ifo_handle_t *h, uint16_t lang){ int i; if(h == NULL || h->pgci_ut == NULL) { WARNING("%s", "*** pgci_ut handle is NULL ***\n"); return NULL; // error? } i = 0; while(i < h->pgci_ut->nr_of_lus && h->pgci_ut->lu[i].lang_code != lang) i++; if(i == h->pgci_ut->nr_of_lus) { NOTE("Language '%c%c' not found, using '%c%c' instead\n", (char)(lang >> 8), (char)(lang & 0xff), (char)(h->pgci_ut->lu[0].lang_code >> 8), (char)(h->pgci_ut->lu[0].lang_code & 0xff)); i = 0; // error? } return h->pgci_ut->lu[i].pgcit;}/* Uses state to decide what to return */static pgcit_t* get_PGCIT(void) { pgcit_t *pgcit; if(state.domain == VTS_DOMAIN) { pgcit = vtsi->vts_pgcit; } else if(state.domain == VTSM_DOMAIN) { pgcit = get_MENU_PGCIT(vtsi, state.registers.SPRM[0]); } else if(state.domain == VMGM_DOMAIN) { pgcit = get_MENU_PGCIT(vmgi, state.registers.SPRM[0]); } else { pgcit = NULL; /* Should never hapen */ } return pgcit;}int vm_get_udf_volids(char *volid, unsigned int volidlen, unsigned char *volsetid, unsigned int volsetidlen){ return DVDUDFVolumeInfo(dvd, volid, volidlen, volsetid, volsetidlen);}int vm_get_iso_volids(char *volid, unsigned int volidlen, unsigned char *volsetid, unsigned int volsetidlen){ return DVDISOVolumeInfo(dvd, volid, volidlen, volsetid, volsetidlen);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -