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 >
Wrap
Text File
|
1993-03-03
|
7KB
|
339 lines
/*
** File: interp.c
**
** (C)opyright 1987-1992 InfoTaskforce.
*/
#include "infocom.h"
extern proc_ptr jmp_op0[] ;
extern proc_ptr jmp_op1[] ;
extern proc_ptr jmp_op2[] ;
extern int operands[] ;
Void
init_interpreter ( init_pc )
boolean init_pc ;
{
extern word pc_page ;
extern word pc_offset ;
extern word *stack_base ;
extern word *stack_var_ptr ;
extern word *stack ;
extern byte_ptr base_ptr ;
extern header data_head ;
extern int screen_width ;
extern int screen_height ;
extern boolean enhanced ;
register byte_ptr ptr ;
if ( init_pc == TRUE )
{
stack_var_ptr = stack_base ;
stack = --stack_var_ptr ;
pc_page = data_head.start / BLOCK_SIZE ;
pc_offset = data_head.start % BLOCK_SIZE ;
}
fix_pc () ;
init_print () ;
/*
** Set the "script_status" word in the data file to the
** value currently in use by the interpreter.
*/
ptr = (byte_ptr) &(((header_ptr)base_ptr) -> script_status) ;
*ptr++ = MOST_SIGNIFICANT_BYTE ( data_head.script_status ) ;
*ptr = LEAST_SIGNIFICANT_BYTE ( data_head.script_status ) ;
if ( data_head.z_code_version <= VERSION_3 )
{
if ( enhanced )
{
((header_ptr)base_ptr) -> mode_bits |= SCREEN_MODES ;
data_head.mode_bits |= SCREEN_MODES ;
USE_WINDOW ( FULL_SCREEN ) ;
}
}
else
{
/*
** Screen Coordinates:
**
** Horizontal: From 0 to (screen_width - 1)
** Vertical: From 0 to (screen_height - 2)
**
** Note: One screen line is needed for the "[MORE]" function,
** hence (screen_height - 2) instead of (screen_height - 1).
*/
((header_ptr)base_ptr) -> interpreter_number = INTERPRETER ;
((header_ptr)base_ptr) -> interpreter_version = (byte)'A' ;
((header_ptr)base_ptr) -> screen_height = (byte)(screen_height - 1) ;
((header_ptr)base_ptr) -> screen_width = (byte)screen_width ;
((header_ptr)base_ptr) -> mode_bits |= MODE_BITS ;
data_head.mode_bits |= MODE_BITS ;
USE_WINDOW ( FULL_SCREEN ) ;
if ( data_head.z_code_version >= VERSION_5 )
{
((header_ptr)base_ptr) -> left = 0 ;
((header_ptr)base_ptr) -> right = (byte)screen_width ;
((header_ptr)base_ptr) -> top = 0 ;
((header_ptr)base_ptr) -> bottom = (byte)(screen_height - 1) ;
((header_ptr)base_ptr) -> unknown1 = 1 ;
((header_ptr)base_ptr) -> unknown2 = 1 ;
((header_ptr)base_ptr) -> unknown3 = 9 ;
((header_ptr)base_ptr) -> unknown4 = 2 ;
}
}
}
Void
execute_opcode ()
{
extern boolean stop ;
extern word pc_page ;
extern word pc_offset ;
register word opcode ;
#ifdef DEBUG
register long debug_pc ;
#endif /* DEBUG */
stop = FALSE ;
while ( stop == FALSE )
{
#ifdef DEBUG
debug_pc = ( (long)pc_page * BLOCK_SIZE ) + (long)pc_offset ;
#endif /* DEBUG */
opcode = next_byte () ;
#ifdef DEBUG
display ( "PC: $" ) ;
hex_display ( (word)(( debug_pc >> 16 ) & 0xFFFF ) ) ;
hex_display ( (word)( debug_pc & 0xFFFF ) ) ;
display ( " - opcode: $" ) ;
hex_display ( opcode ) ;
#endif /* DEBUG */
if ( opcode < 0x80 )
operand2 ( opcode ) ;
else
{
if ( opcode < 0xB0 )
operand1 ( opcode ) ;
else
{
if ( opcode >= 0xC0 )
operand3 ( opcode ) ;
else
{
/*
** Opcode 0xBE is an ADVANCED series opcode. It is
** used to access opcodes 0x40 to 0x4A in the
** "jmp_op2[]" table. These call "illegal_opcode ()"
** for game files earlier than ADVANCED.
*/
if ( opcode == 0xBE )
{
opcode = ( next_byte () & 0x3F ) | 0x40 ;
#ifdef DEBUG
display ( ":<$" ) ;
hex_display ( opcode ) ;
display ( ">" ) ;
#endif /* DEBUG */
operand4 ( opcode ) ;
}
else
(*jmp_op0[opcode & 0x0F])() ;
}
}
}
#ifdef DEBUG
new_line () ;
#endif /* DEBUG */
}
}
Void
operand1 ( opcode )
register word opcode ;
{
register word param1 ;
param1 = load ((int)(( opcode >> 4 ) & 0x03 )) ;
#ifdef DEBUG
display ( "\t$0001 Parameter: $" ) ;
hex_display ( param1 ) ;
#endif /* DEBUG */
(*jmp_op1[opcode & 0x0F])( param1 ) ;
}
Void
operand2 ( opcode )
register word opcode ;
{
extern word param_stack[] ;
register word *param_ptr ;
register word param1 ;
register word param2 ;
register int mode ;
mode = 1 ;
if ( opcode & 0x40 )
++mode ;
param1 = load ( mode ) ;
mode = 1 ;
if ( opcode & 0x20 )
++mode ;
param2 = load ( mode ) ;
#ifdef DEBUG
display ( "\t$0002 Parameters: $" ) ;
hex_display ( param1 ) ;
display ( " $" ) ;
hex_display ( param2 ) ;
#endif /* DEBUG */
opcode &= 0x1F ;
if ( operands[opcode] )
(*jmp_op2[opcode])( param1,param2 ) ;
else
{
param_ptr = ¶m_stack[0] ;
*param_ptr++ = 2 ;
*param_ptr++ = param1 ;
*param_ptr++ = param2 ;
(*jmp_op2[opcode])() ;
}
}
word
*push_params ( modes,param_ptr,count )
register word modes ;
register word *param_ptr ;
register int count ;
{
extern word param_stack[] ;
if ( count )
{
param_ptr = push_params ( ( modes >> 2 ),param_ptr,--count ) ;
if ( param_ptr != (word *)0 )
{
modes &= 0x03 ;
if ( modes != 0x03 )
{
*param_ptr++ = load ( (int)modes ) ;
++param_stack[0] ;
return ( param_ptr ) ;
}
}
return ( (word *)0 ) ;
}
return ( param_ptr ) ;
}
Void
operand3 ( opcode )
register word opcode ;
{
extern word param_stack[] ;
register word *param_ptr ;
/*
** Reset the Parameter Count.
*/
param_stack[0] = 0 ;
/*
** Fetch the Parameters.
**
** Opcode 0xFA is an ADVANCED series opcode. It is used to
** access opcode 0x3A in the "jmp_op2[]" table. This calls
** "illegal_opcode ()" for game files earlier than ADVANCED.
*/
if (( opcode == 0xEC ) || ( opcode == 0xFA ))
param_ptr = push_params ( (word) next_word (),¶m_stack[1],8 ) ;
else
param_ptr = push_params ( (word) next_byte (),¶m_stack[1],4 ) ;
opcode &= 0x3F ;
call_function ( opcode ) ;
}
Void
call_function ( opcode )
register word opcode ;
{
extern word param_stack[] ;
register proc_ptr func ;
#ifdef DEBUG
display ( "\t$" ) ;
hex_display ( param_stack[0] ) ;
display ( " Parameters: $" ) ;
hex_display ( param_stack[1] ) ;
display ( " $" ) ;
hex_display ( param_stack[2] ) ;
display ( " $" ) ;
hex_display ( param_stack[3] ) ;
#endif /* DEBUG */
func = jmp_op2[opcode] ;
switch ( operands[opcode] )
{
case 0 :
(*func)() ;
break ;
case 1 :
(*func)( param_stack[1] ) ;
break ;
case 2 :
(*func)( param_stack[1],param_stack[2] ) ;
break ;
case 3 :
(*func)( param_stack[1],param_stack[2],param_stack[3] ) ;
break ;
}
}
Void
illegal_opcode ()
{
#ifdef DEBUG
new_line () ;
#endif /* DEBUG */
error ( ERR_OPCODE ) ;
}
Void
operand4 ( opcode )
register word opcode ;
{
extern word param_stack[] ;
register word *param_ptr ;
/*
** Reset the Parameter Count.
*/
param_stack[0] = 0 ;
/*
** Fetch the Parameters.
*/
param_ptr = push_params ( (word) next_byte (),¶m_stack[1],4 ) ;
call_function ( opcode ) ;
}