2
/* $Id: osdepend.c,v 1.2 2000/05/25 22:28:56 jholder Exp $
3
* --------------------------------------------------------------------
4
* see doc/License.txt for License Information
5
* --------------------------------------------------------------------
7
* File name: $Id: osdepend.c,v 1.2 2000/05/25 22:28:56 jholder Exp $
11
* Modification history:
12
* $Log: osdepend.c,v $
13
* Revision 1.2 2000/05/25 22:28:56 jholder
14
* changes routine names to reflect zmachine opcode names per spec 1.0
16
* Revision 1.1.1.1 2000/05/10 14:21:34 jholder
21
* --------------------------------------------------------------------
27
* All non screen specific operating system dependent routines.
29
* Olaf Barthel 28-Jul-1992
30
* Modified John Holder(j-holder@home.com) 25-July-1995
31
* Support for standalone storyfiles by Magnu Olsson (mol@df.lth.se) Nov.1995
38
/* File names will be O/S dependent */
41
#define SAVE_NAME "Story.Save" /* Default save name */
42
#define SCRIPT_NAME "PRT:" /* Default script name */
43
#define RECORD_NAME "Story.Record" /* Default record name */
44
#define AUXILARY_NAME "Story.Aux" /* Default auxilary name */
45
#else /* defined(AMIGA) */
46
#define SAVE_NAME "story.sav" /* Default save name */
47
#define SCRIPT_NAME "story.scr" /* Default script name */
48
#define RECORD_NAME "story.rec" /* Default record name */
49
#define AUXILARY_NAME "story.aux" /* Default auxilary name */
50
#endif /* defined(AMIGA) */
55
/* Define stuff for stricter Z-code error checking, for the generic
56
* Unix/DOS/etc terminal-window interface. Feel free to change the way
57
* player prefs are specified, or replace report_zstrict_error()
58
* completely if you want to change the way errors are reported.
61
/* There are four error reporting modes: never report errors;
62
* report only the first time a given error type occurs; report
63
* every time an error occurs; or treat all errors as fatal
64
* errors, killing the interpreter. I strongly recommend
65
* "report once" as the default. But you can compile in a
66
* different default by changing the definition of
67
* STRICTZ_DEFAULT_REPORT_MODE. In any case, the player can
68
* specify a report mode on the command line by typing "-s 0"
72
#define STRICTZ_REPORT_NEVER (0)
73
#define STRICTZ_REPORT_ONCE (1)
74
#define STRICTZ_REPORT_ALWAYS (2)
75
#define STRICTZ_REPORT_FATAL (3)
77
#define STRICTZ_DEFAULT_REPORT_MODE STRICTZ_REPORT_NEVER
79
static int strictz_report_mode;
80
static int strictz_error_count[STRICTZ_NUM_ERRORS];
90
extern const char *optarg;
91
extern ZINT16 default_fg, default_bg;
93
#endif /* !defined(AMIGA) */
96
#if defined OS2 || defined __MSDOS__
107
* Do any argument preprocessing necessary before the game is
108
* started. This may include selecting a specific game file or
109
* setting interface-specific options.
113
void process_arguments( int argc, char *argv[] )
122
/* Initialize the STRICTZ variables. */
124
strictz_report_mode = STRICTZ_DEFAULT_REPORT_MODE;
126
for ( num = 0; num < STRICTZ_NUM_ERRORS; num++ )
128
strictz_error_count[num] = 0;
132
/* Parse the options */
135
hist_buf_size = 1024;
139
#if defined OS2 || defined __MSDOS__
140
#define GETOPT_SET "gbomvzhy?l:c:k:r:t:s:"
142
#define GETOPT_SET "bmvzhy?l:c:k:r:t:s:"
143
#elif defined HARD_COLORS
144
#define GETOPT_SET "mvzhy?l:c:k:r:t:s:f:b:"
146
#define GETOPT_SET "mvzhy?l:c:k:r:t:s:"
149
#if defined OS2 || defined __MSDOS__
150
#define GETOPT_SET "gbomvzhy?l:c:k:r:t:"
152
#define GETOPT_SET "bmvzhy?l:c:k:r:t:"
153
#elif defined HARD_COLORS
154
#define GETOPT_SET "mvzhy?l:c:k:r:t:f:b:"
156
#define GETOPT_SET "mvzhy?l:c:k:r:t:"
159
while ( ( c = getopt( argc, argv, GETOPT_SET ) ) != EOF )
163
case 'l': /* lines */
164
screen_rows = atoi( optarg );
166
case 'c': /* columns */
167
screen_cols = atoi( optarg );
169
case 'r': /* right margin */
170
right_margin = atoi( optarg );
172
case 't': /* top margin */
173
top_margin = atoi( optarg );
175
case 'k': /* number of K for hist_buf_size */
176
size = atoi( optarg );
177
hist_buf_size = ( hist_buf_size > size ) ? hist_buf_size : size;
178
if ( hist_buf_size > 16384 )
179
hist_buf_size = 16384;
181
case 'y': /* Tandy */
184
#if defined OS2 || defined __MSDOS__
185
case 'g': /* Beyond Zork or other games using IBM graphics */
189
case 'v': /* version information */
191
fprintf( stdout, "\nJZIP - An Infocom Z-code Interpreter Program \n" );
192
fprintf( stdout, " %s %s\n", JZIPVER, JZIPRELDATE );
193
if ( STANDALONE_FLAG )
195
fprintf( stdout, " Standalone game: %s\n", argv[0] );
197
fprintf( stdout, "---------------------------------------------------------\n" );
198
fprintf( stdout, "Author : %s\n", JZIPAUTHOR );
199
fprintf( stdout, "Official Webpage: %s\n", JZIPURL );
200
fprintf( stdout, "IF Archive : ftp://ifarchive.org/infocom/interpreters/zip/\n" );
201
fprintf( stdout, " Based on ZIP 2.0 source code by Mark Howell\n\n" );
203
"Bugs: Please report bugs and portability bugs to the maintainer." );
204
fprintf( stdout, "\n\nInterpreter:\n\n" );
205
fprintf( stdout, "\tThis interpreter will run all Infocom V1 to V5 and V8 games.\n" );
207
"\tThis is a Z-machine standard 1.0 interpreter, including support for\n" );
208
fprintf( stdout, "\tthe Quetzal portable save file format, ISO 8859-1 (Latin-1)\n" );
210
"\tinternational character support, and the extended save and load opcodes.\n" );
211
fprintf( stdout, "\t\n" );
214
#if defined (HARD_COLORS)
216
default_fg = atoi( optarg );
219
default_bg = atoi( optarg );
222
#if defined OS2 || defined __MSDOS__
223
case 'm': /* monochrome */
226
case 'b': /* black-and-white */
229
case 'o': /* color */
243
case 's': /* strictz reporting mode */
244
strictz_report_mode = atoi( optarg );
245
if ( strictz_report_mode < STRICTZ_REPORT_NEVER ||
246
strictz_report_mode > STRICTZ_REPORT_FATAL )
266
exit( EXIT_SUCCESS );
268
if ( STANDALONE_FLAG )
275
if ( errflg || optind + expected_args != argc )
278
if ( STANDALONE_FLAG )
279
fprintf( stdout, "usage: %s [options...]\n", argv[0] );
281
fprintf( stdout, "usage: %s [options...] story-file\n", argv[0] );
283
fprintf( stdout, "JZIP - an Infocom story file interpreter.\n" );
284
fprintf( stdout, " Version %s by %s.\n", JZIPVER, JZIPAUTHOR );
285
fprintf( stdout, " Release %s.\n", JZIPRELDATE );
286
fprintf( stdout, " Based on ZIP V2.0 source by Mark Howell\n" );
287
fprintf( stdout, " Plays types 1-5 and 8 Infocom and Inform games.\n\n" );
288
fprintf( stdout, "\t-l n lines in display\n" );
289
fprintf( stdout, "\t-c n columns in display\n" );
290
fprintf( stdout, "\t-r n text right margin (default = %d)\n", DEFAULT_RIGHT_MARGIN );
291
fprintf( stdout, "\t-t n text top margin (default = %d)\n", DEFAULT_TOP_MARGIN );
292
fprintf( stdout, "\t-k n set the size of the command history buffer to n bytes\n" );
293
fprintf( stdout, "\t (Default is 1024 bytes. Maximum is 16384 bytes.)\n" );
294
fprintf( stdout, "\t-y turn on the legendary \"Tandy\" bit\n" );
295
fprintf( stdout, "\t-v display version information\n" );
296
fprintf( stdout, "\t-h display this usage information\n" );
298
#if defined (HARD_COLORS)
299
fprintf( stdout, "\t-f n foreground color\n" );
300
fprintf( stdout, "\t-b n background color (-1 to ignore bg color (try it on an Eterm))\n" );
301
fprintf( stdout, "\t Black=0 Red=1 Green=2 Yellow=3 Blue=4 Magenta=5 Cyan=6 White=7\n" );
303
fprintf( stdout, "\t-m force monochrome mode\n" );
304
#if defined __MSDOS__ || defined OS2
305
fprintf( stdout, "\t-b force black-and-white mode\n" );
306
fprintf( stdout, "\t-o force color mode\n" );
307
fprintf( stdout, "\t-g use \"Beyond Zork\" graphics, rather than standard international\n" );
309
fprintf( stdout, "\t-b run in 43/50 line EGA/VGA mode\n" );
313
fprintf( stdout, "\t-s n stricter error checking (default = %d) (0: none; 1: report 1st\n",
314
STRICTZ_DEFAULT_REPORT_MODE );
315
fprintf( stdout, "\t error; 2: report all errors; 3: exit after any error)\n" );
318
fprintf( stdout, "\t-z display license information.\n" );
319
exit( EXIT_FAILURE );
322
/* Open the story file */
324
if ( !STANDALONE_FLAG ) /* mol 951115 */
325
open_story( argv[optind] );
328
/* standalone, ie. the .exe file _is_ the story file. */
329
if ( argv[0][0] == 0 )
331
/* some OS's (ie DOS prior to v.3.0) don't supply the path to */
332
/* the .exe file in argv[0]; in that case, we give up. (mol) */
333
fatal( "process_arguments(): Sorry, this program will not run on this platform." );
335
open_story( argv[0] );
338
} /* process_arguments */
340
#endif /* !defined(AMIGA) */
347
* Perform actions when a file is successfully closed. Flag can be one of:
348
* GAME_SAVE, GAME_RESTORE, GAME_SCRIPT.
352
void file_cleanup( const char *file_name, int flag )
354
UNUSEDVAR( file_name );
358
#endif /* !defined(AMIGA) */
365
* Play a sound file or a note.
367
* argc = 1: argv[0] = note# (range 1 - 3)
371
* argc = 2: argv[0] = 0
374
* Stop playing current sound.
376
* argc = 2: argv[0] = 0
379
* Free allocated resources.
381
* argc = 3: argv[0] = ID# of sound file to replay.
383
* argv[2] = Volume to replay sound with, this value
384
* can range between 1 and 8.
386
* argc = 4: argv[0] = ID# of sound file to replay.
388
* argv[2] = Control information
389
* argv[3] = Volume information
391
* Volume information:
393
* 0x34FB -> Fade sound in
394
* 0x3507 -> Fade sound out
395
* other -> Replay sound at maximum volume
397
* Control information:
399
* This word is divided into two bytes,
400
* the upper byte determines the number of
401
* cycles to play the sound (e.g. how many
402
* times a clock chimes or a dog barks).
403
* The meaning of the lower byte is yet to
408
void sound( int argc, zword_t * argv )
411
/* Supply default parameters */
420
/* Generic bell sounder */
422
if ( argc == 1 || argv[1] == 2 )
423
display_char( '\007' );
427
#endif /* !defined(AMIGA) */
432
* Return the name of a file. Flag can be one of:
433
* GAME_SAVE - Save file (write only)
434
* GAME_RESTORE - Save file (read only)
435
* GAME_SCRIPT - Script file (write only)
436
* GAME_RECORD - Keystroke record file (write only)
437
* GAME_PLABACK - Keystroke record file (read only)
438
* GAME_SAVE_AUX - Auxilary (preferred settings) file (write only)
439
* GAME_LOAD_AUX - Auxilary (preferred settings) file (read only)
442
int get_file_name( char *file_name, char *default_name, int flag )
444
char buffer[127 + 2]; /* 127 is the biggest positive char */
447
/* If no default file name then supply the standard name */
449
if ( default_name[0] == '\0' )
451
if ( flag == GAME_SCRIPT )
452
strcpy( default_name, SCRIPT_NAME );
453
else if ( flag == GAME_RECORD || flag == GAME_PLAYBACK )
454
strcpy( default_name, RECORD_NAME );
455
else if ( flag == GAME_SAVE_AUX || GAME_LOAD_AUX )
456
strcpy( default_name, AUXILARY_NAME );
457
else /* (flag == GAME_SAVE || flag == GAME_RESTORE) */
458
strcpy( default_name, SAVE_NAME );
461
/* Prompt for the file name */
463
output_line( "Enter a file name." );
464
output_string( "(Default is \"" );
465
output_string( default_name );
466
output_string( "\"): " );
470
( void ) get_line( buffer, 0, 0 );
472
/* Copy file name from the input buffer */
476
unsigned char len = buffer[1];
478
memcpy( file_name, &buffer[2], len );
479
file_name[len] = '\0';
482
strcpy( file_name, &buffer[1] );
484
/* If nothing typed then use the default name */
486
if ( file_name[0] == '\0' )
487
strcpy( file_name, default_name );
489
#if !defined(VMS) /* VMS has file version numbers, so cannot overwrite */
491
/* Check if we are going to overwrite the file */
493
if ( flag == GAME_SAVE || flag == GAME_SCRIPT || flag == GAME_RECORD || flag == GAME_SAVE_AUX )
497
#if defined BUFFER_FILES
498
char tfpbuffer[BUFSIZ];
502
/* Try to access the file */
504
tfp = fopen( file_name, "r" );
507
/* If it succeeded then prompt to overwrite */
509
#if defined BUFFER_FILES
510
setbuf( tfp, tfpbuffer );
513
output_line( "You are about to write over an existing file." );
514
output_string( "Proceed? (Y/N) " );
518
c = ( char ) input_character( 0 );
519
c = ( char ) toupper( c );
521
while ( c != 'Y' && c != 'N' );
526
/* If no overwrite then fail the routine */
534
#endif /* !defined(VMS) */
536
/* Record the file name if it was OK */
539
record_line( file_name );
543
} /* get_file_name */
550
* Display message and stop interpreter.
554
void fatal( const char *s )
558
fprintf( stderr, "\nFatal error: %s (PC = 0x%08lX)\n", s, pc );
560
fprintf( stdout, "\nFatal error: %s (PC = 0x%08lX)\n", s, pc );
566
#endif /* !defined(AMIGA) */
569
* report_strictz_error
571
* This handles Z-code error conditions which ought to be fatal errors,
572
* but which players might want to ignore for the sake of finishing the
575
* The error is provided as both a numeric code and a string. This allows
576
* us to print a warning the first time a particular error occurs, and
577
* ignore it thereafter.
579
* errnum : Numeric code for error (0 to STRICTZ_NUM_ERRORS-1)
580
* errstr : Text description of error
586
void report_strictz_error( int errnum, const char *errstr )
589
char buf[256] = { 0 };
591
if ( errnum <= 0 || errnum >= STRICTZ_NUM_ERRORS )
594
if ( strictz_report_mode == STRICTZ_REPORT_FATAL )
596
sprintf( buf, "STRICTZ: %s (PC = %lx)", errstr, pc );
601
wasfirst = ( strictz_error_count[errnum] == 0 );
602
strictz_error_count[errnum]++;
604
if ( ( strictz_report_mode == STRICTZ_REPORT_ALWAYS ) ||
605
( strictz_report_mode == STRICTZ_REPORT_ONCE && wasfirst ) )
607
sprintf( buf, "STRICTZ Warning: %s (PC = %lx)", errstr, pc );
610
if ( strictz_report_mode == STRICTZ_REPORT_ONCE )
612
write_string( " (will ignore further occurrences)" );
616
sprintf( buf, " (occurrence %d)", strictz_error_count[errnum] );
622
} /* report_strictz_error */
632
* This routine determines whether a line of text will still fit
635
* line : Line of text to test.
636
* pos : Length of text line (in characters).
637
* max : Maximum number of characters to fit on the screen.
640
int fit_line( const char *line_buffer, int pos, int max )
642
UNUSEDVAR( line_buffer );
644
return ( pos < max );
647
#endif /* !defined(AMIGA) */
654
* Print the status line (type 3 games only).
656
* argv[0] : Location name
657
* argv[1] : Moves/Time
660
* Depending on how many arguments are passed to this routine
661
* it is to print the status line. The rendering attributes
662
* and the status line window will be have been activated
663
* when this routine is called. It is to return FALSE if it
664
* cannot render the status line in which case the interpreter
665
* will use display_char() to render it on its own.
667
* This routine has been provided in order to support
668
* proportional-spaced fonts.
672
int print_status( int argc, char *argv[] )
680
#endif /* !defined(AMIGA) */
687
* Set a new character font. Font can be either be:
689
* TEXT_FONT (1) = normal text character font
690
* GRAPHICS_FONT (3) = graphical character font
694
void set_font( int font_type )
696
UNUSEDVAR( font_type );
699
#endif /* !defined(AMIGA) */
701
#if !defined MSDOS && !defined OS2 && !defined AMIGA && !defined HARD_COLORS && !defined ATARIST
706
* Sets screen foreground and background colours.
710
void set_colours( zword_t foreground, zword_t background )
715
#endif /* !defined MSDOS && !defined OS2 && !defined AMIGA !defined HARD_COLORS && !defined ATARIST */
717
#if !defined VMS && !defined MSDOS && !defined OS2 && !defined POSIX
722
* Translate Z-code characters to machine specific characters. These characters
723
* include line drawing characters and international characters.
725
* The routine takes one of the Z-code characters from the following table and
726
* writes the machine specific text replacement. The target replacement buffer
727
* is defined by MAX_TEXT_SIZE in ztypes.h. The replacement text should be in a
728
* normal C, zero terminated, string.
730
* Return 0 if a translation was available, otherwise 1.
732
* Arrow characters (0x18 - 0x1b):
739
* International characters (0x9b - 0xa3):
748
* 0xa2 open quote (>>)
749
* 0xa3 close quota (<<)
751
* Line drawing characters (0xb3 - 0xda):
753
* 0xb3 vertical line (|)
754
* 0xba double vertical line (#)
755
* 0xc4 horizontal line (-)
756
* 0xcd double horizontal line (=)
757
* all other are corner pieces (+)
761
int codes_to_text( int c, char *s )
764
} /* codes_to_text */
766
#endif /* !defined VMS && !defined MSDOS && !defined OS2 && !defined POSIX */