home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GAMES / infocom_src.lha / message.c < prev    next >
Text File  |  1993-03-03  |  11KB  |  664 lines

  1. /*
  2. **    File:    message.c
  3. **
  4. **    (C)opyright 1987-1992 InfoTaskforce.
  5. */
  6.  
  7. #include    "infocom.h"
  8.  
  9. /*
  10. **    Coded Message Routine Global Variables
  11. */
  12.  
  13. char        *table ;                /* Character Table used by "print_coded" */
  14. proc_ptr    letter ;                /* Routine used by "print_coded ()" to   */
  15.                                     /* print a letter.                       */
  16. word        (*find_mode)() ;        /* Routine used by "encode ()" to find   */
  17.                                     /* the mode of a character.              */
  18. int            print_mode ;            /* General Printing Mode                 */
  19. int            single_mode ;            /* Mode for printing the next char       */
  20. word        word_bank ;                /* There are 3 banks of common           */
  21.                                     /* words, each 32 words long.            */
  22.  
  23. /*
  24. **    Character Table
  25. */
  26.  
  27. char    table_1[] =    {    'a','b','c','d','e','f','g','h','i','j','k','l',
  28.                         'm','n','o','p','q','r','s','t','u','v','w','x',
  29.                         'y','z','A','B','C','D','E','F','G','H','I','J',
  30.                         'K','L','M','N','O','P','Q','R','S','T','U','V',
  31.                         'W','X','Y','Z',' ','0','1','2','3','4','5','6',
  32.                         '7','8','9','.',',','!','?','_','#','\'','\"',
  33.                         '/','\\','<','-',':','(',')','\0','\0'
  34.                     } ;
  35.  
  36. char    table_2[] =    {    'a','b','c','d','e','f','g','h','i','j','k','l',
  37.                         'm','n','o','p','q','r','s','t','u','v','w','x',
  38.                         'y','z','A','B','C','D','E','F','G','H','I','J',
  39.                         'K','L','M','N','O','P','Q','R','S','T','U','V',
  40.                         'W','X','Y','Z',' ',' ','0','1','2','3','4','5',
  41.                         '6','7','8','9','.',',','!','?','_','#','\'',
  42.                         '\"','/','\\','-',':','(',')','\0','\0'
  43.                     } ;
  44.  
  45. /*
  46. **    Decode Routines
  47. */
  48.  
  49. Void
  50. init_message ( version )
  51. byte    version ;
  52. {
  53.     extern char        *table ;
  54.     extern char        table_1[] ;
  55.     extern char        table_2[] ;
  56.     extern proc_ptr    letter ;
  57.     extern Void        letter_v1 () ;
  58.     extern Void        letter_v2 () ;
  59.     extern Void        letter_v3 () ;
  60.     extern word        (*find_mode)() ;
  61.     extern word        find_mode_v1 () ;
  62.     extern word        find_mode_v3 () ;
  63.  
  64.     switch ( version )
  65.     {
  66.         case VERSION_1:
  67.                         table = table_1 ;
  68.                         letter = letter_v1 ;
  69.                         find_mode = find_mode_v1 ;
  70.                         break ;
  71.         case VERSION_2:
  72.                         table = table_2 ;
  73.                         letter = letter_v2 ;
  74.                         find_mode = find_mode_v1 ;
  75.                         break ;
  76.         case VERSION_3:
  77.         case VERSION_4:
  78.         case VERSION_5:
  79.         default:
  80.                         table = table_2 ;
  81.                         letter = letter_v3 ;
  82.                         find_mode = find_mode_v3 ;
  83.                         break ;
  84.     }
  85. }
  86.  
  87. Void
  88. print_coded ( page,offset )
  89. word    *page ;
  90. word    *offset ;
  91. {
  92.     word    data ;
  93.  
  94.     /*
  95.     **    Print mode :-        = 0        :    Lower Case Letter ;
  96.     **                        = 1        :    Upper Case Letter ;
  97.     **                        = 2        :    Number or Symbol ;
  98.     **                        = 3        :    ASCII Letter - first byte ;
  99.     **                        = 0x40    :    ASCII Letter - second byte ;
  100.     **                        = 0x80    :    Common Word ;
  101.     */
  102.  
  103.     print_mode = 0 ;
  104.     single_mode = 0 ;
  105.  
  106.     /*
  107.     **    Last word has high bit set
  108.     */
  109.  
  110.     do
  111.     {
  112.         data = get_word ( page,offset ) ;
  113.         decode ( data ) ;
  114.     }
  115.     while (( data & 0x8000 ) == 0 ) ;
  116. }
  117.  
  118. Void
  119. decode ( data ) 
  120. word    data ;
  121. {
  122.     extern byte_ptr        common_word_ptr ;
  123.     extern proc_ptr        PrintChar ;
  124.     extern proc_ptr        letter ;
  125.     
  126.     word                page ;
  127.     word                offset ;
  128.     word                code ;
  129.     int                    save_mode ;
  130.     int                    i ;
  131.     byte_ptr            ptr ;
  132.     char                ch[3] ;
  133.  
  134.     /*
  135.     **    Reduce word to 3 characters of 5 bits
  136.     */
  137.  
  138.     code = data ;
  139.     for ( i = 0 ; i <= 2 ; i++ )
  140.     {
  141.         ch[i] = code & 0x1F ;
  142.         code >>= 5 ;
  143.     }
  144.  
  145.     /*
  146.     **    Print each character
  147.     */
  148.  
  149.     for ( i = 2 ; i >= 0 ; i-- )
  150.     {
  151.         if ( single_mode & 0x80 )
  152.         {
  153.             /*
  154.             **    Print a Special Word
  155.             **
  156.             **    Note:
  157.             **        We need to save the 'print_mode' before
  158.             **        recursively calling 'print_coded ()'. This
  159.             **        is because 'print_mode' is most efficiently
  160.             **        implemented as a global variable.
  161.             */
  162.  
  163.             ptr = common_word_ptr + word_bank + (int)( ch[i] << 1 ) ;
  164.             page = *ptr++ ;
  165.             offset = *ptr << 1 ;
  166.             save_mode = print_mode ;
  167.             print_coded ( &page,&offset ) ;
  168.             single_mode = print_mode = save_mode ;
  169.             continue ;
  170.         }
  171.         if ( single_mode < 3 )
  172.         {
  173.             /*
  174.             **    Print a single character
  175.             */
  176.  
  177.             (*letter)( ch[i] ) ;
  178.             continue ;
  179.         }
  180.         if ( single_mode == 3 )
  181.         {
  182.             /*
  183.             **    Print ASCII character - store the high 3 bits of
  184.             **    char in the low 3 bits of the current printing mode.
  185.             */
  186.  
  187.             single_mode = 0x40 + ch[i] ;
  188.             continue ;
  189.         }
  190.         if ( single_mode & 0x40 )
  191.         {
  192.             /*
  193.             **    Print an ASCII character - consists of the current
  194.             **    character as the low 5 bits and the high 3 bits coming
  195.             **    from the low 3 bits of the current printing mode.
  196.             */
  197.  
  198.             ch[i] += ( single_mode & 0x03 ) << 5 ;
  199.             (*PrintChar)( (word)ch[i] ) ;
  200.             single_mode = print_mode ;
  201.         }
  202.     }
  203. }
  204.  
  205. Void
  206. letter_v1 ( ch )
  207. char    ch ;
  208. {
  209.     extern proc_ptr    PrintChar ;
  210.     extern char        *table ;
  211.  
  212.     if ( ch == 0 )
  213.     {
  214.         (*PrintChar)( (word)' ' ) ;
  215.         single_mode = print_mode ;
  216.         return ;
  217.     }
  218.  
  219.     if ( ch == 1 )
  220.     {
  221.         /*
  222.         **    Print a Carriage Return
  223.         */
  224.  
  225.         new_line () ;
  226.         single_mode = print_mode ;
  227.         return ;
  228.     }
  229.  
  230.     if (( ch == 2 ) || ( ch == 3 ))
  231.     {
  232.         /*
  233.         **    Switch printing modes
  234.         */
  235.  
  236.         single_mode = ( single_mode + 2 + ch ) % 3 ;
  237.         return ;
  238.     }
  239.  
  240.     if (( ch == 4 ) || ( ch == 5 ))
  241.     {
  242.         /*
  243.         **    Switch printing modes
  244.         */
  245.  
  246.         print_mode = ( single_mode + ch ) % 3 ;
  247.         single_mode = print_mode ;
  248.         return ;
  249.     }
  250.  
  251.     if (( ch == 6 ) && ( single_mode == 2 ))
  252.     {
  253.         /*
  254.         **    Increment printing mode to 3 - ASCII Letter.
  255.         */
  256.  
  257.         ++single_mode ;
  258.         return ;
  259.     }
  260.  
  261.     /*
  262.     **    None of the above, so this must be a single character
  263.     */
  264.  
  265.     (*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
  266.     single_mode = print_mode ;
  267. }
  268.  
  269. Void
  270. letter_v2 ( ch )
  271. char    ch ;
  272. {
  273.     extern proc_ptr    PrintChar ;
  274.     extern char        *table ;
  275.  
  276.     if ( ch == 0 )
  277.     {
  278.         (*PrintChar)( (word)' ' ) ;
  279.         single_mode = print_mode ;
  280.         return ;
  281.     }
  282.  
  283.     if ( ch == 1 )
  284.     {
  285.         /*
  286.         **    Set single_mode to "Common Word" & set word_bank
  287.         */
  288.  
  289.         single_mode |= 0x80 ;
  290.         word_bank = ( ch - 1 ) << 6 ;
  291.         return ;
  292.     }
  293.  
  294.     if (( ch == 2 ) || ( ch == 3 ))
  295.     {
  296.         /*
  297.         **    Switch printing modes
  298.         */
  299.  
  300.         single_mode = ( single_mode + 2 + ch ) % 3 ;
  301.         return ;
  302.     }
  303.  
  304.     if (( ch == 4 ) || ( ch == 5 ))
  305.     {
  306.         /*
  307.         **    Switch printing modes
  308.         */
  309.  
  310.         print_mode = ( single_mode + ch ) % 3 ;
  311.         single_mode = print_mode ;
  312.         return ;
  313.     }
  314.  
  315.     if (( ch == 6 ) && ( single_mode == 2 ))
  316.     {
  317.         /*
  318.         **    Increment printing mode to 3 - ASCII Letter.
  319.         */
  320.  
  321.         ++single_mode ;
  322.         return ;
  323.     }
  324.  
  325.     if (( ch == 7 ) && ( single_mode == 2 ))
  326.     {
  327.         /*
  328.         **    Print a Carriage Return
  329.         */
  330.  
  331.         new_line () ;
  332.         single_mode = print_mode ;
  333.         return ;
  334.     }
  335.  
  336.     /*
  337.     **    None of the above, so this must be a single character
  338.     */
  339.  
  340.     (*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
  341.     single_mode = print_mode ;
  342. }
  343.  
  344. Void
  345. letter_v3 ( ch )
  346. char    ch ;
  347. {
  348.     extern proc_ptr    PrintChar ;
  349.     extern char        *table ;
  350.  
  351.     if ( ch == 0 )
  352.     {
  353.         (*PrintChar)( (word)' ' ) ;
  354.         single_mode = print_mode ;
  355.         return ;
  356.     }
  357.  
  358.     if ( ch <= 3 )
  359.     {
  360.         /*
  361.         **    Set single_mode to "Common Word" & set word_bank
  362.         */
  363.  
  364.         single_mode |= 0x80 ;
  365.         word_bank = ( ch - 1 ) << 6 ;
  366.         return ;
  367.     }
  368.  
  369.     if (( ch == 4 ) || ( ch == 5 ))
  370.     {
  371.         /*
  372.         **    Switch printing modes
  373.         */
  374.  
  375.         if ( single_mode == 0 )
  376.             single_mode = ch - 3 ;
  377.         else
  378.         {
  379.             if ( single_mode != ch - 3 )
  380.                 single_mode = 0 ;
  381.             print_mode = single_mode ;
  382.         }
  383.         return ;
  384.     }
  385.  
  386.     if (( ch == 6 ) && ( single_mode == 2 ))
  387.     {
  388.         /*
  389.         **    Increment printing mode to 3 - ASCII Letter.
  390.         */
  391.  
  392.         ++single_mode ;
  393.         return ;
  394.     }
  395.  
  396.     if (( ch == 7 ) && ( single_mode == 2 ))
  397.     {
  398.         /*
  399.         **    Print a Carriage Return
  400.         */
  401.  
  402.         new_line () ;
  403.         single_mode = print_mode ;
  404.         return ;
  405.     }
  406.  
  407.     /*
  408.     **    None of the above, so this must be a single character
  409.     */
  410.  
  411.     (*PrintChar)( (word)table[( single_mode * 26 ) + ch - 6] ) ;
  412.     single_mode = print_mode ;
  413. }
  414.  
  415. /*
  416. **    Encode Routines
  417. */
  418.  
  419. Void
  420. std_encode ( the_word,coded )
  421. byte    *the_word ;
  422. word    coded[] ;
  423. {
  424.     extern word            (*find_mode)() ;
  425.  
  426.     word                data[STD_CHARS_PER_WORD] ;
  427.     word                mode ;
  428.     word                offset ;
  429.     register byte        ch ;
  430.     register int        count ;
  431.  
  432.     /*
  433.     **    Note:
  434.     **        The parameter "the_word" is of type "byte *"
  435.     **        NOT "byte_ptr" - these definitions are
  436.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  437.     */
  438.  
  439.     count = 0 ;
  440.     while ( count < (int)STD_CHARS_PER_WORD )
  441.     {
  442.         ch = *the_word++ ;
  443.         if ( ch == 0 )
  444.         {
  445.             /*
  446.             **    Finished, so fill with blanks
  447.             */
  448.  
  449.             while ( count < (int)STD_CHARS_PER_WORD )
  450.                 data[count++] = 5 ;
  451.         }
  452.         else
  453.         {
  454.             /*
  455.             **    Get Character Print-Mode
  456.             */
  457.  
  458.             mode = (*find_mode)( (char)ch ) ;
  459.             if ( mode != 0 )
  460.                 data[count++] = mode ;
  461.  
  462.             /*
  463.             **    Get offset of character in Table[]
  464.             */
  465.  
  466.             if ( count < (int)STD_CHARS_PER_WORD )
  467.             {
  468.                 offset = convert ( (char)ch ) ;
  469.                 if ( offset == 0 )
  470.                 {
  471.                     /*
  472.                     **    Character not in Table[], so use ASCII
  473.                     */
  474.  
  475.                     data[count++] = 6 ;
  476.                     if ( count < (int)STD_CHARS_PER_WORD )
  477.                         data[count++] = ch >> 5 ;
  478.                     if ( count < (int)STD_CHARS_PER_WORD )
  479.                         data[count++] = ch & 0x1F ;
  480.                 }
  481.                 else
  482.                     data[count++] = offset ;
  483.             }
  484.         }
  485.     }
  486.  
  487.     /*
  488.     **    Encrypt
  489.     */
  490.  
  491.     for ( count = 0 ; count < (int)STD_ENCODED_SIZE ; count++ )
  492.         coded[count] = (data[count*3] << 10) | (data[count*3+1] << 5) | data[count*3+2] ;
  493.     coded[STD_ENCODED_SIZE - 1] |= 0x8000 ;
  494. }
  495.  
  496. Void
  497. plus_encode ( the_word,coded )
  498. byte    *the_word ;
  499. word    coded[] ;
  500. {
  501.     extern word            (*find_mode)() ;
  502.  
  503.     word                data[PLUS_CHARS_PER_WORD] ;
  504.     word                mode ;
  505.     word                offset ;
  506.     register byte        ch ;
  507.     register int        count ;
  508.  
  509.     /*
  510.     **    Note:
  511.     **        The parameter "the_word" is of type "byte *"
  512.     **        NOT "byte_ptr" - these definitions are
  513.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  514.     */
  515.  
  516.     count = 0 ;
  517.     while ( count < (int)PLUS_CHARS_PER_WORD )
  518.     {
  519.         ch = *the_word++ ;
  520.         if ( ch == 0 )
  521.         {
  522.             /*
  523.             **    Finished, so fill with blanks
  524.             */
  525.  
  526.             while ( count < (int)PLUS_CHARS_PER_WORD )
  527.                 data[count++] = 5 ;
  528.         }
  529.         else
  530.         {
  531.             /*
  532.             **    Get Character Print-Mode
  533.             */
  534.  
  535.             mode = (*find_mode)( (char)ch ) ;
  536.             if ( mode != 0 )
  537.                 data[count++] = mode ;
  538.  
  539.             /*
  540.             **    Get offset of character in Table[]
  541.             */
  542.  
  543.             if ( count < (int)PLUS_CHARS_PER_WORD )
  544.             {
  545.                 offset = convert ( (char)ch ) ;
  546.                 if ( offset == 0 )
  547.                 {
  548.                     /*
  549.                     **    Character not in Table[], so use ASCII
  550.                     */
  551.  
  552.                     data[count++] = 6 ;
  553.                     if ( count < (int)PLUS_CHARS_PER_WORD )
  554.                         data[count++] = ch >> 5 ;
  555.                     if ( count < (int)PLUS_CHARS_PER_WORD )
  556.                         data[count++] = ch & 0x1F ;
  557.                 }
  558.                 else
  559.                     data[count++] = offset ;
  560.             }
  561.         }
  562.     }
  563.  
  564.     /*
  565.     **    Encrypt
  566.     */
  567.  
  568.     for ( count = 0 ; count < (int)PLUS_ENCODED_SIZE ; count++ )
  569.         coded[count] = (data[count*3] << 10) | (data[count*3+1] << 5) | data[count*3+2] ;
  570.     coded[PLUS_ENCODED_SIZE - 1] |= 0x8000 ;
  571. }
  572.  
  573. word
  574. find_mode_v1 ( ch )
  575. char    ch ;
  576. {
  577.     if ( ch == 0 )
  578.     {
  579.         /*
  580.         **    Mode is 3.
  581.         */
  582.  
  583.         return ( 3+3 ) ;
  584.     }
  585.     if (( ch >= 'a' ) && ( ch <= 'z' ))
  586.     {
  587.         /*
  588.         **    Mode is 0.
  589.         */
  590.  
  591.         return ( 0 ) ;
  592.     }
  593.     if (( ch >= 'A' ) && ( ch <= 'Z' ))
  594.     {
  595.         /*
  596.         **    Mode is 1.
  597.         */
  598.  
  599.         return ( 1+1 ) ;
  600.     }
  601.  
  602.     /*
  603.     **    Mode is 2.
  604.     */
  605.  
  606.     return ( 2+1 ) ;
  607. }
  608.  
  609. word
  610. find_mode_v3 ( ch )
  611. char    ch ;
  612. {
  613.     if ( ch == 0 )
  614.     {
  615.         /*
  616.         **    Mode is 3.
  617.         */
  618.  
  619.         return ( 3+3 ) ;
  620.     }
  621.     if (( ch >= 'a' ) && ( ch <= 'z' ))
  622.     {
  623.         /*
  624.         **    Mode is 0.
  625.         */
  626.  
  627.         return ( 0 ) ;
  628.     }
  629.     if (( ch >= 'A' ) && ( ch <= 'Z' ))
  630.     {
  631.         /*
  632.         **    Mode is 1.
  633.         */
  634.  
  635.         return ( 1+3 ) ;
  636.     }
  637.  
  638.     /*
  639.     **    Mode is 2.
  640.     */
  641.  
  642.     return ( 2+3 ) ;
  643. }
  644.  
  645. word
  646. convert ( ch )
  647. char    ch ;
  648. {
  649.     extern char        *table ;
  650.  
  651.     register char    *ptr ;
  652.     register word    code ;
  653.  
  654.     ptr = table ;
  655.     while (( *ptr != ch ) && ( *ptr != 0 ))
  656.         ++ptr ;
  657.     if ( *ptr == 0 )
  658.         return ( 0 ) ;
  659.     code = ( ptr - table ) + 6 ;
  660.     while ( code >= 0x20 )
  661.         code -= 0x1A ;
  662.     return ( code ) ;
  663. }
  664.