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

  1. /*
  2. **    File:    interp.c
  3. **
  4. **    (C)opyright 1987-1992 InfoTaskforce.
  5. */
  6.  
  7. #include    "infocom.h"
  8.  
  9. extern proc_ptr    jmp_op0[] ;
  10. extern proc_ptr    jmp_op1[] ;
  11. extern proc_ptr    jmp_op2[] ;
  12. extern int        operands[] ;
  13.  
  14. Void
  15. init_interpreter ( init_pc )
  16. boolean        init_pc ;
  17. {
  18.     extern word            pc_page ;
  19.     extern word            pc_offset ;
  20.     extern word            *stack_base ;
  21.     extern word            *stack_var_ptr ;
  22.     extern word            *stack ;
  23.     extern byte_ptr        base_ptr ;
  24.     extern header        data_head ;
  25.     extern int            screen_width ;
  26.     extern int            screen_height ;
  27.     extern boolean        enhanced ;
  28.  
  29.     register byte_ptr    ptr ;
  30.  
  31.     if ( init_pc == TRUE )
  32.     {
  33.         stack_var_ptr = stack_base ;
  34.         stack = --stack_var_ptr ;
  35.         pc_page = data_head.start / BLOCK_SIZE ;
  36.         pc_offset = data_head.start % BLOCK_SIZE ;
  37.     }
  38.  
  39.     fix_pc () ;
  40.     init_print () ;
  41.  
  42.     /*
  43.     **    Set the "script_status" word in the data file to the
  44.     **    value currently in use by the interpreter.
  45.     */
  46.  
  47.     ptr = (byte_ptr) &(((header_ptr)base_ptr) -> script_status) ;
  48.     *ptr++ = MOST_SIGNIFICANT_BYTE ( data_head.script_status ) ;
  49.     *ptr = LEAST_SIGNIFICANT_BYTE ( data_head.script_status ) ;
  50.  
  51.     if ( data_head.z_code_version <= VERSION_3 )
  52.     {
  53.         if ( enhanced )
  54.         {
  55.             ((header_ptr)base_ptr) -> mode_bits |= SCREEN_MODES ;
  56.             data_head.mode_bits |= SCREEN_MODES ;
  57.             USE_WINDOW ( FULL_SCREEN ) ;
  58.         }
  59.     }
  60.     else
  61.     {
  62.         /*
  63.         **    Screen Coordinates:
  64.         **
  65.         **        Horizontal:    From 0 to (screen_width - 1)
  66.         **        Vertical:    From 0 to (screen_height - 2)
  67.         **
  68.         **    Note: One screen line is needed for the "[MORE]" function,
  69.         **    hence (screen_height - 2) instead of (screen_height - 1).
  70.         */
  71.             
  72.         ((header_ptr)base_ptr) -> interpreter_number = INTERPRETER ;
  73.         ((header_ptr)base_ptr) -> interpreter_version = (byte)'A' ;
  74.         ((header_ptr)base_ptr) -> screen_height = (byte)(screen_height - 1) ;
  75.         ((header_ptr)base_ptr) -> screen_width = (byte)screen_width ;
  76.         ((header_ptr)base_ptr) -> mode_bits |= MODE_BITS ;
  77.         data_head.mode_bits |= MODE_BITS ;
  78.         USE_WINDOW ( FULL_SCREEN ) ;
  79.  
  80.         if ( data_head.z_code_version >= VERSION_5 )
  81.         {
  82.  
  83.             ((header_ptr)base_ptr) -> left = 0 ;
  84.             ((header_ptr)base_ptr) -> right = (byte)screen_width ;
  85.             ((header_ptr)base_ptr) -> top = 0 ;
  86.             ((header_ptr)base_ptr) -> bottom = (byte)(screen_height - 1) ;
  87.             ((header_ptr)base_ptr) -> unknown1 = 1 ;
  88.             ((header_ptr)base_ptr) -> unknown2 = 1 ;
  89.             ((header_ptr)base_ptr) -> unknown3 = 9 ;
  90.             ((header_ptr)base_ptr) -> unknown4 = 2 ;
  91.         }
  92.     }
  93. }
  94.  
  95. Void
  96. execute_opcode ()
  97. {
  98.     extern boolean    stop ;
  99.     extern word        pc_page ;
  100.     extern word        pc_offset ;
  101.  
  102.     register word    opcode ;
  103.  
  104. #ifdef    DEBUG
  105.     register long    debug_pc ;
  106. #endif    /* DEBUG */
  107.  
  108.     stop = FALSE ;
  109.     while ( stop == FALSE )
  110.     {
  111.  
  112. #ifdef    DEBUG
  113.         debug_pc = ( (long)pc_page * BLOCK_SIZE ) + (long)pc_offset ;
  114. #endif    /* DEBUG */
  115.         opcode = next_byte () ;
  116. #ifdef    DEBUG
  117.         display ( "PC: $" ) ;
  118.         hex_display ( (word)(( debug_pc >> 16 ) & 0xFFFF ) ) ;
  119.         hex_display ( (word)( debug_pc & 0xFFFF ) ) ;
  120.         display ( " - opcode: $" ) ;
  121.         hex_display ( opcode ) ;
  122. #endif    /* DEBUG */
  123.         if ( opcode < 0x80 )
  124.             operand2 ( opcode ) ;
  125.         else
  126.         {
  127.             if ( opcode < 0xB0 )
  128.                 operand1 ( opcode ) ;
  129.             else
  130.             {
  131.                 if ( opcode >= 0xC0 )
  132.                     operand3 ( opcode ) ;
  133.                 else
  134.                 {
  135.                     /*
  136.                     **    Opcode 0xBE is an ADVANCED series opcode. It is
  137.                     **    used to access opcodes 0x40 to 0x4A in the
  138.                     **    "jmp_op2[]" table. These call "illegal_opcode ()"
  139.                     **    for game files earlier than ADVANCED.
  140.                     */
  141.  
  142.                     if ( opcode == 0xBE )
  143.                     {
  144.                         opcode = ( next_byte () & 0x3F ) | 0x40 ;
  145. #ifdef    DEBUG
  146.                         display ( ":<$" ) ;
  147.                         hex_display ( opcode ) ;
  148.                         display ( ">" ) ;
  149. #endif    /* DEBUG */
  150.                         operand4 ( opcode ) ;
  151.                     }
  152.                     else
  153.                         (*jmp_op0[opcode & 0x0F])() ;
  154.                 }
  155.             }
  156.         }
  157. #ifdef    DEBUG
  158.         new_line () ;
  159. #endif    /* DEBUG */
  160.     }
  161. }
  162.  
  163. Void
  164. operand1 ( opcode )
  165. register word    opcode ;
  166. {
  167.     register word    param1 ;
  168.  
  169.     param1 = load ((int)(( opcode >> 4 ) & 0x03 )) ;
  170. #ifdef    DEBUG
  171.     display ( "\t$0001 Parameter: $" ) ;
  172.     hex_display ( param1 ) ;
  173. #endif    /* DEBUG */
  174.     (*jmp_op1[opcode & 0x0F])( param1 ) ;
  175. }
  176.  
  177. Void
  178. operand2 ( opcode )
  179. register word    opcode ;
  180. {
  181.     extern word        param_stack[] ;
  182.  
  183.     register word    *param_ptr ;
  184.     register word    param1 ;
  185.     register word    param2 ;
  186.     register int    mode ;
  187.  
  188.     mode = 1 ;
  189.     if ( opcode & 0x40 )
  190.         ++mode ;
  191.     param1 = load ( mode ) ;
  192.     mode = 1 ;
  193.     if ( opcode & 0x20 )
  194.         ++mode ;
  195.     param2 = load ( mode ) ;
  196. #ifdef    DEBUG
  197.     display ( "\t$0002 Parameters: $" ) ;
  198.     hex_display ( param1 ) ;
  199.     display ( " $" ) ;
  200.     hex_display ( param2 ) ;
  201. #endif    /* DEBUG */
  202.     opcode &= 0x1F ;
  203.     if ( operands[opcode] )
  204.         (*jmp_op2[opcode])( param1,param2 ) ;
  205.     else
  206.     {
  207.         param_ptr = ¶m_stack[0] ;
  208.         *param_ptr++ = 2 ;
  209.         *param_ptr++ = param1 ;
  210.         *param_ptr++ = param2 ;
  211.         (*jmp_op2[opcode])() ;
  212.     }
  213. }
  214.  
  215. word
  216. *push_params ( modes,param_ptr,count )
  217. register word    modes ;
  218. register word    *param_ptr ;
  219. register int    count ;
  220. {
  221.     extern word        param_stack[] ;
  222.  
  223.     if ( count )
  224.     {
  225.         param_ptr = push_params ( ( modes >> 2 ),param_ptr,--count ) ;
  226.         if ( param_ptr != (word *)0 )
  227.         {
  228.             modes &= 0x03 ;
  229.             if ( modes != 0x03 )
  230.             {
  231.                 *param_ptr++ = load ( (int)modes ) ;
  232.                 ++param_stack[0] ;
  233.                 return ( param_ptr ) ;
  234.             }
  235.         }
  236.         return ( (word *)0 ) ;
  237.     }
  238.     return ( param_ptr ) ;
  239. }
  240.  
  241. Void
  242. operand3 ( opcode )
  243. register word    opcode ;
  244. {
  245.     extern word        param_stack[] ;
  246.  
  247.     register word    *param_ptr ;
  248.  
  249.     /*
  250.     **    Reset the Parameter Count.
  251.     */
  252.  
  253.     param_stack[0] = 0 ;
  254.  
  255.     /*
  256.     **    Fetch the Parameters.
  257.     **
  258.     **    Opcode 0xFA is an ADVANCED series opcode. It is used to
  259.     **    access opcode 0x3A in the "jmp_op2[]" table. This calls
  260.     **    "illegal_opcode ()" for game files earlier than ADVANCED.
  261.     */
  262.  
  263.     if (( opcode == 0xEC ) || ( opcode == 0xFA ))
  264.         param_ptr = push_params ( (word) next_word (),¶m_stack[1],8 ) ;
  265.     else
  266.         param_ptr = push_params ( (word) next_byte (),¶m_stack[1],4 ) ;
  267.  
  268.     opcode &= 0x3F ;
  269.     call_function ( opcode ) ;
  270. }
  271.  
  272. Void
  273. call_function ( opcode )
  274. register word    opcode ;
  275. {
  276.     extern word            param_stack[] ;
  277.  
  278.     register proc_ptr    func ;
  279.  
  280. #ifdef    DEBUG
  281.     display ( "\t$" ) ;
  282.     hex_display ( param_stack[0] ) ;
  283.     display ( " Parameters: $" ) ;
  284.     hex_display ( param_stack[1] ) ;
  285.     display ( " $" ) ;
  286.     hex_display ( param_stack[2] ) ;
  287.     display ( " $" ) ;
  288.     hex_display ( param_stack[3] ) ;
  289. #endif    /* DEBUG */
  290.  
  291.     func = jmp_op2[opcode] ;
  292.     switch ( operands[opcode] )
  293.     {
  294.         case 0 :
  295.                 (*func)() ;
  296.                 break ;
  297.         case 1 :
  298.                 (*func)( param_stack[1] ) ;
  299.                 break ;
  300.         case 2 :
  301.                 (*func)( param_stack[1],param_stack[2] ) ;
  302.                 break ;
  303.         case 3 :
  304.                 (*func)( param_stack[1],param_stack[2],param_stack[3] ) ;
  305.                 break ;
  306.     }
  307. }
  308.  
  309. Void
  310. illegal_opcode ()
  311. {
  312. #ifdef    DEBUG
  313.     new_line () ;
  314. #endif    /* DEBUG */
  315.     error ( ERR_OPCODE ) ;
  316. }
  317.  
  318. Void
  319. operand4 ( opcode )
  320. register word    opcode ;
  321. {
  322.     extern word        param_stack[] ;
  323.  
  324.     register word    *param_ptr ;
  325.  
  326.     /*
  327.     **    Reset the Parameter Count.
  328.     */
  329.  
  330.     param_stack[0] = 0 ;
  331.  
  332.     /*
  333.     **    Fetch the Parameters.
  334.     */
  335.  
  336.     param_ptr = push_params ( (word) next_byte (),¶m_stack[1],4 ) ;
  337.     call_function ( opcode ) ;
  338. }
  339.