//
// g0: scratch
// g1: current location
- // g12: location that last jumped to a video
+ // g2: location that last jumped to a 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
" <vmgm>\n"
" <menus>\n";
- for (unsigned menu_num = 0;
- menu_num != contents.menus.size();
- ++menu_num)
+ for (unsigned menu_index = 0;
+ menu_index != contents.menus.size();
+ ++menu_index)
{
- const dvd_contents::menu & menu = contents.menus[menu_num];
+ const dvd_contents::menu & menu = contents.menus[menu_index];
- if (menu_num == 0)
+ if (menu_index == 0)
{
// This is the first (title) menu, displayed when the
// disc is first played.
menu_incr != 0;
menu_incr /= 2)
{
- if (menu_num + menu_incr < contents.menus.size()
- && (menu_num & (menu_incr * 2 - 1)) == 0)
+ if (menu_index + menu_incr < contents.menus.size()
+ && (menu_index & (menu_incr * 2 - 1)) == 0)
{
file <<
- " if (g0 ge " << 1 + menu_num + menu_incr
+ " if (g0 ge " << 1 + menu_index + menu_incr
<< ")\n"
- " jump menu " << 1 + menu_num + menu_incr
+ " jump menu " << 1 + menu_index + menu_incr
<< ";\n";
}
}
" </pre>\n"
" <vob file='" << menu.vob_temp->get_name() << "'/>\n";
- for (unsigned button_num = 0;
- button_num != menu.entries.size();
- ++button_num)
+ for (unsigned button_index = 0;
+ button_index != menu.entries.size();
+ ++button_index)
{
const dvd_contents::pgc_ref & target =
- menu.entries[button_num];
+ menu.entries[button_index];
file << " <button> ";
target_menu_entries =
contents.menus[target.index].entries;
dvd_contents::pgc_ref this_pgc(dvd_contents::menu_pgc,
- menu_num);
+ menu_index);
target_button_num = target_menu_entries.size();
while (target_button_num != 0
- && (target_menu_entries[--target_button_num]
+ && (target_menu_entries[target_button_num - 1]
!= this_pgc))
- ;
- target_button_num += 1;
+ --target_button_num;
}
- file << "g1 = "
- << (1 + target.index
- + target_button_num * button_mult)
- << "; jump menu " << 1 + target.index << ";";
+ file <<
+ // Set new menu location.
+ "g1 = " << (1 + target.index
+ + target_button_num * button_mult) << "; "
+ // Jump to the target menu.
+ "jump menu " << 1 + target.index << "; ";
}
else
{
assert(target.type == dvd_contents::title_pgc);
- file << "g1 = "
- << 1 + menu_num + (1 + button_num) * button_mult
- << "; jump title "
- << 1 + target.index;
- // FIXME: Here we should check target.sub_index and
- // jump to a specific chapter if it is non-zero.
- // However, we can't jump directly to chapters from
- // the VMGM.
- file << ";";
+ file <<
+ // Record current menu location (g1 specifies this
+ // menu but not necessarily this button).
+ "g1 = " << (1 + menu_index
+ + (1 + button_index) * button_mult) << "; "
+ // Set target chapter number.
+ "g3 = " << target.sub_index << "; "
+ // Jump to the target title.
+ "jump title " << 1 + target.index << "; ";
}
- file << " </button>\n";
+ file << "</button>\n";
}
file <<
// Generate a titleset for each title. This appears to make
// jumping to titles a whole lot simpler (but limits us to 99
// titles).
- for (unsigned title_num = 0;
- title_num != contents.titles.size();
- ++title_num)
+ for (unsigned title_index = 0;
+ title_index != contents.titles.size();
+ ++title_index)
{
file <<
" <titleset>\n"
" </menus>\n"
" <titles>\n"
" <pgc>\n"
+ " <pre>\n"
// Record calling location.
- " <pre> g12 = g1; </pre>\n";
+ " g2 = g1;\n";
- for (vob_list::const_iterator it = contents.titles[title_num].begin(),
- end = contents.titles[title_num].end();
+ // Count chapters in the title.
+ unsigned n_chapters = 0;
+ for (vob_list::const_iterator
+ it = contents.titles[title_index].begin(),
+ end = contents.titles[title_index].end();
+ it != end;
+ ++it)
+ {
+ // Chapter start times may be specified in the "chapters"
+ // attribute as a comma-separated list. If this is not
+ // specified then the beginning of each file starts a new
+ // chapter. Thus the number of chapters in each file is
+ // the number of commas in the chapter attribute, plus 1.
+ ++n_chapters;
+ std::size_t pos = 0;
+ while ((pos = it->chapters.find(',', pos)) != std::string::npos)
+ {
+ ++n_chapters;
+ ++pos;
+ }
+ }
+
+ // Generate jump "table" for chapters.
+ for (unsigned chapter_num = 1;
+ chapter_num <= n_chapters;
+ ++chapter_num)
+ file <<
+ " if (g3 == " << chapter_num << ")\n"
+ " jump chapter " << chapter_num << ";\n";
+
+ file <<
+ " </pre>\n";
+
+ for (vob_list::const_iterator
+ it = contents.titles[title_index].begin(),
+ end = contents.titles[title_index].end();
it != end;
++it)
{
}
file <<
+ " <post>\n"
// If the menu location has not been changed during
// the title, set the location to be the following
- // button in the menu. In any case, return to some
- // menu.
- " <post> if (g1 eq g12) g1 = g1 + " << button_mult
- << "; call menu; </post>\n"
+ // button in the menu.
+ " if (g1 eq g2)\n"
+ " g1 = g1 + " << button_mult << ";\n"
+ // In any case, return to some menu.
+ " call menu;\n"
+ " </post>\n"
" </pgc>\n"
" </titles>\n"
" </titleset>\n";