Presented here is the Corporate Loop example project from tfdvd.com reauthored in TFDVDEdit 2.
This project plays up to four tracks continuously, such as for a trade show, allowing the user to choose which combination of tracks to play. The tracks, if played, are always played in the same sequence.
For this example we nuked the abstraction layer commands before beginning. We also used a binary bit for each title, which makes the implementation much easier than other methods.
For this project we used 7 registers, as follows:
R0 Scratch R1 Menu number, 1, 2, or 3 R2 Button number for menu 1, 1-3 R3 Button number for menu 2, 1-6 R4 Button number for menu 3, 1-11 R5 Current track bit mask, 1, 2, 4, or 8 R6 Play list bit mask, any 0-15
This project remembers the last button number activated, not counting the links between menus, for each menu. This results in each menu showing the last button that was used for that menu when it is reentered for any reason.
The values of 1, 2, 4, and 8 are significant because they are powers of two, which also means that they each have only one bit present. In binary they are:
1 0001 2 0010 4 0100 8 1000
What we are going to do with the play list mask is to turn on the appropriate bit for each title that we want to play. This yields the following possible play lists:
0 0000 Play nothing (not used in our example) 1 0001 Play title 1 2 0010 Play title 2 3 0011 Play titles 1 and 2 4 0100 Play title 3 5 0101 Play titles 1 and 3 6 0110 Play titles 2 and 3 7 0111 Play titles 1, 2, and 3 8 1000 Play title 4 9 1001 Play titles 1 and 4 10 1010 Play titles 2 and 4 11 1011 Play titles 1, 2, and 4 12 1100 Play titles 3 and 4 13 1101 Play titles 1, 3, and 4 14 1110 Play titles 2, 3, and 4 15 1111 Play all four titles
So, for each play button in each menu, all we need to do is select the correct value from the above list, and the Boolean logic in just two PGCs will do the rest.
First Play PGC
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:First Play PGC:" 1: Set r1 = 1 2: Set r2 = 1 3: Set r3 = 1 4: Set r4 = 1 5: Jump VTS 1 Menu Root
This initializes the menu and button registers to their default values, then jumps to the root menu in VTS 1. If you check the PGCs in VTS 1, only one menu will have the root designation. The other three PGCs, which are the three actual menus, are designated non-entry PGCs.
VTS 1 VTSM PGC 1 (root)
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Video Title Set Menus:Title Set 1 Menus:English (4 menus):VTSM PGC 1:" 1: if r1 <= 1 then Link PGC 2 2: if r1 == 2 then Link PGC 3 3: Link PGC 4
The root menu links to one of the three actual menus, depending on the value of r1.
VTS 1 VTSM PGC 2 (non-entry)
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Video Title Set Menus:Title Set 1 Menus:English (4 menus): VTSM PGC 2 (1 program):" 1: Set r0 = r2 2: Set r0 *= $400 3: Set Button r0 4: Set r1 = 1
This is the Title Menu, which offers three choices: to loop all of the tracks, to choose a single track, or to choose multiple tracks.
The pre commands decode the button number in r2 and highlights that button. Remember the button number must be multiplied by 1024 before storing in the system parameter, SPRM 8. Then it sets the menu number to 1, the first menu.
In DVDSP 2 we hooked up all of the buttons in all of the menus to something, even though we threw away the abstraction layer commands that were generated from doing this. This has the useful side-effect of generating a LinkTailPGC button command in each menu Nav pack, which transfers control to the PGCs post commands when the button is activated.
#PostCommands from "CorporateSimple:Video Title Set Menus:Title Set 1 Menus:English (4 menus): VTSM PGC 2 (1 program):" 1: Set r2 = Button 2: Set r2 /= $400 3: if r2 != 1 then GoTo Line 7 4: Set r5 = 1 5: Set r6 = $f 6: Jump VTS TT 1 7: if r2 != 2 then GoTo Line 9 8: Link PGC 3 9: if r2 != 3 then GoTo Line 11 10: Link PGC 4 11: Jump First Play
This reads the button number that was activated back out from SPRM 8 and divides by 1024 to get the simple button number. This is done directly in r2 so that the next time we enter this menu the same button that was activated will be selected when the menu is displayed.
Then if the first button was activated, (Loop All tracks), it sets r5 to 1. This means start at track 1, which is designated by the binary value 0001.
R6 is set to 15, all four bits on. This means play all four tracks.
It then jumps to the first title within the current VTS, which is VTS 1. This is because DVDSP 2 always puts all 4:3 menus in VTS 1. Since the track we want is also in the same VTS, we can jump there directly instead of navigating through the Video Manager domain which we will do when the target track is not in VTS 1.
If button 2 or 3 was activated, we link to another menu. The Jump to First Play is a safety valve in case the register had a value we didnt expect. It would be better practice to create a debugging menu for this purpose, so you could know for sure that you had a scripting error.
VTS 1 VTSM PGC 3 (non-entry)
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Video Title Set Menus:Title Set 1 Menus:English (4 menus): VTSM PGC 3 (1 program):" 1: Set r0 = r3 2: Set r0 *= $400 3: Set Button r0 4: Set r1 = 2
This menu offers to loop each one of the four tracks, link to a multiple track loop menu, or return to the title menu.
It uses r3 to choose which button to highlight, and sets r1 to indicate we are on the second menu.
#PostCommands from "CorporateSimple:Video Title Set Menus:Title Set 1 Menus:English (4 menus): VTSM PGC 3 (1 program):" 1: Set r0 = Button 2: Set r0 /= $400 3: if r0 != 5 then GoTo Line 5 4: Link PGC 4 5: if r0 != 6 then GoTo Line 7 6: Link PGC 2 7: Set r3 = r0 8: if r0 != 1 then GoTo Line 12 9: Set r5 = 1 10: Set r6 = 1 11: Jump VTS TT 1 12: if r0 != 2 then GoTo Line 16 13: Set r5 = 2 14: Set r6 = 2 15: Jump VMG PGC 2 16: if r0 != 3 then GoTo Line 20 17: Set r5 = 4 18: Set r6 = 4 19: Jump VMG PGC 2 20: if r0 != 4 then GoTo Line 24 21: Set r5 = 8 22: Set r6 = 8 23: Jump VMG PGC 2 24: Jump First Play
When the user activates a button, control is transferred to the post commands. Here we test which button was hit by using r0, not r3. This is so we do not destroy the current contents of r3 if we choose to link to another menu. That way, this menu will always remember the last single track that was played from this menu, or be set to the default of Track 1.
First we check for the link to the multiple tracks menu, or to return to the previous (Title) menu. Once we are sure that it is neither of these, we go ahead and set r3 for the next time.
Then for each of the possible four tracks, we set both r5 and r6 to the same value: 0001, 0010, 0100, or 1000. This will result in a single track looping forever or until the user hits a button on the remote. (We expect the Menu or Title button). We then link to the first of the Boolean logic PGCs.
VMG PGC 2
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Manager Menus:English (3 menus):VMG PGC 2:" 1: Set r0 = 1 2: if r5 & r0 then Jump TT 1 3: Set r0 = 2 4: if r5 & r0 then Jump TT 2 5: Set r0 = 4 6: if r5 & r0 then Jump TT 3 7: Set r0 = 8 8: if r5 & r0 then Jump TT 4 9: Jump First Play
Each pair of commands tests for the presence of a single bit in the current track register. It does so by doing a Boolean logical and with the value representing the bit we want to test for.
Because of restrictions in the DVD Spec on the format of commands, we must first put the value to be tested in another register; we cannot test directly for the value 1, for example, when combined with the Jump TT command.
So, what does r0 & r5 mean? It means, does at least one bit in the same position exist in both registers. It doesnt matter which register is named first or second, r0 & r5 means the same thing as r5 & r0.
Since we are concerned with only only four tracks, we can ignore the zeros that are in the high order bits of the two registers. Also since we know that only one bit can be present in each register (we deliberately set it up that way), the only possible legal values for r5 are:
0001 0010 0100 1000
The logical and says that the bit in each position is compared with the same bit in the other register, and if both bits are on, the resulting bit is set on. So we can see that in the very restricted case we are testing, the & comparison has the same result as the == comparison. We will give more examples in VMG PGC 3 when we get to it.
So, after testing the current track register, we jump to one of the Tracks. Each track is set up in exactly the same way, it plays through once and then control is passed to its post commands. Each track has exactly one and only one post command, and no other commands of any type.
VTS 1 PGC 1 TT1
VTS 2 PGC 1 TT1
VTS 3 PGC 1 TT1
VTS 4 PGC 1 TT1
#TFDVDEDIT Commands V1 #PostCommands from "CorporateSimple:Video Title Sets:VTS 1:PGC 1 TT 1:" 1: Call VMG PGC 3 resume C1
This transfers control to the Video Manager routing PGC, and saves the current resume point, cell 1 of the track.
VMG PGC 3 (non-entry)
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Manager Menus:English (3 menus):VMG PGC 3:" 1: Set r5 *= 2 2: if r5 <= r6 then GoTo Line 4 3: Set r5 = 1 4: if r5 & r6 then Link PGC 2 5: GoTo Line 1
This is the other Boolean logic PGC. Its purpose is to check the tracks in sequence starting from the track just played and find the next track to play.
First we multiply the current track value (remember, 1, 2, 4 or 8) by two. This is what is known in Boolean programming as shifting the register left by one position. Here are the possible results:
Before Shifted left 0001 0010 0010 0100 0100 1000 1000 10000
The next command compares the result to the play list mask, which can only have a value from 1 to 15. Since the play list mask must have contained the track just played, this command will branch (goto line 4) only if the result is possibly within the highest track number in the play list.
For example, if the play list is 0011 (play tracks 1 and 2) and the current track was 0001, it is becomes 0010 and that is less than 0011, so it branches. If the current track was 0010, it becomes 0100 and that is greater than 0011, so it does not branch.
If it did not branch, the current track is set to 0001, to start the testing all over again.
The next line does a logical and of the current track and the play list. If the bit in the current track is on in the play list, it links to PGC 2 and plays that track. If not, it repeats the entire command list.
Since we know the play list contains at least one bit, the loop is guaranteed to find a bit every time, even if it is the same bit it just played. (A single track was selected).
This concludes the Boolean logic. Once you understand these methods, they can be applied to many DVD authoring problems.
VTS 2 VTSM PGC 1
VTS 3 VTSM PGC 1
VTS 4 VTSM PGC 1
The remaining Video Title Set Menu PGCs are all identical, and are used to direct navigation back to the right place when the user hits the Menu Key on the remote. Note that these are all root menus.
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Video Title Set Menus:Title Set 4 Menus:English (1 menu):VTSM PGC 1:" 1: Jump VMG PGC 4
Since the DVD Spec prohibits direct jumps between Video Title Sets, we jump to the Video Manager in order to jump back to the root menu of VTS 1.
VMG PGC 4
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Manager Menus:English (4 menus):VMG PGC 4:" 1: Jump VTS 1 Menu Root
The only remaining PGC in the project is the Video Manager Title Menu, which is where navigation is directed when the user hits the Title Key on the remote.
VGM PGC 1
#TFDVDEDIT Commands V1 #PreCommands from "CorporateSimple:Manager Menus:English (4 menus):VMG PGC 1:" 1: Set r1 = 1 2: Jump VTS 1 Menu Root
We add the wrinkle here to set the current menu register r3 to the first menu, the Title Menu. Thus the Title Key on the remote will always take you back home, and the Menu Key on the remote will take you to the last menu visited.
Also notice that the Menu Key will toggle between playing the selected titles and returning to the menu where those titles were selected. That is because of the Call VMG PGC 3 resume C1 command that was executed after the playing of each track that command sets up the SPRMs to return execution to that track and cell when the Menu Key is hit. This example is much simpler than the abstraction layer version would have been, because only one set of variables are used, the memory variables are always self-consistent and represent a valid state of execution, and the commands are able to branch (jump, call, link, or goto) exactly the area they wish to.
Although this example uses seven registers, it could have compressed r1 through r4 into a single register if registers had been at a premium, using Boolean methods of bit extraction and replacement. A later example will illustrate these methods.