- // g0: scratch
- // g1: target menu location
- // g2: source/return menu location for title
- // g3: target chapter number
- //
- // All locations are divided into two bitfields: the least
- // significant 10 bits are a page/menu number and the most
- // significant 6 bits are a link/button number, and numbering
- // starts at 1, not 0. This is done for compatibility with
- // the encoding of the s8 (button) register.
- //
- static const int button_mult = dvd::reg_s8_button_mult;
- static const int menu_mask = button_mult - 1;
- static const int button_mask = (1 << dvd::reg_bits) - button_mult;
-
- file <<
- "<dvdauthor>\n"
- " <vmgm>\n"
- " <menus>\n";
-
- for (unsigned menu_index = 0; menu_index != menus_.size(); ++menu_index)
+ // g0: Scratch.
+ // g1: Target location when jumping between menus. Top 6 bits are
+ // the button number (like s8) and bottom 10 bits are the menu
+ // number. This is used for selecting the appropriate button
+ // when entering a menu, for completing indirect jumps between
+ // domains, and for jumping to the correct menu after exiting a
+ // title. This is set to 0 in the pre-routine of the target
+ // menu.
+ // g2: Current location in menus. This is used for jumping to the
+ // correct menu when the player exits a title.
+ // g3: Target chapter number plus 1 when jumping to a title.
+ // This is used to jump to the correct chapter and to
+ // distinguish between indirect jumps to menus and titles.
+ // This is set to 0 in the pre-routine of the target title.
+ // g4: Source menu location used to jump to a title. This is
+ // compared with g2 to determine whether to increment the
+ // button number if the title is played to the end.
+
+ static const unsigned button_mult = dvd::reg_s8_button_mult;
+ static const unsigned menu_mask = button_mult - 1;
+ static const unsigned button_mask = (1U << dvd::reg_bits) - button_mult;
+
+ // Iterate over VMGM and titlesets. For these purposes, we
+ // consider the VMGM to be titleset 0.
+
+ // We need a titleset for each title, and we may also need titlesets to
+ // hold extra menus if we have too many for the VMGM.
+ // Also, we need at least one titleset.
+ const unsigned titleset_end = std::max<unsigned>(
+ 1U + std::max<unsigned>(1U, titles_.size()),
+ (menus_.size() + dvdauthor_anonymous_menus_max - 1)
+ / dvdauthor_anonymous_menus_max);
+
+ for (unsigned titleset_num = 0;
+ titleset_num != titleset_end;
+ ++titleset_num)