A DVD Studio Pro script for playing one track out of 16 tracks at random. The script won’t play a track twice unless all tracks have been played.

So you have made a few short films you want to show around, let’s say 16 of them. You create a nice DVD in DVD Studio Pro but now you want a random button. This button should show the viewer one random movie out of your 16 masterworks, and it should remember which ones it has already played. You start looking at the manual, you start looking around the internet but all you can find are pointers to expensive tutorials and scripts for random play with 3 tracks.

This can’t be that hard, you think, but actually it is. The easy part is the random choice: DVD Studio Pro has a ran function for that. The hard part is remembering which movie has been played. DVD Studio Pro has only 8 registers to use. And you have 16 movies to show.

But every register is 16 bits long. This means that you can remember 16 tracks in one register. My script does exactly that, and it is expandable to 32 or 48 tracks if you want.

Jump to download section

Register layout

Before we continue with the script, let me explain the register layout.

register layout

I tend to give my registers names because this eases reading and writing scripts a lot. I start allocating the registers on top for temporary use and the ones at the bottom for permanent duty. In this case we have 3 temp registers (GRPM 0 to 2) which can be reused by other scripts, and one global register (Random_mask) containing the tracks played.

Random_mask is a bitmask containing the tracks we already played. 1 means “played”, 0 means unplayed. 0000 0010 0000 0100 means track 10 and 3 have been played. If you are a bit rusty with binary numbers and bitmasks, read this article by David Nagel first. I have to warn you that loading the site may cause your browser to explode, but it has to be said that David Nagel’s articles on DVD Studio Pro are among the best on the net.

The script

Here it is:

the script header the script 1 the script 2 the script 3 the script 4 the script 5 the script footer

The script is divided in 5 mayor parts. I put a Nop-separator between each part.

Part 1: input and safety check.

the script 1

Line 1 is a safety check. Random_mask will be all ones if all tracks have been played. (1111 1111 1111 1111 in binary is equal to 65535 in decimal.) We need to reset Random_mask, otherwise the script will keep on looking for a new random track that hasn’t been played. This causes an endless loop which your viewers will enterprete as a DVD that “hangs”.

Line 2 chooses a number between 1 and 16 and puts it in tmp_random_track.

Part 2: creation of the bitmask

the script 2

In this part the script creates the bitmask that represents our currently chosen tmp_random_track. The way to do this is pretty easy: start with a bitmask with 1 bit at the extreme right (line 4) and keep shifting it to the left until it’s at its place. Multiplying a number by 2 is the equivalent of a shift to the left in binary (multiplying by 10 is the same as a shift to the left in decimal).

In pseudo-code the algorithm looks a bit like this:

tmp_mask = 1;
tmp_counter = tmp_random_track;
while (tmp_counter > 1) {
   tmp_mask = tmp_mask * 2;
   tmp_counter = tmp_counter - 1;
}

The actual implementation is a bit different to get the main loop (lines 7 to 9) as tight as possible. (I just couldn’t resist writing a script that goes to eleven…)

After this part, tmp_mask contains the bitmask representing our random track: e.g. 0000 0000 0000 0100 if tmp_random_track is equal to 3.

Part 3: check if the track has already been played

the script 3

This is the part where we did all this trouble for: check if we haven’t already played the track we chose. If it weren’t for this, line 2 would be sufficient on its own. Since we have the bitmask we can simply AND it with Random_mask and see if there’s our bit is on. Remember, 0 AND 0 = 0, 1 AND 0 = 0, 0 AND 1 = 0 but 1 AND 1 = 1. So, if the result of tmp_maskAND Random_mask contains a 1, it must be our bit. In other words, we have already played the track. If so, we choose another track (line 13, Goto 2 if ...).

The only trouble is that the and operation in DVD Studio Pro destroys one of both registers. That’s why I copy the mask to tmp_counter, as we need tmp_mask in the next part.

Part 4: registration of the chosen track

the script 4

Here we set the bit of the track we’re going to play in Random_mask. The operation we use is OR, since 0 OR 0 = 0, but 1 OR 0 = 1, 0 OR 1 = 1 and 1 0R 1 = 1.

Part 5: jump to the chosen track

the script 5

This code adjusts the random_track number. Before we have a tracknumber between 1 and 16, afterwards we have a track number between 49280 and 51200. Then the script jumps to this number. It looks like magic and it is a bit magic.

I learned of these numbers through David Nagel’s articles. DVD Studio Pro gives every item a number behind the scenes. Tracks are numbered starting from 49280 (0xC080) and upward. They’re spaced 128 (0×80) magic units apart. This means that 49280 (0xC080) is the first track in your outline, 49408 (0xC100) is the next one and so on. You can jump straight to a track once you know its number with Jump Indirect.

Menu are numbered from 32 (0×20), spaced 32 units (0×20) apart (32, 64, 96, … or 0×20, 0×40, 0×60, …) and buttons are numbered from 0 to … within the menu . Add the number of a button to the menu it’s in and you can jump straight to it (f.i. Jump Indirect(35) jumps to the fourth button in Menu 1).

Download and adjust.

You can download the script from here. Unzip it. Load it into DVD Studio Pro by right clicking on a script and choosing “Load script”. Sadly, you may have to adjust the script. My ancient 2.0 version keeps forgetting the registers. Make sure the script looks absolutely the same as above.

Less than 16 tracks?

part 1 explained

You need to adjust 2 lines if you have less than 16 tracks to choose from. Obviously, you need to change the 16 in line 2 to the actual number of tracks. But you also need to adjust the limit (65535 in line 1) for your actual number of tracks. Failure to do so may cause endless loops, hanging DVDs and general infertility. Here’s the table to guide you:

# tracks limit (2#tracks-1)
1 1
2 3
3 7
4 15
5 31
6 63
7 127
8 255
9 511
10 1023
11 2047
12 4095
13 8191
14 16383
15 32767
16 65535

More than 16 tracks?

If you have more than 16 tracks you will need a second Random_mask. Use the first one for tracks 1-16 and the second one for 17 and higher. You will need to alter the safety check in part 1 and basically duplicate all of part 2, 3 and 4 for Random_mask_2.

Running time

The runtime complexity of this script is O(n2). That means that the script may take a long time to find the last unplayed track if the number of tracks is large (>> 16).