comparison vm/vm.c @ 412:34e632fb6a39 src

Prevent abort if a menu doesn't exist. From John Stebbins original email on the patch: This patch prevents an abort when a nav command tries to send you to a menu that doesn't exist. Mac the ripper's feature title extraction removes menus from the resulting image, but does not remove navigation instructions that attempt to jump to those menus. This patch checks that a menu exists before acting on such instructions. If the menu does not exist, it puts the vm into the stopped state. Thanks goes to John Stebbins for the original send of this patch and noticing that I introduced a bug when attempting to streamline this patch. Finally, he has guided this patch and many more for an extended period of time. Thanks again John.
author erik
date Sun, 21 Nov 2010 23:59:43 +0000
parents ce9b314b6e43
children fe65a31e707a
comparison
equal deleted inserted replaced
411:ce9b314b6e43 412:34e632fb6a39
607 case VTSM_DOMAIN: 607 case VTSM_DOMAIN:
608 case VMGM_DOMAIN: 608 case VMGM_DOMAIN:
609 switch(menuid) { 609 switch(menuid) {
610 case DVD_MENU_Title: 610 case DVD_MENU_Title:
611 case DVD_MENU_Escape: 611 case DVD_MENU_Escape:
612 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) {
613 return 0;
614 }
612 (vm->state).domain = VMGM_DOMAIN; 615 (vm->state).domain = VMGM_DOMAIN;
613 break; 616 break;
614 case DVD_MENU_Root: 617 case DVD_MENU_Root:
615 case DVD_MENU_Subpicture: 618 case DVD_MENU_Subpicture:
616 case DVD_MENU_Audio: 619 case DVD_MENU_Audio:
617 case DVD_MENU_Angle: 620 case DVD_MENU_Angle:
618 case DVD_MENU_Part: 621 case DVD_MENU_Part:
622 if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) {
623 return 0;
624 }
619 (vm->state).domain = VTSM_DOMAIN; 625 (vm->state).domain = VTSM_DOMAIN;
620 break; 626 break;
621 } 627 }
622 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) 628 if(get_PGCIT(vm) && set_MENU(vm, menuid)) {
623 return 0;
624 else if(get_PGCIT(vm) && set_MENU(vm, menuid)) {
625 process_command(vm, play_PGC(vm)); 629 process_command(vm, play_PGC(vm));
626 return 1; /* Jump */ 630 return 1; /* Jump */
627 } else { 631 } else {
628 (vm->state).domain = old_domain; 632 (vm->state).domain = old_domain;
629 } 633 }
1435 /* PGC Pre-Commands are not executed */ 1439 /* PGC Pre-Commands are not executed */
1436 assert((vm->state).domain == VTS_DOMAIN); 1440 assert((vm->state).domain == VTS_DOMAIN);
1437 if(link_values.data2 != 0) 1441 if(link_values.data2 != 0)
1438 (vm->state).HL_BTNN_REG = link_values.data2 << 10; 1442 (vm->state).HL_BTNN_REG = link_values.data2 << 10;
1439 if(!set_VTS_PTT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG, link_values.data1)) 1443 if(!set_VTS_PTT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG, link_values.data1))
1440 assert(0); 1444 link_values.command = Exit;
1441 link_values = play_PG(vm); 1445 else
1446 link_values = play_PG(vm);
1442 break; 1447 break;
1443 case LinkPGN: 1448 case LinkPGN:
1444 /* Link to Program Number:data1 */ 1449 /* Link to Program Number:data1 */
1445 /* BUTTON number:data2 */ 1450 /* BUTTON number:data2 */
1446 if(link_values.data2 != 0) 1451 if(link_values.data2 != 0)
1481 /* or the Video Title Set Domain(VTS) */ 1486 /* or the Video Title Set Domain(VTS) */
1482 /* Stop SPRM9 Timer */ 1487 /* Stop SPRM9 Timer */
1483 /* Set SPRM1 and SPRM2 */ 1488 /* Set SPRM1 and SPRM2 */
1484 assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */ 1489 assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */
1485 if(!set_VTS_TT(vm, (vm->state).vtsN, link_values.data1)) 1490 if(!set_VTS_TT(vm, (vm->state).vtsN, link_values.data1))
1486 assert(0); 1491 link_values.command = Exit;
1487 link_values = play_PGC(vm); 1492 else
1493 link_values = play_PGC(vm);
1488 break; 1494 break;
1489 case JumpVTS_PTT: 1495 case JumpVTS_PTT:
1490 /* Jump to Part:data2 of Title:data1 in same VTS Title Domain */ 1496 /* Jump to Part:data2 of Title:data1 in same VTS Title Domain */
1491 /* Only allowed from the VTS Menu Domain(VTSM) */ 1497 /* Only allowed from the VTS Menu Domain(VTSM) */
1492 /* or the Video Title Set Domain(VTS) */ 1498 /* or the Video Title Set Domain(VTS) */
1493 /* Stop SPRM9 Timer */ 1499 /* Stop SPRM9 Timer */
1494 /* Set SPRM1 and SPRM2 */ 1500 /* Set SPRM1 and SPRM2 */
1495 assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */ 1501 assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */
1496 if(!set_VTS_PTT(vm, (vm->state).vtsN, link_values.data1, link_values.data2)) 1502 if(!set_VTS_PTT(vm, (vm->state).vtsN, link_values.data1, link_values.data2))
1497 assert(0); 1503 link_values.command = Exit;
1498 link_values = play_PGC_PG(vm, (vm->state).pgN); 1504 else
1505 link_values = play_PGC_PG(vm, (vm->state).pgN);
1499 break; 1506 break;
1500 1507
1501 case JumpSS_FP: 1508 case JumpSS_FP:
1502 /* Jump to First Play Domain */ 1509 /* Jump to First Play Domain */
1503 /* Only allowed from the VTS Menu Domain(VTSM) */ 1510 /* Only allowed from the VTS Menu Domain(VTSM) */
1511 case JumpSS_VMGM_MENU: 1518 case JumpSS_VMGM_MENU:
1512 /* Jump to Video Manager domain - Title Menu:data1 or any PGC in VMG */ 1519 /* Jump to Video Manager domain - Title Menu:data1 or any PGC in VMG */
1513 /* Allowed from anywhere except the VTS Title domain */ 1520 /* Allowed from anywhere except the VTS Title domain */
1514 /* Stop SPRM9 Timer and any GPRM counters */ 1521 /* Stop SPRM9 Timer and any GPRM counters */
1515 assert((vm->state).domain != VTS_DOMAIN); /* ?? */ 1522 assert((vm->state).domain != VTS_DOMAIN); /* ?? */
1523 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) {
1524 link_values.command = Exit;
1525 break;
1526 }
1516 (vm->state).domain = VMGM_DOMAIN; 1527 (vm->state).domain = VMGM_DOMAIN;
1517 if(!set_MENU(vm, link_values.data1)) 1528 if(!set_MENU(vm, link_values.data1))
1518 assert(0); 1529 assert(0);
1519 link_values = play_PGC(vm); 1530 link_values = play_PGC(vm);
1520 break; 1531 break;
1527 /* get_MENU:data3 */ 1538 /* get_MENU:data3 */
1528 if(link_values.data1 != 0) { 1539 if(link_values.data1 != 0) {
1529 if (link_values.data1 != (vm->state).vtsN) { 1540 if (link_values.data1 != (vm->state).vtsN) {
1530 /* the normal case */ 1541 /* the normal case */
1531 assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */ 1542 assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */
1532 (vm->state).domain = VTSM_DOMAIN;
1533 if (!ifoOpenNewVTSI(vm, vm->dvd, link_values.data1)) /* Also sets (vm->state).vtsN */ 1543 if (!ifoOpenNewVTSI(vm, vm->dvd, link_values.data1)) /* Also sets (vm->state).vtsN */
1534 assert(0); 1544 assert(0);
1545 if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) {
1546 link_values.command = Exit;
1547 break;
1548 }
1549 (vm->state).domain = VTSM_DOMAIN;
1535 } else { 1550 } else {
1536 /* This happens on some discs like "Captain Scarlet & the Mysterons" or 1551 /* This happens on some discs like "Captain Scarlet & the Mysterons" or
1537 * the German RC2 of "Anatomie" in VTSM. */ 1552 * the German RC2 of "Anatomie" in VTSM. */
1538 assert((vm->state).domain == VTSM_DOMAIN || 1553 assert((vm->state).domain == VTSM_DOMAIN ||
1539 (vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */ 1554 (vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */
1555 if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) {
1556 link_values.command = Exit;
1557 break;
1558 }
1540 (vm->state).domain = VTSM_DOMAIN; 1559 (vm->state).domain = VTSM_DOMAIN;
1541 } 1560 }
1542 } else { 1561 } else {
1543 /* This happens on 'The Fifth Element' region 2. */ 1562 /* This happens on 'The Fifth Element' region 2. */
1544 assert((vm->state).domain == VTSM_DOMAIN); 1563 assert((vm->state).domain == VTSM_DOMAIN);
1556 break; 1575 break;
1557 case JumpSS_VMGM_PGC: 1576 case JumpSS_VMGM_PGC:
1558 /* set_PGCN:data1 */ 1577 /* set_PGCN:data1 */
1559 /* Stop SPRM9 Timer and any GPRM counters */ 1578 /* Stop SPRM9 Timer and any GPRM counters */
1560 assert((vm->state).domain != VTS_DOMAIN); /* ?? */ 1579 assert((vm->state).domain != VTS_DOMAIN); /* ?? */
1580 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) {
1581 link_values.command = Exit;
1582 break;
1583 }
1561 (vm->state).domain = VMGM_DOMAIN; 1584 (vm->state).domain = VMGM_DOMAIN;
1562 if(!set_PGCN(vm, link_values.data1)) 1585 if(!set_PGCN(vm, link_values.data1))
1563 assert(0); 1586 assert(0);
1564 link_values = play_PGC(vm); 1587 link_values = play_PGC(vm);
1565 break; 1588 break;
1575 case CallSS_VMGM_MENU: 1598 case CallSS_VMGM_MENU:
1576 /* set_MENU:data1 */ 1599 /* set_MENU:data1 */
1577 /* set_RSMinfo:data2 */ 1600 /* set_RSMinfo:data2 */
1578 assert((vm->state).domain == VTS_DOMAIN); /* ?? */ 1601 assert((vm->state).domain == VTS_DOMAIN); /* ?? */
1579 /* Must be called before domain is changed */ 1602 /* Must be called before domain is changed */
1603 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) {
1604 link_values.command = Exit;
1605 break;
1606 }
1580 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); 1607 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
1581 (vm->state).domain = VMGM_DOMAIN; 1608 (vm->state).domain = VMGM_DOMAIN;
1582 if(!set_MENU(vm, link_values.data1)) 1609 if(!set_MENU(vm, link_values.data1))
1583 assert(0); 1610 assert(0);
1584 link_values = play_PGC(vm); 1611 link_values = play_PGC(vm);
1586 case CallSS_VTSM: 1613 case CallSS_VTSM:
1587 /* set_MENU:data1 */ 1614 /* set_MENU:data1 */
1588 /* set_RSMinfo:data2 */ 1615 /* set_RSMinfo:data2 */
1589 assert((vm->state).domain == VTS_DOMAIN); /* ?? */ 1616 assert((vm->state).domain == VTS_DOMAIN); /* ?? */
1590 /* Must be called before domain is changed */ 1617 /* Must be called before domain is changed */
1618 if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) {
1619 link_values.command = Exit;
1620 break;
1621 }
1591 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); 1622 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
1592 (vm->state).domain = VTSM_DOMAIN; 1623 (vm->state).domain = VTSM_DOMAIN;
1593 if(!set_MENU(vm, link_values.data1)) 1624 if(!set_MENU(vm, link_values.data1))
1594 assert(0); 1625 assert(0);
1595 link_values = play_PGC(vm); 1626 link_values = play_PGC(vm);
1597 case CallSS_VMGM_PGC: 1628 case CallSS_VMGM_PGC:
1598 /* set_PGC:data1 */ 1629 /* set_PGC:data1 */
1599 /* set_RSMinfo:data2 */ 1630 /* set_RSMinfo:data2 */
1600 assert((vm->state).domain == VTS_DOMAIN); /* ?? */ 1631 assert((vm->state).domain == VTS_DOMAIN); /* ?? */
1601 /* Must be called before domain is changed */ 1632 /* Must be called before domain is changed */
1633 if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) {
1634 link_values.command = Exit;
1635 break;
1636 }
1602 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); 1637 set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
1603 (vm->state).domain = VMGM_DOMAIN; 1638 (vm->state).domain = VMGM_DOMAIN;
1604 if(!set_PGCN(vm, link_values.data1)) 1639 if(!set_PGCN(vm, link_values.data1))
1605 assert(0); 1640 assert(0);
1606 link_values = play_PGC(vm); 1641 link_values = play_PGC(vm);
1657 pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn; 1692 pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn;
1658 1693
1659 (vm->state).TT_PGCN_REG = pgcN; 1694 (vm->state).TT_PGCN_REG = pgcN;
1660 (vm->state).PTTN_REG = part; 1695 (vm->state).PTTN_REG = part;
1661 (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn); 1696 (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn);
1662 assert( (vm->state.TTN_REG) != 0 ); 1697 if( (vm->state.TTN_REG) == 0 )
1698 return 0;
1699
1663 (vm->state).VTS_TTN_REG = vts_ttn; 1700 (vm->state).VTS_TTN_REG = vts_ttn;
1664 (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */ 1701 (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */
1665 /* Any other registers? */ 1702 /* Any other registers? */
1666 1703
1667 res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */ 1704 res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */