home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
program
/
c
/
itf_src
/
message.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-22
|
12KB
|
664 lines
/*
** File: message.c
**
** (C)opyright 1987-1992 InfoTaskforce.
*/
#include "infocom.h"
/*
** Coded Message Routine Global Variables
*/
char *table ; /* Character Table used by "print_coded" */
proc_ptr letter ; /* Routine used by "print_coded ()" to */
/* print a letter. */
word (*find_mode)() ; /* Routine used by "encode ()" to find */
/* the mode of a character. */
int print_mode ; /* General Printing Mode */
int single_mode ; /* Mode for printing the next char */
word word_bank ; /* There are 3 banks of common */
/* words, each 32 words long. */
/*
** Character Table
*/
char table_1[] = { 'a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x',
'y','z','A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T','U','V',
'W','X','Y','Z',' ','0','1','2','3','4','5','6',
'7','8','9','.',',','!','?','_','#','\'','\"',
'/','\\','<','-',':','(',')','\0','\0'
} ;
char table_2[] = { 'a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x',
'y','z','A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T','U','V',
'W','X','Y','Z',' ',' ','0','1','2','3','4','5',
'6','7','8','9','.',',','!','?','_','#','\'',
'\"','/','\\','-',':','(',')','\0','\0'
} ;
/*
** Decode Routines
*/
Void
init_message ( version )
byte version ;
{
extern char *table ;
extern char table_1[] ;
extern char table_2[] ;
extern proc_ptr letter ;
extern Void letter_v1 () ;
extern Void letter_v2 () ;
extern Void letter_v3 () ;
extern word (*find_mode)() ;
extern word find_mode_v1 () ;
extern word find_mode_v3 () ;
switch ( version )
{
case VERSION_1:
table = table_1 ;
letter = letter_v1 ;
find_mode = find_mode_v1 ;
break ;
case VERSION_2:
table = table_2 ;
letter = letter_v2 ;
find_mode = find_mode_v1 ;
break ;
case VERSION_3:
case VERSION_4:
case VERSION_5:
default:
table = table_2 ;
letter = letter_v3 ;
find_mode = find_mode_v3 ;
break ;
}
}
Void
print_coded ( page,offset )
word *page ;
word *offset ;
{
word data ;
/*
** Print mode :- = 0 : Lower Case Letter ;
** = 1 : Upper Case Letter ;
** = 2 : Number or Symbol ;
** = 3 : ASCII Letter - first byte ;
** = 0x40 : ASCII Letter - second byte ;
** = 0x80 : Common Word ;
*/
print_mode = 0 ;
single_mode = 0 ;
/*
** Last word has high bit set
*/
do
{
data = get_word ( page,offset ) ;
decode ( data ) ;
}
while (( data & 0x8000 ) == 0 ) ;
}
Void
decode ( data )
word data ;
{
extern byte_ptr common_word_ptr ;
extern proc_ptr PrintChar ;
extern proc_ptr letter ;
word page ;
word offset ;
word code ;
int save_mode ;
int i ;
byte_ptr ptr ;
char ch[3] ;
/*
** Reduce word to 3 characters of 5 bits
*/
code = data ;
for ( i = 0 ; i <= 2 ; i++ )
{
ch[i] = code & 0x1F ;
code >>= 5 ;
}
/*
** Print each character
*/
for ( i = 2 ; i >= 0 ; i-- )
{
if ( single_mode & 0x80 )
{
/*
** Print a Special Word
**
** Note:
** We need to save the 'print_mode' before
** recursively calling 'print_coded ()'. This
** is because 'print_mode' is most efficiently
** implemented as a global variable.
*/
ptr = common_word_ptr + word_bank + (int)( ch[i] << 1 ) ;
page = *ptr++ ;
offset = *ptr << 1 ;
save_mode = print_mode ;
print_coded ( &page,&offset ) ;
single_mode = print_mode = save_mode ;
continue ;
}
if ( single_mode < 3 )
{
/*
** Print a single character
*/
(*letter)( ch[i] ) ;
continue ;
}
if ( single_mode == 3 )
{
/*
** Print ASCII character - store the high 3 bits of
** char in the low 3 bits of the current printing mode.
*/
single_mode = 0x40 + ch[i] ;
continue ;
}
if ( single_mode & 0x40 )
{
/*
** Print an ASCII character - consists of the current
** character as the low 5 bits and the high 3 bits coming
** from the low 3 bits of the current printing mode.
*/
ch[i] += ( single_mode & 0x03 ) << 5 ;
(*PrintChar)( (word)ch[i] ) ;
single_mode = print_mode ;
}
}
}
Void
letter_v1 ( ch )
char ch ;
{
extern proc_ptr PrintChar ;
extern char *table ;
if ( ch == 0 )
{
(*PrintChar)( (word)' ' ) ;
single_mode = print_mode ;
return ;
}
if ( ch == 1 )
{
/*
** Print a Carriage Return
*/
new_line () ;
single_mode = print_mode ;
return ;
}
if (( ch == 2 ) || ( ch == 3 ))
{
/*
** Switch printing modes
*/
single_mode = ( single_mode + 2 + ch ) % 3 ;
return ;
}
if (( ch == 4 ) || ( ch == 5 ))
{
/*
** Switch printing modes
*/
print_mode = ( single_mode + ch ) % 3 ;
single_mode = print_mode ;
return ;
}
if (( ch == 6 ) && ( single_mode == 2 ))
{
/*
** Increment printing mode to 3 - ASCII Letter.
*/
++single_mode ;
return ;
}
/*
** None of the above, so this must be a single character
*/
(*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
single_mode = print_mode ;
}
Void
letter_v2 ( ch )
char ch ;
{
extern proc_ptr PrintChar ;
extern char *table ;
if ( ch == 0 )
{
(*PrintChar)( (word)' ' ) ;
single_mode = print_mode ;
return ;
}
if ( ch == 1 )
{
/*
** Set single_mode to "Common Word" & set word_bank
*/
single_mode |= 0x80 ;
word_bank = ( ch - 1 ) << 6 ;
return ;
}
if (( ch == 2 ) || ( ch == 3 ))
{
/*
** Switch printing modes
*/
single_mode = ( single_mode + 2 + ch ) % 3 ;
return ;
}
if (( ch == 4 ) || ( ch == 5 ))
{
/*
** Switch printing modes
*/
print_mode = ( single_mode + ch ) % 3 ;
single_mode = print_mode ;
return ;
}
if (( ch == 6 ) && ( single_mode == 2 ))
{
/*
** Increment printing mode to 3 - ASCII Letter.
*/
++single_mode ;
return ;
}
if (( ch == 7 ) && ( single_mode == 2 ))
{
/*
** Print a Carriage Return
*/
new_line () ;
single_mode = print_mode ;
return ;
}
/*
** None of the above, so this must be a single character
*/
(*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
single_mode = print_mode ;
}
Void
letter_v3 ( ch )
char ch ;
{
extern proc_ptr PrintChar ;
extern char *table ;
if ( ch == 0 )
{
(*PrintChar)( (word)' ' ) ;
single_mode = print_mode ;
return ;
}
if ( ch <= 3 )
{
/*
** Set single_mode to "Common Word" & set word_bank
*/
single_mode |= 0x80 ;
word_bank = ( ch - 1 ) << 6 ;
return ;
}
if (( ch == 4 ) || ( ch == 5 ))
{
/*
** Switch printing modes
*/
if ( single_mode == 0 )
single_mode = ch - 3 ;
else
{
if ( single_mode != ch - 3 )
single_mode = 0 ;
print_mode = single_mode ;
}
return ;
}
if (( ch == 6 ) && ( single_mode == 2 ))
{
/*
** Increment printing mode to 3 - ASCII Letter.
*/
++single_mode ;
return ;
}
if (( ch == 7 ) && ( single_mode == 2 ))
{
/*
** Print a Carriage Return
*/
new_line () ;
single_mode = print_mode ;
return ;
}
/*
** None of the above, so this must be a single character
*/
(*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
single_mode = print_mode ;
}
/*
** Encode Routines
*/
Void
std_encode ( the_word,coded )
byte *the_word ;
word coded[] ;
{
extern word (*find_mode)() ;
word data[STD_CHARS_PER_WORD] ;
word mode ;
word offset ;
register byte ch ;
register int count ;
/*
** Note:
** The parameter "the_word" is of type "byte *"
** NOT "byte_ptr" - these definitions are
** different for MSDOS Compilers ("byte_ptr" is huge).
*/
count = 0 ;
while ( count < (int)STD_CHARS_PER_WORD )
{
ch = *the_word++ ;
if ( ch == 0 )
{
/*
** Finished, so fill with blanks
*/
while ( count < (int)STD_CHARS_PER_WORD )
data[count++] = 5 ;
}
else
{
/*
** Get Character Print-Mode
*/
mode = (*find_mode)( (char)ch ) ;
if ( mode != 0 )
data[count++] = mode ;
/*
** Get offset of character in Table[]
*/
if ( count < (int)STD_CHARS_PER_WORD )
{
offset = convert ( (char)ch ) ;
if ( offset == 0 )
{
/*
** Character not in Table[], so use ASCII
*/
data[count++] = 6 ;
if ( count < (int)STD_CHARS_PER_WORD )
data[count++] = ch >> 5 ;
if ( count < (int)STD_CHARS_PER_WORD )
data[count++] = ch & 0x1F ;
}
else
data[count++] = offset ;
}
}
}
/*
** Encrypt
*/
for ( count = 0 ; count < (int)STD_ENCODED_SIZE ; count++ )
coded[count] = (data[count*3] << 10) | (data[count*3+1] << 5) | data[count*3+2] ;
coded[STD_ENCODED_SIZE - 1] |= 0x8000 ;
}
Void
plus_encode ( the_word,coded )
byte *the_word ;
word coded[] ;
{
extern word (*find_mode)() ;
word data[PLUS_CHARS_PER_WORD] ;
word mode ;
word offset ;
register byte ch ;
register int count ;
/*
** Note:
** The parameter "the_word" is of type "byte *"
** NOT "byte_ptr" - these definitions are
** different for MSDOS Compilers ("byte_ptr" is huge).
*/
count = 0 ;
while ( count < (int)PLUS_CHARS_PER_WORD )
{
ch = *the_word++ ;
if ( ch == 0 )
{
/*
** Finished, so fill with blanks
*/
while ( count < (int)PLUS_CHARS_PER_WORD )
data[count++] = 5 ;
}
else
{
/*
** Get Character Print-Mode
*/
mode = (*find_mode)( (char)ch ) ;
if ( mode != 0 )
data[count++] = mode ;
/*
** Get offset of character in Table[]
*/
if ( count < (int)PLUS_CHARS_PER_WORD )
{
offset = convert ( (char)ch ) ;
if ( offset == 0 )
{
/*
** Character not in Table[], so use ASCII
*/
data[count++] = 6 ;
if ( count < (int)PLUS_CHARS_PER_WORD )
data[count++] = ch >> 5 ;
if ( count < (int)PLUS_CHARS_PER_WORD )
data[count++] = ch & 0x1F ;
}
else
data[count++] = offset ;
}
}
}
/*
** Encrypt
*/
for ( count = 0 ; count < (int)PLUS_ENCODED_SIZE ; count++ )
coded[count] = (data[count*3] << 10) | (data[count*3+1] << 5) | data[count*3+2] ;
coded[PLUS_ENCODED_SIZE - 1] |= 0x8000 ;
}
word
find_mode_v1 ( ch )
char ch ;
{
if ( ch == 0 )
{
/*
** Mode is 3.
*/
return ( 3+3 ) ;
}
if (( ch >= 'a' ) && ( ch <= 'z' ))
{
/*
** Mode is 0.
*/
return ( 0 ) ;
}
if (( ch >= 'A' ) && ( ch <= 'Z' ))
{
/*
** Mode is 1.
*/
return ( 1+1 ) ;
}
/*
** Mode is 2.
*/
return ( 2+1 ) ;
}
word
find_mode_v3 ( ch )
char ch ;
{
if ( ch == 0 )
{
/*
** Mode is 3.
*/
return ( 3+3 ) ;
}
if (( ch >= 'a' ) && ( ch <= 'z' ))
{
/*
** Mode is 0.
*/
return ( 0 ) ;
}
if (( ch >= 'A' ) && ( ch <= 'Z' ))
{
/*
** Mode is 1.
*/
return ( 1+3 ) ;
}
/*
** Mode is 2.
*/
return ( 2+3 ) ;
}
word
convert ( ch )
char ch ;
{
extern char *table ;
register char *ptr ;
register word code ;
ptr = table ;
while (( *ptr != ch ) && ( *ptr != 0 ))
++ptr ;
if ( *ptr == 0 )
return ( 0 ) ;
code = ( ptr - table ) + 6 ;
while ( code >= 0x20 )
code -= 0x1A ;
return ( code ) ;
}