home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
GAMES
/
infocom_src.lha
/
plus_fns.c
< prev
next >
Wrap
Text File
|
1993-03-03
|
16KB
|
836 lines
/*
** File: plus_fns.c
**
** (C)opyright 1987-1992 InfoTaskforce.
*/
#include <stdio.h>
#include "infocom.h"
/*
** PLUS Interpreter Function Definitions.
*/
Void
parameter_copy ( src,dst )
word *src ;
word *dst ;
{
word src_size ;
word dst_size ;
src_size = *src++ ;
dst_size = *dst++ ;
if ( src_size > dst_size )
{
src += dst_size ;
dst += dst_size ;
src_size -= dst_size ;
while ( src_size-- )
*dst++ = *src++ ;
}
}
Void
plus_compare2 ()
{
extern word param_stack[] ;
register word *ptr = ¶m_stack[1] ;
register word data ; /* Parameter 1 */
register word address ; /* Parameter 2 */
register word num_words ; /* Parameter 3 */
word addr_page ;
word addr_offset ;
data = *ptr++ ;
address = *ptr++ ;
num_words = *ptr++ ;
addr_page = address / BLOCK_SIZE ;
addr_offset = address % BLOCK_SIZE ;
while ( num_words-- != 0 )
{
if ( data == get_word ( &addr_page,&addr_offset ) )
{
address = ( addr_page * BLOCK_SIZE ) + addr_offset - 2 ;
store ( address ) ;
ret_value ( TRUE ) ;
return ;
}
}
store ( (word)0 ) ;
ret_value ( FALSE ) ;
}
Void
adv_compare2 ()
{
extern word param_stack[] ;
extern word default_param_stack[] ;
register word *ptr = ¶m_stack[1] ;
register word data ; /* Parameter 1 */
register word address ; /* Parameter 2 */
register word num_words ; /* Parameter 3 */
register word inc ; /* Parameter 4 */
register word data_size ; /* Parameter 4 */
word addr_page ;
word addr_offset ;
default_param_stack[0] = 4 ;
default_param_stack[4] = 0x82 ;
parameter_copy ( default_param_stack,param_stack ) ;
data = *ptr++ ;
address = *ptr++ ;
num_words = *ptr++ ;
inc = *ptr & 0x7F ;
data_size = *ptr & 0x80 ;
while ( num_words-- )
{
addr_page = address / BLOCK_SIZE ;
addr_offset = address % BLOCK_SIZE ;
if ( data_size != 0 )
{
if ( data == get_word ( &addr_page,&addr_offset ) )
{
store ( address ) ;
ret_value ( TRUE ) ;
return ;
}
}
else
{
if ( (byte)data == get_byte ( &addr_page,&addr_offset ) )
{
store ( address ) ;
ret_value ( TRUE ) ;
return ;
}
}
address += inc ;
}
store ( (word)0 ) ;
ret_value ( FALSE ) ;
}
Void
gosub2 ( address )
word address ;
{
extern proc_ptr jmp_op2[] ;
extern word param_stack[] ;
param_stack[0] = 1 ;
param_stack[1] = address ;
/*
** Call the current "gosub" opcode ...
*/
(*jmp_op2[0x20])() ;
}
Void
do_beep ( sound )
word sound ;
{
/*
** Note: The only legal values for sound are 1 and 2.
*/
while ( sound-- )
putchar ( BELL ) ;
}
Void
erase_line ( mode )
word mode ;
{
/*
** "mode" must be 1.
** The characters at the cursor and to the right are erased.
** The cursor itself is not moved.
*/
if ( mode == 1 )
ERASE_TO_EOLN () ;
}
Void
do_clear_screen ( param )
word param ;
{
extern header data_head ;
extern word window_height ;
extern int screen_height ;
extern word top_screen_line ;
signed_word window ;
window = (signed_word)param ;
switch ( window )
{
case -1:
split_screen ( (word)0 ) ;
ERASE_WINDOW ( top_screen_line,(word)screen_height ) ;
if ( data_head.z_code_version == VERSION_4 )
{
/*
** cursor to bottom l.h.s
*/
GOTO_XY ( 0,screen_height - 1 ) ;
}
break ;
case 0:
ERASE_WINDOW ( window_height,(word)screen_height ) ;
break ;
case 1:
ERASE_WINDOW ( top_screen_line,window_height ) ;
break ;
}
}
Void
set_cursor_posn ()
{
/*
** Here is some code from either a MAC or an AMIGA.
** It is different to that used by the IBM PC (see below).
** Which is better ?
**
** if ( current_window != 1 )
** error ( PLUS_ERROR_2 ) ;
** GOTO_XY ( param_stack[2],param_stack[1] ) ;
*/
extern header data_head ;
extern word param_stack[] ;
extern word current_window ;
extern boolean use_buffered_io ;
if ( data_head.z_code_version >= VERSION_5 )
{
flush_prt_buff () ;
GOTO_XY ( --param_stack[2],--param_stack[1] ) ;
}
else
{
if ( use_buffered_io == FALSE )
{
if ( current_window != 0 )
GOTO_XY ( --param_stack[2],--param_stack[1] ) ;
}
}
}
Void
set_text_mode ( mode )
word mode ;
{
/*
** Mode:
** 0 = NORMAL_MODE ;
** 1 = INVERSE_MODE ;
** 2 = BOLD_MODE ;
*/
/*
** In interpreters prior to VERSION_5, the "mode" parameter is not
** checked before being incremented and passed to "print_char ()".
** In VERSION_5 and subsequent interpreters, the "mode" parameter
** is checked first.
**
** However, there is no reason for us not to adopt the VERSION_5
** method for all versions of the interpreter.
**
** Interpreters prior to VERSION_5 did not include the statement:
**
** if ( mode < 5 )
*/
if ( mode < 5 )
print_char ( ++mode ) ;
}
Void
io_buffer_mode ( param )
word param ;
{
extern boolean use_buffered_io ;
if ( param == 0 )
{
use_buffered_io = FALSE ;
flush_prt_buff () ;
}
else
use_buffered_io = TRUE ;
}
Void
io_mode ()
{
extern header data_head ;
extern word param_stack[] ;
extern byte_ptr base_ptr ;
extern byte_ptr internal_io_buffer ;
extern byte_ptr internal_io_ptr ;
extern word int_io_buff_length ;
extern boolean enable_screen ;
extern boolean script_on ;
extern boolean use_internal_buffer ;
byte_ptr ptr ;
signed_word mode ;
mode = (signed_word)param_stack[1] ;
switch ( mode )
{
case 1:
enable_screen = TRUE ;
break ;
case 2:
if ( script_on == FALSE )
{
data_head.script_status |= SCRIPT_MODE_ON ;
if (( script_on = open_script () ) == FALSE )
data_head.script_status = SCRIPT_ERROR ;
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 ) ;
}
break ;
case 3:
use_internal_buffer = TRUE ;
internal_io_buffer = base_ptr + param_stack[2] ;
int_io_buff_length = 0 ;
internal_io_ptr = internal_io_buffer + 2 ;
break ;
case -1:
enable_screen = FALSE ;
break ;
case -2:
script_on = FALSE ;
data_head.script_status &= SCRIPT_MODE_OFF ;
close_script () ;
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 ) ;
break ;
case -3:
use_internal_buffer = FALSE ;
*internal_io_buffer++ = MOST_SIGNIFICANT_BYTE ( int_io_buff_length ) ;
*internal_io_buffer = LEAST_SIGNIFICANT_BYTE ( int_io_buff_length ) ;
*internal_io_ptr = 0 ;
break ;
}
}
Void
get_key ()
{
extern header data_head ;
extern word param_stack[] ;
extern int linecount ;
if ( data_head.z_code_version >= VERSION_5 )
flush_prt_buff () ;
linecount = 0 ;
if ( param_stack[1] == 1 )
{
if ( param_stack[0] < 3 )
{
store ( read_the_key () ) ;
return ;
}
else
{
if ( wait_for_key ( param_stack[2]/10,param_stack[3] ) == TRUE )
{
store ( read_the_key () ) ;
return ;
}
}
}
store ( (word)0 ) ;
}
word
read_the_key ()
{
/*
** This routine assumes that special keys such as the cursor
** movement and backspace/delete keys have been translated by
** the "GET_CH" routine.
**
** The following translations are suggested:
**
** DELETE -> BACK_SPACE character ('\b')
** LEFT_ARROW -> BACK_SPACE character ('\b')
** RIGHT_ARROW -> BELL character (0x07)
** UP_ARROW -> VERTICAL_TAB character (0x0B)
** DOWN_ARROW -> CARRIAGE_RETURN character ('\r')
**
** This routine translates '\n' to '\r'.
*/
register int ch ;
register int done = FALSE ;
while ( ! done )
{
switch ( ch = GET_CH () )
{
case BELL:
case VERTICAL_TAB:
case '\b':
case '\n':
done = TRUE ;
break ;
case '\l':
ch = '\r' ;
done = TRUE ;
break ;
default:
if ( ch >= ' ' )
done = TRUE ;
break ;
}
}
return ( (word)ch ) ;
}
boolean
wait_for_key ( time_out,address )
word time_out ;
word address ;
{
register word delay ;
register long now ;
register long next ;
do
{
delay = time_out ;
do
{
now = TIME_FUNCTION ;
do
{
if ( KBD_HIT () )
return ( TRUE ) ;
next = TIME_FUNCTION ;
} while ( next - now < ONE_SECOND ) ;
now = next ;
} while ( --delay != 0 ) ;
} while ( special_gosub ( address ) == 0 ) ;
return ( FALSE ) ;
}
word
special_gosub ( address )
word address ;
{
extern proc_ptr jmp_op2[] ;
extern word param_stack[] ;
extern word pc_page ;
extern word *stack ;
extern boolean stop ;
word value ;
boolean old_stop ;
old_stop = stop ;
*(--stack) = pc_page ;
pc_page = EMPTY_PAGE ;
param_stack[0] = 1 ;
param_stack[1] = address ;
/*
** Call the current "gosub" opcode ...
*/
(*jmp_op2[0x20])() ;
execute_opcode () ;
value = *stack++ ;
pc_page = *stack++ ;
fix_pc () ;
stop = old_stop ;
return ( value ) ;
}
/*
** ADVANCED Interpreter Function Definitions.
*/
Void
gosub4 ()
{
call ( PROCEDURE ) ;
}
Void
gosub5 ( address )
word address ;
{
extern word param_stack[] ;
param_stack[0] = 1 ;
param_stack[1] = address ;
gosub4 () ;
}
Void
call ( type )
word type ;
{
extern word pc_offset ;
extern word pc_page ;
extern word *stack_base ;
extern word *stack_var_ptr ;
extern word *stack ;
extern word param_stack[] ;
extern byte local_params ;
register word *param_ptr = ¶m_stack[0] ;
register word address ;
register word parameter ;
register int num_params ;
int vars ;
num_params = (int) *param_ptr++ ;
if (( address = *param_ptr++ ) == 0 )
{
if ( type != PROCEDURE )
store ( address ) ;
}
else
{
--num_params ;
*(--stack) = pc_page ;
*(--stack) = pc_offset ;
*(--stack) = type | local_params ;
/*
** Push offset of old stack_var_ptr from stack_base onto stack
*/
*(--stack) = (word)(stack_var_ptr - stack_base) ;
pc_page = PLUS_PAGE ( address ) ;
pc_offset = PLUS_OFFSET ( address ) ;
fix_pc () ;
/*
** The value of the current stack pointer is the
** new value of stack_var_ptr.
*/
stack_var_ptr = stack ;
local_params = num_params ;
/*
** Global variables 1 to 15 are Local variables, which
** reside on the stack (and so are local to each procedure).
*/
vars = (int) next_byte () ;
if ( vars > ( (int)LOCAL_VARS - 1 ) )
{
display ( "Bad loc num" ) ;
vars = LOCAL_VARS - 1 ;
}
if ( num_params > vars )
{
display ( "Bad optional num" ) ;
num_params = vars ;
}
vars -= num_params ;
while ( num_params-- )
*(--stack) = *param_ptr++ ;
while ( vars-- )
*(--stack) = 0 ;
}
}
Void
branch_true ()
{
ret_value ( TRUE ) ;
}
Void
throw_away_stack_frame ( value,stack_offset )
word value ;
word stack_offset ;
{
extern word *stack_base ;
extern word *stack_var_ptr ;
register word *new_svp ;
new_svp = stack_base + (signed_word)stack_offset ;
if ( new_svp < stack_var_ptr )
display ( "Bad Throw" ) ;
else
{
stack_var_ptr = new_svp ;
adv_rtn ( value ) ;
}
}
Void
parse ()
{
extern word default_param_stack[] ;
extern word param_stack[] ;
extern byte_ptr base_ptr ;
extern byte_ptr main_vocab_list ;
byte_ptr in_buf_strt ;
byte_ptr word_buff_strt ;
byte_ptr vocab_strt ;
default_param_stack[0] = 4 ;
default_param_stack[3] = 0 ;
default_param_stack[4] = 0 ;
parameter_copy ( default_param_stack,param_stack ) ;
in_buf_strt = base_ptr + param_stack[1] ;
word_buff_strt = base_ptr + param_stack[2] ;
if ( param_stack[3] == 0 )
vocab_strt = main_vocab_list ;
else
vocab_strt = base_ptr + param_stack[3] ;
advanced_parse_buffer ( in_buf_strt,word_buff_strt,vocab_strt,param_stack[4] ) ;
}
Void
encrypt ( param1,param2,param3,param4 )
word param1 ;
word param2 ;
word param3 ;
word param4 ;
{
extern byte_ptr base_ptr ;
word coded[PLUS_ENCODED_SIZE] ;
byte_ptr ptr ;
register word i ;
ptr = base_ptr + param1 + param3 ;
i = get_code ( &ptr,PLUS_CHARS_PER_WORD,coded ) ;
ptr = base_ptr + param4 ;
for ( i = 0 ; i < PLUS_ENCODED_SIZE ; i++ )
{
*ptr++ = MOST_SIGNIFICANT_BYTE ( coded[i] ) ;
*ptr++ = LEAST_SIGNIFICANT_BYTE ( coded[i] ) ;
}
}
Void
block_copy ()
{
extern word param_stack[] ;
extern byte_ptr base_ptr ;
register word *ptr = ¶m_stack[1] ;
register boolean negative = FALSE ;
register byte_ptr dst ;
register word src_offset ; /* Parameter 1 */
register word dst_offset ; /* Parameter 2 */
register signed_word num_words ; /* Parameter 3 */
word addr_page ;
word addr_offset ;
src_offset = *ptr++ ;
dst_offset = *ptr++ ;
if ( src_offset != dst_offset )
{
num_words = (signed_word)*ptr ;
if ( num_words != 0 )
{
if ( num_words < 0 )
{
negative = TRUE ;
num_words = -num_words ;
}
if ( dst_offset == 0 )
{
dst = base_ptr + src_offset ;
while ( num_words-- )
*dst++ = 0 ;
}
else
{
if (
( negative )
||
( src_offset > dst_offset )
||
( (word)( (signed_word)src_offset + num_words ) < dst_offset )
)
{
dst = base_ptr + dst_offset ;
addr_page = src_offset / BLOCK_SIZE ;
addr_offset = src_offset % BLOCK_SIZE ;
while ( num_words-- )
*dst++ = get_byte ( &addr_page,&addr_offset ) ;
}
else
{
dst = base_ptr + ( dst_offset + num_words ) ;
src_offset += num_words ;
while ( num_words-- )
{
--src_offset ;
addr_page = src_offset / BLOCK_SIZE ;
addr_offset = src_offset % BLOCK_SIZE ;
*(--dst) = get_byte ( &addr_page,&addr_offset ) ;
}
}
}
}
}
}
Void
print_text ()
{
extern word default_param_stack[] ;
extern word param_stack[] ;
register word *ptr = ¶m_stack[1] ;
register word address ; /* Parameter 1 */
register word line_width ; /* Parameter 2 */
register word num_lines ; /* Parameter 3 */
register word count ;
word addr_page ;
word addr_offset ;
int cursor_x ;
int cursor_y ;
default_param_stack[0] = 3 ;
default_param_stack[3] = 1 ;
parameter_copy ( default_param_stack,param_stack ) ;
cursor_x = GET_X () ;
cursor_y = GET_Y () ;
address = *ptr++ ;
line_width = *ptr++ ;
num_lines = *ptr++ ;
if ( line_width > 0 )
{
while ( num_lines )
{
count = line_width ;
addr_page = address / BLOCK_SIZE ;
addr_offset = address % BLOCK_SIZE ;
while ( count-- )
print_char ( (word) get_byte ( &addr_page,&addr_offset ) ) ;
if ( --num_lines )
{
/*
** New Line.
*/
GOTO_XY ( cursor_x,++cursor_y ) ;
address += line_width ;
}
}
}
}
Void
num_local_params ( num_params )
word num_params ;
{
extern byte local_params ;
if ( num_params <= (word)local_params )
ret_value ( TRUE ) ;
else
ret_value ( FALSE ) ;
}
Void
logical_shift ( param1,param2 )
word param1 ;
word param2 ;
{
register signed_word bits_to_shift ;
bits_to_shift = (signed_word) param2 ;
if ( bits_to_shift < 0 )
store ( (word)( param1 >> ( -bits_to_shift ) ) ) ;
else
store ( (word)( param1 << bits_to_shift ) ) ;
}
Void
arithmetic_shift ( param1,param2 )
word param1 ;
word param2 ;
{
register signed_word bits_to_shift ;
bits_to_shift = (signed_word) param2 ;
if ( bits_to_shift < 0 )
{
if ( ( (signed_word)param1 ) < 0 )
store ( (word)( ~((signed_word)( ~param1 ) >> ( -bits_to_shift )) ) ) ;
else
store ( (word)( (signed_word)param1 >> ( -bits_to_shift ) ) ) ;
}
else
store ( (word)( param1 << bits_to_shift ) ) ;
}
Void
clear_flag ()
{
/*
** Load a register with 0 but don't do anything with it.
*/
}
Void
set_flag ()
{
/*
** Load a register with 1 but don't do anything with it.
*/
}
int
array_test ( ptr,value )
byte_ptr ptr ;
word value ;
{
/*
** This function is only used by "test_byte_array ()".
** On a MAC, it always returns -1.
*/
return ( -1 ) ;
}
Void
test_byte_array ( value,offset )
word value ;
word offset ;
{
extern byte_ptr base_ptr ;
register byte_ptr ptr ;
ptr = base_ptr + offset ;
if ( array_test ( ptr,value ) >= 0 )
ret_value ( TRUE ) ;
else
ret_value ( FALSE ) ;
}