shirriff@sprite.berkeley.edu (Ken Shirriff) (05/23/91)
I wrote the following C program to decode the first 1000 VCR+ codes.
I did this for the challenge of trying to unravel the code.
Let me know if you find any errors.
(Note: in Chicago, channel 3 seems to be channel 32 for some reason.)
Thanks to Andy Kinsman for his assistance.
Ken Shirriff shirriff@sprite.Berkeley.EDU
-----------------------cut here------------------------------------
/*
* Copyright 1991 Ken Shirriff shirriff@sprite.Berkeley.EDU
*/
char *tn[8] = { "6:30", "4:00", "7:30", "4:30", "3:30", "5:30", "6:00", "2:30"};
main(argc,argv)
int argc;
char **argv;
{
int num, month;
int line, day;
int time, chan;
int shift;
int wrap;
int decnum;
int num0;
int table[32][32];
if (argc != 3) {
printf("Usage: decode num month\n");
exit(-1);
}
num = atoi(argv[1]);
num0 = num;
month = atoi(argv[2]);
decnum = decode100(num%100);
if (num==103 || num==387 || num==474 || num==536 || num==658 ||
num==745 || num==929) {
printf("number %d does not fall into the range of the others\n", num);
} else if (num <= 100) {
/*
* Swap 1-9 decoded with 1-9 encoded
*/
if (1<= num && num<=9) {
decnum = num;
} else if (decnum<=9) {
decnum = decode100(decnum);
}
day = 1 + (decnum-1)/32;
line = (decnum+day-1)%32;
} else {
retry:
/*
* We decode the last two digits.
* Then we shift according to the first digit.
* Each shift moves us 3 days over and 7 lines down.
* But since we are using the sheared table, the 3 days over
* results in moving 4 days down.
*/
shift = (11 + num/100 - shift100(decnum))%10;
day = 1 + (decnum-1)/32; /* 1-4 */
line = (decnum-1)%32; /* 0-31 sheared table */
line += shift*4; /* 0-31 + wrap */
/*
* If we've moved down more than 32 lines, we have to wrap back.
*/
wrap = line/32;
day += shift*3 + wrap;
line += day; /* Undo the shear */
decnum = ((line-day-1)%31)+(day-1)*32+1; /* sheared table number*/
/*
* If we decode a number >100 into something in the first 100,
* we have to take the number there and start over.
* This ensures that numbers 1-100 map into codes 1-100.
*/
if (decnum<100) {
/*
* Get the appropriate entry from the first columns, and start over.
*/
num = decode100(num%100);
decnum = decode100(num);
goto retry;
}
}
/*
* Apply the month correction.
*/
line = (line+day*month)&31;
/*
* Decode the line into the time and channel.
*/
time = ((line&16)>>2) | ((line&4)>>1) | (line&1);
chan = (((line&8)>>2) | ((line&2)>>1))+1;
printf("Code %d in month %d = %s, ch %d on day %d\n", num0, month,
tn[time], chan, day);
}
/*
* Decode 0-99 into a sequential number 1-100:
* 1
* .. 33
* .. 65
* .. .. .. 97
* .. .. .. ..
* .. .. .. 100
* 32
* 64
* 96
*/
int
decode100(num)
{
int day;
int row, col, rem, div;
/*
* 4 special cases that make the modulo operations messy
*/
switch (num) {
case 87:
return 97;
case 58:
return 98;
case 29:
return 99;
case 0:
return 100;
}
/*
* Break up into 7 rows of 5 columns on 3 days.
* The numbers are broken mod 29 and then broken in half again.
*/
rem = num%29;
div = num/29;
if (rem<16-div) {
row = 3-div;
} else {
row = 6-div;
rem -= 13;
}
col = 4-(rem-1)/3;
day = (rem-1)%3;
/*
* The numbers are then assigned consecutively down the columns.
*/
return col*7+row + day*31;
}
/*
* Compute the 100's digit shift.
*/
int
shift100(num)
{
int shift;
int i,j;
i = (num+30)%31;
j = (num+30)/31;
shift = ((i+1)/10)*7 + j*4 + i*3;
if ((i==8 || i==28) && (j==2 || j==3)) shift += 7;
if (i==6 && j==4) shift += 8;
if ((i==17 || i==18) && j==3) shift += 7;
shift = shift%10;
return shift;
}