alt.sources
by DaviD W. Sanderson (but note that he is not the
original author of these programs). I then used these to reverse-engineer
the British VideoPlus system by writing a program in BASIC
for the Sinclair
Spectrum (no really, it's true!).
Steve Hosgood has a DOS version of the VideoPlus system (which can be configured for UK or US) including C source and some information about the difference between UK and US systems, in case Spectrum BASIC is not your forté.
There is also a program with some documentation by Paul Balyoz.
The paper that started it all off was written by Ken Shirriff, Curt Welch and Andy Kinsman. Curt Welch's projects page has a bit of information about the history of that paper and some links.
The program does not cope well with numbers longer than 6 digits. This is because the encryption algorithm seems to differ significantly for the longer codes and no one has so far been able to reverse-engineer it.
Most of the tables of start and end times are contained within the program. The tables that are loaded in are just the first 192 elements which are in a more or less random order and can be seen as individual assignments in the C programs.
Since this is a Spectrum program, you can also get a snapshot file (compressed) which you can run on a spectrum emulator.
1 CLEAR 39999 10 GO SUB 1000 20 INPUT LINE a$: PRINT a$;: LET b$="68150631": GO SUB 1120: PRINT " ->";a$; 30 IF LEN a$>2 THEN LET b$=a$( LEN a$-2 TO ): LET t$=a$( TO LEN a$-3): GO TO 40 35 LET b$=a$: LET t$="" 40 LET x= VAL b$-1: LET quo= INT (x/32): LET rem=x-32*quo: LET day=quo+1 45 IF day<td THEN LET tm=tm+1: IF tm>12 THEN LET tm=tm-12: LET ty=ty+1 50 IF LEN a$ >= 4 THEN GO SUB 1160: GO TO 70 60 LET ofout=0: LET t$="0" 70 PRINT "." 75 LET t2c1=rem+day*(tm+1)+ofout: LET t8c5= VAL t$ 77 IF LEN a$>6 THEN PRINT "Date=";day;"/";tm;"/";ty'"Can't decode this long number": GO TO 140 80 GO SUB 1380 81 LET cc=cval: LET tt=tval 90 LET chan=cval+1 100 PRINT "Date=";day;"/";tm;"/";ty;" Channel=";chan;" (t=";tt;")" 110 GO SUB 1440 120 LET s$= STR$ s: LET s$=("000"+s$)( LEN s$ TO ): LET s$=s$( TO 2)+":"+s$(3 TO ) 130 IF l>0 THEN PRINT "Time=";s$;" Length=";l 140 REM PRINT t$;",";t2c1-32* INT (t2c1/32) 200 GO TO 10 899 STOP 900 PRINT INVERSE 1;a$;: LET b$="9371": GO SUB 1120: PRINT , INVERSE 1;a$ 999 STOP 1000 REM *set time* 1010 LET times=40500: LET lens=40100 1020 IF PEEK 40000=56 THEN LET td= PEEK 40001: LET tm= PEEK 40002: LET ty= PEEK 40003: RETURN 1030 INPUT "Today's date:";td,"Month:";tm,"Year:";ty 1035 IF ty >= 1900 THEN LET ty=ty-1900 1040 POKE 40001,td: POKE 40002,tm: POKE 40003,ty: POKE 40000,56: GO TO 5000: RETURN 1050 REM *mixup* c$=mix(a$,b$) 1060 LET a$="00000000"( LEN a$ TO )+a$: LET b$="00000000"( LEN b$ TO )+b$: LET c$="000000000" 1070 FOR i=1 TO 9: FOR j=10-i TO 9 1080 LET ij=i+j-9: LET d= CODE c$(ij)+( CODE a$(i)-48)*( CODE b$(j)-48) 1090 IF d>57 THEN LET d=d-10* INT ((d-48)/10) 1100 LET c$(ij)= CHR$ d 1110 NEXT j: NEXT i: RETURN 1120 REM *f1* encode a$ with b$ 1130 LET n= LEN a$: IF n>8 THEN PRINT "Input ";a$;" is too long": STOP 1140 GO SUB 1050: LET a$=c$(10-n TO ): IF a$(1)="0" THEN GO TO 1140 1150 RETURN 1160 REM *offset* (ofout,t$)=offset(day,ty,t$) 1170 LET off=0: LET d= LEN t$: FOR i=1 TO d: LET off=off+ CODE t$(i)-48: NEXT i 1180 FOR i=0 TO ty-16* INT (ty/16): PRINT ".";: GO SUB 1220: LET off=off+ CODE u$(3)-48: NEXT i 1190 LET t$= STR$ VAL u$: IF LEN t$<d THEN GO TO 1180 1200 LET ofout=off-32* INT (off/32) 1210 RETURN 1220 REM *maptop* u$=m(day,i,t$,d) 1225 LET u$=("000"+t$)(1+ LEN t$ TO ) 1226 IF d>3 THEN RETURN 1230 LET y=i-16* INT (i/16): LET d2= CODE u$-48: LET d1= CODE u$(2)-48: LET d0= CODE u$(3)-48 1240 LET f0=1: LET f1=y+1: LET f2=f1*(y+2)/2: LET f3=f2*(y+3)/3 1250 LET f1=f1-10* INT (f1/10) 1260 LET f2=f2-10* INT (f2/10) 1270 LET f3=f3-10* INT (f3/10) 1279 LET n0=0: LET n1=0: LET n2=0 1280 IF d=1 THEN LET n0=d0*f0+day*f1 1290 IF d=2 THEN LET n0=d0*f0+d1*f1+day*f2: LET n1=d1*f0+day*f1 1300 IF d=3 THEN LET n0=d0*f0+d1*f1+d2*f2+day*f3: LET n1=d1*f0+d2*f1+day*f2: LET n2=d2*f0+day*f1 1310 LET u$=( STR$ n2)( LEN STR$ n2)+( STR$ n1)( LEN STR$ n1)+( STR$ n0)( LEN STR$ n0) 1320 RETURN 1330 REM *binary* x$=bin(x)[len y] 1340 LET x$="": FOR i=1 TO y 1350 LET x$= STR$ (x-2* INT (x/2))+x$: LET x= INT (x/2) 1360 NEXT i 1370 RETURN 1380 REM *bit shuffle* 1390 LET x=t2c1: LET y=5: GO SUB 1330: LET y$=x$: LET x=t8c5: LET y=10: GO SUB 1330 1400 REM LET v$=x$(1)+x$(3)+x$(5)+x$(6)+x$(7)+x$(10)+y$(1)+y$(3)+y$(5): LET w$=x$(2)+x$(4)+x$(8)+x$(9)+y$(2)+y$(4) 1410 LET v$=x$(1)+x$(2)+x$(3)+x$(4)+x$(5)+x$(6)+x$(7)+x$(10)+y$(1)+y$(3)+y$(5): LET w$=x$(8)+x$(9)+y$(2)+y$(4) 1420 LET tval= VAL (" BIN "+v$): LET cval= VAL (" BIN "+w$) 1430 RETURN 1440 REM look up tval for s,l 1450 IF tval<192 THEN LET s= PEEK (times+tval*2)+256* PEEK (times+1+tval*2): LET l= PEEK (lens+tval*2)+256* PEEK (lens+1+tval*2): RETURN 1460 IF tval<384 THEN LET l= INT (tval/48-3)*30: LET s=tval-48* INT (tval/48): LET s=100* INT (s/2)+(30 AND s/2 <> INT (s/2))+15: RETURN 1470 IF tval >= 1914 THEN LET s=tval-1674: LET l= INT (s/48)*30: LET s=s-48* INT (s/48): LET s=2330-100* INT (s/2)-(30 AND s/2 <> INT (s/2)): RETURN 1480 IF tval<486 THEN LET tval=tval+1530 1490 LET v=tval-486: LET h= INT (v/34): LET v=v-34*h: LET v=v+1+(v>1) 1500 RESTORE 1600: FOR i=0 TO h: READ s,l: NEXT i 1510 LET l=l-5* INT (v/6): LET s=s+5*(v-6* INT (v/6)) 1520 RETURN 1600 DATA 1930,90,2300,90,2330,90,2130,120,2200,120,2300,120,2330,120,0,120,30,120,100,120,130,120 1610 DATA 1730,60,1800,60,1830,60,1900,60,1930,60,2000,60,2030,60 1620 DATA 200,120,230,120,300,120,330,120,400,120,1200,120,1400,120,1530,120 1630 DATA 2100,60,2130,60,2200,60,2230,60,2300,60,2330,60 1640 DATA 1730,30,1800,30,1830,30,1900,30,1930,30,2000,30,2030,30,2100,30,2130,30,2200,30,2230,30,2300,30,2330,30 4000 LET l=0: LET s=0: RETURN 4990 REM Initialise tables 5000 LOAD "vlengths" CODE lens: LOAD "vstarts" CODE times 5010 RETURN 6000 LET t=9: FOR x=128 TO 191: PRINT PEEK (41200+2*x)+256* PEEK (41201+2*x);","; PEEK (40100+2*x); TAB t;: LET t=t+9-(27 AND t=18): NEXT x 7000 INPUT x;",";z: LET y=18: GO SUB 1330: PRINT x$;" ";: LET x=z: LET y=5: GO SUB 1330: PRINT x$: GO TO 7000 vlengths (format "p: n" where p is an index and n is a 2-byte number) 0: 30 28: 30 56: 60 84: 60 112: 90 139: 60 166: 90 1: 30 29: 60 57: 30 85: 60 113: 30 140: 60 167: 90 2: 30 30: 90 58: 120 86: 120 114: 30 141: 90 168: 90 3: 30 31: 30 59: 30 87: 30 115: 120 142: 90 169: 120 4: 30 32: 30 60: 120 88: 90 116: 30 143: 120 170: 60 5: 30 33: 30 61: 120 89: 120 117: 120 144: 90 171: 120 6: 30 34: 30 62: 120 90: 120 118: 120 145: 120 172: 60 7: 30 35: 60 63: 30 91: 90 119: 30 146: 90 173: 60 8: 30 36: 30 64: 90 92: 90 120: 90 147: 120 174: 120 9: 60 37: 60 65: 30 93: 90 121: 60 148: 120 175: 90 10: 30 38: 120 66: 30 94: 90 122: 60 149: 90 176: 60 11: 30 39: 60 67: 30 95: 120 123: 60 150: 120 177: 120 12: 30 40: 30 68: 120 96: 60 124: 120 151: 90 178: 60 13: 120 41: 30 69: 90 97: 120 125: 90 152: 90 179: 60 14: 30 42: 30 70: 90 98: 90 126: 60 153: 90 180: 60 15: 30 43: 30 71: 60 99: 30 127: 60 154: 60 181: 90 16: 120 44: 120 72: 90 100: 120 128: 90 155: 60 182: 60 17: 120 45: 30 73: 90 101: 90 129: 120 156: 120 183: 120 18: 60 46: 30 74: 90 102: 120 130: 120 157: 60 184: 60 19: 120 47: 30 75: 90 103: 120 131: 90 158: 60 185: 60 20: 60 48: 120 76: 90 104: 90 132: 60 159: 60 186: 90 21: 60 49: 30 77: 60 105: 90 133: 60 160: 120 187: 60 22: 60 50: 60 78: 90 106: 30 134: 120 161: 60 188: 90 23: 120 51: 60 79: 30 107: 30 135: 90 162: 90 189: 120 24: 60 52: 30 80: 120 108: 120 136: 90 163: 90 190: 90 25: 120 53: 30 81: 60 109: 90 137: 120 164: 60 191: 90 26: 30 54: 120 82: 90 110: 90 138: 120 165: 90 27: 30 55: 60 83: 120 111: 30 vstarts 0: 1830 28: 2300 56: 1400 84: 800 112: 2330 139: 1830 166: 430 1: 1600 29: 1600 57: 1000 85: 700 113: 350 140: 1430 167: 430 2: 1930 30: 2100 58: 800 86: 2130 114: 200 141: 1130 168: 130 3: 1630 31: 2100 59: 2330 87: 500 115: 2230 142: 30 169: 1230 4: 1530 32: 1230 60: 1300 88: 1530 116: 400 143: 830 170: 130 5: 1730 33: 1330 61: 1200 89: 1130 117: 600 144: 1030 171: 230 6: 1800 34: 930 62: 900 90: 1100 118: 400 145: 1430 172: 1930 7: 1430 35: 1300 63: 630 91: 830 119: 230 146: 100 173: 300 8: 1900 36: 2130 64: 1800 92: 2230 120: 630 147: 730 174: 1030 9: 1700 37: 1200 65: 600 93: 900 121: 30 148: 2030 175: 200 10: 1400 38: 1000 66: 530 94: 2130 122: 2230 149: 300 176: 330 11: 2030 39: 1800 67: 0 95: 1630 123: 100 150: 300 177: 500 12: 1700 40: 2200 68: 2330 96: 0 124: 30 151: 1330 178: 930 13: 1600 41: 1200 69: 2200 97: 100 125: 2300 152: 1230 179: 230 14: 2000 42: 800 70: 1300 98: 1400 126: 1630 153: 230 180: 2030 15: 1500 43: 830 71: 900 99: 130 127: 830 154: 2130 181: 400 16: 2000 44: 1700 72: 1630 100: 330 128: 0 155: 1130 182: 1530 17: 2100 45: 900 73: 1600 101: 1500 129: 1930 156: 1830 183: 430 18: 2000 46: 2230 74: 1430 102: 1500 130: 930 157: 630 184: 1330 19: 1800 47: 1030 75: 2000 103: 2300 131: 2030 158: 530 185: 1230 20: 1900 48: 1900 76: 1830 104: 1900 132: 500 159: 200 186: 330 21: 2200 49: 730 77: 600 105: 800 133: 1730 160: 1530 187: 1030 22: 2100 50: 2300 78: 1200 106: 430 134: 200 161: 730 188: 500 23: 1400 51: 1000 79: 30 107: 300 135: 1930 162: 600 189: 530 24: 1500 52: 700 80: 130 108: 1330 136: 930 163: 1730 190: 530 25: 2200 53: 1300 81: 0 109: 1000 137: 1730 164: 400 191: 1100 26: 1130 54: 700 82: 1700 110: 700 138: 630 165: 730 27: 1100 55: 1100 83: 0 111: 100