==> cryptology/vcrplus.s <== This program will decode codes 1 through 1000. /* * 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; }