525 lines
12 KiB
C
525 lines
12 KiB
C
|
|
/* $Id: osdepend.c,v 1.2 2000/05/25 22:28:56 jholder Exp $
|
|
* --------------------------------------------------------------------
|
|
* see doc/License.txt for License Information
|
|
* --------------------------------------------------------------------
|
|
*
|
|
* File name: $Id: osdepend.c,v 1.2 2000/05/25 22:28:56 jholder Exp $
|
|
*
|
|
* Description:
|
|
*
|
|
* Modification history:
|
|
* $Log: osdepend.c,v $
|
|
* Revision 1.2 2000/05/25 22:28:56 jholder
|
|
* changes routine names to reflect zmachine opcode names per spec 1.0
|
|
*
|
|
* Revision 1.1.1.1 2000/05/10 14:21:34 jholder
|
|
*
|
|
* imported
|
|
*
|
|
*
|
|
* --------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
* osdepend.c
|
|
*
|
|
* All non screen specific operating system dependent routines.
|
|
*
|
|
* Olaf Barthel 28-Jul-1992
|
|
* Modified John Holder(j-holder@home.com) 25-July-1995
|
|
* Support for standalone storyfiles by Magnu Olsson (mol@df.lth.se) Nov.1995
|
|
*
|
|
*/
|
|
|
|
#include "ztypes.h"
|
|
//#include "jzexe.h"
|
|
|
|
/* File names will be O/S dependent */
|
|
|
|
#if defined(AMIGA)
|
|
#define SAVE_NAME "Story.Save" /* Default save name */
|
|
#define SCRIPT_NAME "PRT:" /* Default script name */
|
|
#define RECORD_NAME "Story.Record" /* Default record name */
|
|
#define AUXILARY_NAME "Story.Aux" /* Default auxilary name */
|
|
#else /* defined(AMIGA) */
|
|
#define SAVE_NAME "story.sav" /* Default save name */
|
|
#define SCRIPT_NAME "story.scr" /* Default script name */
|
|
#define RECORD_NAME "story.rec" /* Default record name */
|
|
#define AUXILARY_NAME "story.aux" /* Default auxilary name */
|
|
#endif /* defined(AMIGA) */
|
|
|
|
|
|
#ifdef STRICTZ
|
|
|
|
/* Define stuff for stricter Z-code error checking, for the generic
|
|
* Unix/DOS/etc terminal-window interface. Feel free to change the way
|
|
* player prefs are specified, or replace report_zstrict_error()
|
|
* completely if you want to change the way errors are reported.
|
|
*/
|
|
|
|
/* There are four error reporting modes: never report errors;
|
|
* report only the first time a given error type occurs; report
|
|
* every time an error occurs; or treat all errors as fatal
|
|
* errors, killing the interpreter. I strongly recommend
|
|
* "report once" as the default. But you can compile in a
|
|
* different default by changing the definition of
|
|
* STRICTZ_DEFAULT_REPORT_MODE. In any case, the player can
|
|
* specify a report mode on the command line by typing "-s 0"
|
|
* through "-s 3".
|
|
*/
|
|
|
|
#define STRICTZ_REPORT_NEVER (0)
|
|
#define STRICTZ_REPORT_ONCE (1)
|
|
#define STRICTZ_REPORT_ALWAYS (2)
|
|
#define STRICTZ_REPORT_FATAL (3)
|
|
|
|
#define STRICTZ_DEFAULT_REPORT_MODE STRICTZ_REPORT_NEVER
|
|
|
|
static int strictz_report_mode;
|
|
static int strictz_error_count[STRICTZ_NUM_ERRORS];
|
|
|
|
#endif /* STRICTZ */
|
|
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/* getopt linkages */
|
|
|
|
extern int optind;
|
|
extern const char *optarg;
|
|
extern ZINT16 default_fg, default_bg;
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
|
|
#if defined OS2 || defined __MSDOS__
|
|
int iPalette;
|
|
#endif
|
|
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* file_cleanup
|
|
*
|
|
* Perform actions when a file is successfully closed. Flag can be one of:
|
|
* GAME_SAVE, GAME_RESTORE, GAME_SCRIPT.
|
|
*
|
|
*/
|
|
|
|
void file_cleanup( const char *file_name, int flag )
|
|
{
|
|
UNUSEDVAR( file_name );
|
|
UNUSEDVAR( flag );
|
|
} /* file_cleanup */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* sound
|
|
*
|
|
* Play a sound file or a note.
|
|
*
|
|
* argc = 1: argv[0] = note# (range 1 - 3)
|
|
*
|
|
* Play note.
|
|
*
|
|
* argc = 2: argv[0] = 0
|
|
* argv[1] = 3
|
|
*
|
|
* Stop playing current sound.
|
|
*
|
|
* argc = 2: argv[0] = 0
|
|
* argv[1] = 4
|
|
*
|
|
* Free allocated resources.
|
|
*
|
|
* argc = 3: argv[0] = ID# of sound file to replay.
|
|
* argv[1] = 2
|
|
* argv[2] = Volume to replay sound with, this value
|
|
* can range between 1 and 8.
|
|
*
|
|
* argc = 4: argv[0] = ID# of sound file to replay.
|
|
* argv[1] = 2
|
|
* argv[2] = Control information
|
|
* argv[3] = Volume information
|
|
*
|
|
* Volume information:
|
|
*
|
|
* 0x34FB -> Fade sound in
|
|
* 0x3507 -> Fade sound out
|
|
* other -> Replay sound at maximum volume
|
|
*
|
|
* Control information:
|
|
*
|
|
* This word is divided into two bytes,
|
|
* the upper byte determines the number of
|
|
* cycles to play the sound (e.g. how many
|
|
* times a clock chimes or a dog barks).
|
|
* The meaning of the lower byte is yet to
|
|
* be discovered :)
|
|
*
|
|
*/
|
|
|
|
void sound( int argc, zword_t * argv )
|
|
{
|
|
|
|
/* Supply default parameters */
|
|
|
|
if ( argc < 4 )
|
|
argv[3] = 0;
|
|
if ( argc < 3 )
|
|
argv[2] = 0xff;
|
|
if ( argc < 2 )
|
|
argv[1] = 2;
|
|
|
|
/* Generic bell sounder */
|
|
|
|
if ( argc == 1 || argv[1] == 2 )
|
|
display_char( '\007' );
|
|
|
|
} /* sound */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
/*
|
|
* get_file_name
|
|
*
|
|
* Return the name of a file. Flag can be one of:
|
|
* GAME_SAVE - Save file (write only)
|
|
* GAME_RESTORE - Save file (read only)
|
|
* GAME_SCRIPT - Script file (write only)
|
|
* GAME_RECORD - Keystroke record file (write only)
|
|
* GAME_PLABACK - Keystroke record file (read only)
|
|
* GAME_SAVE_AUX - Auxilary (preferred settings) file (write only)
|
|
* GAME_LOAD_AUX - Auxilary (preferred settings) file (read only)
|
|
*/
|
|
|
|
int get_file_name( char *file_name, char *default_name, int flag )
|
|
{
|
|
char buffer[127 + 2]; /* 127 is the biggest positive char */
|
|
int status = 0;
|
|
|
|
/* If no default file name then supply the standard name */
|
|
|
|
if ( default_name[0] == '\0' )
|
|
{
|
|
if ( flag == GAME_SCRIPT )
|
|
strcpy( default_name, SCRIPT_NAME );
|
|
else if ( flag == GAME_RECORD || flag == GAME_PLAYBACK )
|
|
strcpy( default_name, RECORD_NAME );
|
|
else if ( flag == GAME_SAVE_AUX || GAME_LOAD_AUX )
|
|
strcpy( default_name, AUXILARY_NAME );
|
|
else /* (flag == GAME_SAVE || flag == GAME_RESTORE) */
|
|
strcpy( default_name, SAVE_NAME );
|
|
}
|
|
|
|
/* Prompt for the file name */
|
|
|
|
output_line( "Enter a file name." );
|
|
output_string( "(Default is \"" );
|
|
output_string( default_name );
|
|
output_string( "\"): " );
|
|
|
|
buffer[0] = 127;
|
|
buffer[1] = 0;
|
|
( void ) get_line( buffer, 0, 0 );
|
|
|
|
/* Copy file name from the input buffer */
|
|
|
|
if ( h_type > V4 )
|
|
{
|
|
unsigned char len = buffer[1];
|
|
|
|
memcpy( file_name, &buffer[2], len );
|
|
file_name[len] = '\0';
|
|
}
|
|
else
|
|
strcpy( file_name, &buffer[1] );
|
|
|
|
/* If nothing typed then use the default name */
|
|
|
|
if ( file_name[0] == '\0' )
|
|
strcpy( file_name, default_name );
|
|
|
|
#if !defined(VMS) /* VMS has file version numbers, so cannot overwrite */
|
|
|
|
/* Check if we are going to overwrite the file */
|
|
|
|
if ( flag == GAME_SAVE || flag == GAME_SCRIPT || flag == GAME_RECORD || flag == GAME_SAVE_AUX )
|
|
{
|
|
FILE *tfp;
|
|
|
|
#if defined BUFFER_FILES
|
|
char tfpbuffer[BUFSIZ];
|
|
#endif
|
|
char c;
|
|
|
|
/* Try to access the file */
|
|
|
|
tfp = fopen( file_name, "r" );
|
|
if ( tfp != NULL )
|
|
{
|
|
/* If it succeeded then prompt to overwrite */
|
|
|
|
#if defined BUFFER_FILES
|
|
setbuf( tfp, tfpbuffer );
|
|
#endif
|
|
|
|
output_line( "You are about to write over an existing file." );
|
|
output_string( "Proceed? (Y/N) " );
|
|
|
|
do
|
|
{
|
|
c = ( char ) input_character( 0 );
|
|
c = ( char ) toupper( c );
|
|
}
|
|
while ( c != 'Y' && c != 'N' );
|
|
|
|
output_char( c );
|
|
output_new_line( );
|
|
|
|
/* If no overwrite then fail the routine */
|
|
|
|
if ( c == 'N' )
|
|
status = 1;
|
|
|
|
fclose( tfp );
|
|
}
|
|
}
|
|
#endif /* !defined(VMS) */
|
|
|
|
/* Record the file name if it was OK */
|
|
|
|
if ( status == 0 )
|
|
record_line( file_name );
|
|
|
|
return ( status );
|
|
|
|
} /* get_file_name */
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* fatal
|
|
*
|
|
* Display message and stop interpreter.
|
|
*
|
|
*/
|
|
|
|
void fatal( const char *s )
|
|
{
|
|
|
|
reset_screen( );
|
|
fprintf( stderr, "\nFatal error: %s (PC = 0x%08lX)\n", s, pc );
|
|
#ifdef DEBUG_TERPRE
|
|
fprintf( stdout, "\nFatal error: %s (PC = 0x%08lX)\n", s, pc );
|
|
#endif
|
|
exit( 1 );
|
|
|
|
} /* fatal */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
/*
|
|
* report_strictz_error
|
|
*
|
|
* This handles Z-code error conditions which ought to be fatal errors,
|
|
* but which players might want to ignore for the sake of finishing the
|
|
* game.
|
|
*
|
|
* The error is provided as both a numeric code and a string. This allows
|
|
* us to print a warning the first time a particular error occurs, and
|
|
* ignore it thereafter.
|
|
*
|
|
* errnum : Numeric code for error (0 to STRICTZ_NUM_ERRORS-1)
|
|
* errstr : Text description of error
|
|
*
|
|
*/
|
|
|
|
#ifdef STRICTZ
|
|
|
|
void report_strictz_error( int errnum, const char *errstr )
|
|
{
|
|
int wasfirst;
|
|
char buf[256] = { 0 };
|
|
|
|
if ( errnum <= 0 || errnum >= STRICTZ_NUM_ERRORS )
|
|
return;
|
|
|
|
if ( strictz_report_mode == STRICTZ_REPORT_FATAL )
|
|
{
|
|
sprintf( buf, "STRICTZ: %s (PC = %lx)", errstr, pc );
|
|
fatal( buf );
|
|
return;
|
|
}
|
|
|
|
wasfirst = ( strictz_error_count[errnum] == 0 );
|
|
strictz_error_count[errnum]++;
|
|
|
|
if ( ( strictz_report_mode == STRICTZ_REPORT_ALWAYS ) ||
|
|
( strictz_report_mode == STRICTZ_REPORT_ONCE && wasfirst ) )
|
|
{
|
|
sprintf( buf, "STRICTZ Warning: %s (PC = %lx)", errstr, pc );
|
|
write_string( buf );
|
|
|
|
if ( strictz_report_mode == STRICTZ_REPORT_ONCE )
|
|
{
|
|
write_string( " (will ignore further occurrences)" );
|
|
}
|
|
else
|
|
{
|
|
sprintf( buf, " (occurrence %d)", strictz_error_count[errnum] );
|
|
write_string( buf );
|
|
}
|
|
z_new_line( );
|
|
}
|
|
|
|
} /* report_strictz_error */
|
|
|
|
#endif /* STRICTZ */
|
|
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* fit_line
|
|
*
|
|
* This routine determines whether a line of text will still fit
|
|
* on the screen.
|
|
*
|
|
* line : Line of text to test.
|
|
* pos : Length of text line (in characters).
|
|
* max : Maximum number of characters to fit on the screen.
|
|
*
|
|
*/
|
|
int fit_line( const char *line_buffer, int pos, int max )
|
|
{
|
|
UNUSEDVAR( line_buffer );
|
|
|
|
return ( pos < max );
|
|
} /* fit_line */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* print_status
|
|
*
|
|
* Print the status line (type 3 games only).
|
|
*
|
|
* argv[0] : Location name
|
|
* argv[1] : Moves/Time
|
|
* argv[2] : Score
|
|
*
|
|
* Depending on how many arguments are passed to this routine
|
|
* it is to print the status line. The rendering attributes
|
|
* and the status line window will be have been activated
|
|
* when this routine is called. It is to return FALSE if it
|
|
* cannot render the status line in which case the interpreter
|
|
* will use display_char() to render it on its own.
|
|
*
|
|
* This routine has been provided in order to support
|
|
* proportional-spaced fonts.
|
|
*
|
|
*/
|
|
|
|
int print_status( int argc, char *argv[] )
|
|
{
|
|
UNUSEDVAR( argc );
|
|
UNUSEDVAR( argv );
|
|
|
|
return ( FALSE );
|
|
} /* print_status */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
#if !defined(AMIGA)
|
|
|
|
/*
|
|
* set_font
|
|
*
|
|
* Set a new character font. Font can be either be:
|
|
*
|
|
* TEXT_FONT (1) = normal text character font
|
|
* GRAPHICS_FONT (3) = graphical character font
|
|
*
|
|
*/
|
|
|
|
void set_font( int font_type )
|
|
{
|
|
UNUSEDVAR( font_type );
|
|
} /* set_font */
|
|
|
|
#endif /* !defined(AMIGA) */
|
|
|
|
#if !defined MSDOS && !defined OS2 && !defined AMIGA && !defined HARD_COLORS && !defined ATARIST
|
|
|
|
/*
|
|
* set_colours
|
|
*
|
|
* Sets screen foreground and background colours.
|
|
*
|
|
*/
|
|
|
|
void set_colours( zword_t foreground, zword_t background )
|
|
{
|
|
|
|
} /* set_colours */
|
|
|
|
#endif /* !defined MSDOS && !defined OS2 && !defined AMIGA !defined HARD_COLORS && !defined ATARIST */
|
|
|
|
#if !defined VMS && !defined MSDOS && !defined OS2 && !defined POSIX
|
|
|
|
/*
|
|
* codes_to_text
|
|
*
|
|
* Translate Z-code characters to machine specific characters. These characters
|
|
* include line drawing characters and international characters.
|
|
*
|
|
* The routine takes one of the Z-code characters from the following table and
|
|
* writes the machine specific text replacement. The target replacement buffer
|
|
* is defined by MAX_TEXT_SIZE in ztypes.h. The replacement text should be in a
|
|
* normal C, zero terminated, string.
|
|
*
|
|
* Return 0 if a translation was available, otherwise 1.
|
|
*
|
|
* Arrow characters (0x18 - 0x1b):
|
|
*
|
|
* 0x18 Up arrow
|
|
* 0x19 Down arrow
|
|
* 0x1a Right arrow
|
|
* 0x1b Left arrow
|
|
*
|
|
* International characters (0x9b - 0xa3):
|
|
*
|
|
* 0x9b a umlaut (ae)
|
|
* 0x9c o umlaut (oe)
|
|
* 0x9d u umlaut (ue)
|
|
* 0x9e A umlaut (Ae)
|
|
* 0x9f O umlaut (Oe)
|
|
* 0xa0 U umlaut (Ue)
|
|
* 0xa1 sz (ss)
|
|
* 0xa2 open quote (>>)
|
|
* 0xa3 close quota (<<)
|
|
*
|
|
* Line drawing characters (0xb3 - 0xda):
|
|
*
|
|
* 0xb3 vertical line (|)
|
|
* 0xba double vertical line (#)
|
|
* 0xc4 horizontal line (-)
|
|
* 0xcd double horizontal line (=)
|
|
* all other are corner pieces (+)
|
|
*
|
|
*/
|
|
|
|
int codes_to_text( int c, char *s )
|
|
{
|
|
return 1;
|
|
} /* codes_to_text */
|
|
|
|
#endif /* !defined VMS && !defined MSDOS && !defined OS2 && !defined POSIX */
|