2
/* $Id: fileio.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
3
* --------------------------------------------------------------------
4
* see doc/License.txt for License Information
5
* --------------------------------------------------------------------
7
* File name: $Id: fileio.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
11
* Modification history:
13
* Revision 1.3 2000/07/05 15:20:34 jholder
14
* Updated code to remove warnings.
16
* Revision 1.2 2000/05/25 22:28:56 jholder
17
* changes routine names to reflect zmachine opcode names per spec 1.0
19
* Revision 1.1.1.1 2000/05/10 14:21:34 jholder
24
* --------------------------------------------------------------------
30
* File manipulation routines. Should be generic.
35
#include "jzexe.h" /* mol 951115 */
42
static gzFile *gfp = NULL; /* Zcode file pointer */
44
static FILE *gfp = NULL; /* Zcode file pointer */
47
static FILE *sfp = NULL; /* Script file pointer */
48
static FILE *rfp = NULL; /* Record file pointer */
50
#if defined BUFFER_FILES
52
static char gfpbuffer[BUFSIZ];
55
static char sfpbuffer[BUFSIZ];
56
static char rfpbuffer[BUFSIZ];
58
char save_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.sav";
59
char script_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.scr";
60
char record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.rec";
61
char auxilary_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.aux";
63
static int undo_valid = FALSE;
64
static zword_t undo_stack[STACK_SIZE];
66
static int script_file_valid = FALSE;
68
static long story_offset = 0; /* mol 951114 */
69
char *magic = ( char * ) MAGIC_STRING; /* mol */
71
static int save_restore( const char *, int );
76
* This function is called if the game file seems to be a JZEXE file
77
* (standalone game file). If that is the case, story_offset is set
78
* to the beginning of the Z code and the function returns TRUE,
79
* otherwise no action is taken and it returns FALSE.
81
* Magnus Olsson, November 1995
83
int analyze_exefile( void )
87
if ( story_offset > 0 )
89
/* This is wrong; we shouldn't be doing this. */
93
/* Look for the magic string, starting from the beginning. */
97
while ( ( c = jz_getc( gfp ) ) > -1 )
103
i = 1; /* Next character should match magic[1] */
110
else if ( ++i == MAGIC_END )
112
/* Found the magic string! The next byte must be zero. */
113
if ( jz_getc( gfp ) != 0 )
118
/* Read offset and return. We won't concern ourselves with possible
119
* read errors, since their consequences will be detected later on,
120
* when we try to interpret the file as Z code. */
121
story_offset = jz_getc( gfp );
122
story_offset += 256L * jz_getc( gfp );
123
story_offset += 65536L * jz_getc( gfp );
127
/* If we get here, we've reached the end of the infile without success. */
130
} /* analyze_exefile */
136
* Set up the story names intelligently.
137
* John Holder, 28 Sept 1995
139
void set_names( const char *storyname )
143
strcpy( save_name, storyname );
144
strcpy( script_name, storyname );
145
strcpy( record_name, storyname );
146
strcpy( auxilary_name, storyname );
148
/* experimental setting of save_name, added by John Holder 26 July 1995 */
149
per_pos = strrchr( storyname, '.' ); /* find last '.' in storyname. */
150
if ( per_pos ) /* The story file looks like "Odius.dat" or "odieus.z3" */
152
per_pos = strrchr( save_name, '.' );
154
strcat( save_name, ".sav" );
156
per_pos = strrchr( script_name, '.' );
158
strcat( script_name, ".scr" );
160
per_pos = strrchr( record_name, '.' );
162
strcat( record_name, ".rec" );
164
per_pos = strrchr( auxilary_name, '.' );
166
strcat( auxilary_name, ".aux" );
168
else /* The story file looks like: "OdieusQuest" */
170
strcat( save_name, ".sav" );
171
strcat( script_name, ".src" );
172
strcat( record_name, ".rec" );
173
strcat( auxilary_name, ".aux" );
180
* Open game file for read.
184
void open_story( const char *storyname )
187
char tmp[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
189
if ( !STANDALONE_FLAG )
195
/* standalone game; offset to story start is saved in low-endian */
196
/* format after magic string */
198
magic[MAGIC_END + 1] + magic[MAGIC_END + 2] * 256L + magic[MAGIC_END + 3] * 65536L;
201
strcpy( tmp, storyname );
202
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
204
#if defined BUFFER_FILES
206
setbuf( gfp, gfpbuffer );
209
set_names( storyname );
211
#if defined MSDOS || defined OS2
215
sprintf( tmp, "%s.exe", storyname );
216
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
218
#if defined BUFFER_FILES
220
setbuf( gfp, gfpbuffer );
223
set_names( storyname );
229
if ( !STANDALONE_FLAG && ( path = getenv( "INFOCOM_PATH" ) ) == NULL )
231
fprintf( stderr, "%s ", tmp );
232
fatal( "open_story(): Zcode file not found" );
234
else if ( STANDALONE_FLAG && ( path = getenv( "PATH" ) ) == NULL )
236
fprintf( stderr, "%s ", tmp );
237
fatal( "open_story(): Zcode file not found" );
240
/* dos path will be like: */
241
/* SET INFOCOM_PATH = C:\INFOCOM\LTOI1;C:\INFOCOM\LTOI2;C:\INFOCOM\INFORM */
242
#if defined MSDOS || defined OS2
243
p = strtok( path, ";" );
245
/* UNIX path will be like: */
246
/* setenv INFOCOM_PATH /usr/local/lib/ltoi1:/usr/local/lib/ltoi2 */
247
p = strtok( path, ":" );
252
sprintf( tmp, "%s/%s", p, storyname );
253
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
255
#if defined BUFFER_FILES
257
setbuf( gfp, gfpbuffer );
260
set_names( storyname );
262
#if defined MSDOS || defined OS2
266
sprintf( tmp, "%s/%s.exe", p, storyname );
267
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
269
#if defined BUFFER_FILES
271
setbuf( gfp, gfpbuffer );
274
set_names( storyname );
279
#if defined MSDOS || defined OS2
280
p = strtok( NULL, ";" );
282
p = strtok( NULL, ":" );
286
fprintf( stderr, "%s ", tmp );
287
fatal( "open_story(): Zcode file not found" );
294
* Close game file if open.
298
void close_story( void )
311
* Calculate the size of the game file. Only used for very old games that do not
312
* have the game file size in the header.
316
unsigned int get_story_size( void )
318
unsigned long file_length;
320
/* Read whole file to calculate file size */
322
for ( file_length = 0; jz_getc( gfp ) != EOF; file_length++ )
326
/* Calculate length of file in game allocation units */
328
( file_length + ( unsigned long ) ( story_scaler - 1 ) ) / ( unsigned long ) story_scaler;
330
return ( ( unsigned int ) file_length );
332
} /* get_story_size */
337
* Read one game file page.
341
void read_page( int page, void *buffer )
343
unsigned long file_size;
344
unsigned int pages, offset;
346
/* Seek to start of page */
347
jz_seek( gfp, story_offset + ( long ) page * PAGE_SIZE, SEEK_SET );
352
if ( gzread( gfp, buffer, PAGE_SIZE ) == -1 )
354
if ( fread( buffer, PAGE_SIZE, 1, gfp ) != 1 )
357
/* Read failed. Are we in the last page? */
358
file_size = ( unsigned long ) h_file_size *story_scaler;
360
pages = ( unsigned int ) ( ( unsigned long ) file_size / PAGE_SIZE );
361
offset = ( unsigned int ) ( ( unsigned long ) file_size & PAGE_MASK );
363
if ( ( unsigned int ) page == pages )
365
/* Read partial page if this is the last page in the game file */
366
jz_seek( gfp, story_offset + ( long ) page * PAGE_SIZE, SEEK_SET );
368
if ( gzread( gfp, buffer, offset ) == -1 )
370
if ( fread( buffer, offset, 1, gfp ) != 1 )
373
fatal( "read_page(): Zcode file read error" );
383
* Verify game ($verify verb). Add all bytes in game file except for bytes in
384
* the game file header.
388
void z_verify( void )
390
unsigned long file_size;
391
unsigned int pages, offset;
392
unsigned int start, end, i, j;
393
zword_t checksum = 0;
394
zbyte_t buffer[PAGE_SIZE] = { 0 };
395
char szBuffer[6] = { 0 };
397
/* Print version banner */
400
write_string( "Running on " );
401
write_string( JZIPVER );
402
write_string( " (" );
406
write_string( "Generic" );
409
write_string( "Amiga" );
411
case INTERP_ATARI_ST:
412
write_string( "Atari ST" );
415
write_string( "DOS" );
418
write_string( "UNIX" );
421
write_string( "VMS" );
424
write_string( "). Reporting Spec " );
425
sprintf( szBuffer, "%d.%d", get_byte( H_STANDARD_HIGH ), get_byte( H_STANDARD_LOW ) );
426
write_string( szBuffer );
427
write_string( " Compliance." );
430
write_string( "Compile options: " );
432
write_string( "USE_QUETZAL " );
435
write_string( "STRICTZ " );
438
write_string( "USE_ZLIB " );
441
write_string( "LOUSY_RANDOM " );
444
write_string( "HARD_COLORS " );
448
write_string( "Release " );
449
write_string( JZIPRELDATE );
453
write_string( "Playing a Version " );
454
z_print_num( (zword_t) GLOBALVER );
455
write_string( " Story." );
460
/* Calculate game file dimensions */
462
file_size = ( unsigned long ) h_file_size *story_scaler;
464
pages = ( unsigned int ) ( ( unsigned long ) file_size / PAGE_SIZE );
465
offset = ( unsigned int ) file_size & PAGE_MASK;
467
/* Sum all bytes in game file, except header bytes */
469
for ( i = 0; i <= pages; i++ )
471
read_page( i, buffer );
472
start = ( i == 0 ) ? 64 : 0;
473
end = ( i == pages ) ? offset : PAGE_SIZE;
474
for ( j = start; j < end; j++ )
476
checksum += buffer[j];
480
/* Make a conditional jump based on whether the checksum is equal */
482
conditional_jump( checksum == h_checksum );
490
* Read a default file name from the memory of the Z-machine and
491
* copy it to an array.
495
static void get_default_name( char *default_name, zword_t addr )
503
len = get_byte( addr );
505
for ( i = 0; i < len; i++ )
508
c = get_byte( addr );
513
if ( strchr( default_name, '.' ) == 0 )
515
strcpy( default_name + i, ".aux" );
521
strcpy( default_name, auxilary_name );
524
} /* get_default_name */
530
* Saves data to disk. Returns:
536
int z_save( int argc, zword_t table, zword_t bytes, zword_t name )
538
char new_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
539
char default_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
542
#if defined BUFFER_FILES
543
char afpbuffer[BUFSIZ];
549
get_default_name( default_name, name );
550
if ( get_file_name( new_name, default_name, GAME_SAVE_AUX ) != 0 )
555
if ( ( afp = fopen( new_name, "wb" ) ) == NULL )
560
#if defined BUFFER_FILES
561
setbuf( afp, afpbuffer );
564
status = fwrite( datap + table, bytes, 1, afp );
570
strcpy( auxilary_name, default_name );
577
/* Get the file name */
580
if ( get_file_name( new_name, save_name, GAME_SAVE ) == 0 )
582
/* Do a save operation */
583
if ( save_restore( new_name, GAME_SAVE ) == 0 )
586
file_cleanup( new_name, GAME_SAVE );
588
/* Save the new name as the default file name */
589
strcpy( save_name, new_name );
591
/* Indicate success */
599
/* Return result of save to Z-code */
603
conditional_jump( status == 0 );
607
store_operand( (zword_t)(( status == 0 ) ? 1 : 0) );
617
* Restore game state from disk. Returns:
619
* 2 = restore succeeded
622
int z_restore( int argc, zword_t table, zword_t bytes, zword_t name )
624
char new_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
625
char default_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
628
#if defined BUFFER_FILES
629
char afpbuffer[BUFSIZ];
637
get_default_name( default_name, name );
638
if ( get_file_name( new_name, default_name, GAME_LOAD_AUX ) == 0 )
643
if ( ( afp = fopen( new_name, "rb" ) ) == NULL )
648
#if defined BUFFER_FILES
649
setbuf( afp, afpbuffer );
652
status = fread( datap + table, bytes, 1, afp );
658
strcpy( auxilary_name, default_name );
665
/* Get the file name */
667
if ( get_file_name( new_name, save_name, GAME_RESTORE ) == 0 )
669
/* Do the restore operation */
670
if ( save_restore( new_name, GAME_RESTORE ) == 0 )
672
/* Reset the status region (this is just for Seastalker) */
676
blank_status_line( );
680
file_cleanup( new_name, GAME_SAVE );
682
/* Save the new name as the default file name */
683
strcpy( save_name, new_name );
685
/* Indicate success */
692
/* Return result of save to Z-code */
696
conditional_jump( status == 0 );
700
store_operand( (zword_t)(( status == 0 ) ? 2 : 0) );
709
* Save the current Z machine state in memory for a future undo. Returns:
710
* -1 = feature unavailable
716
void z_save_undo( void )
718
/* Check if undo is available first */
719
if ( undo_datap != NULL )
721
/* Save the undo data and return success */
722
save_restore( NULL, UNDO_SAVE );
728
/* If no memory for data area then say undo is not available */
729
store_operand( ( zword_t ) - 1 );
737
* Restore the current Z machine state from memory. Returns:
738
* -1 = feature unavailable
740
* 2 = restore succeeded
744
void z_restore_undo( void )
746
/* Check if undo is available first */
747
if ( undo_datap != NULL )
749
/* If no undo save done then return an error */
750
if ( undo_valid == TRUE )
752
/* Restore the undo data and return success */
753
save_restore( NULL, UNDO_RESTORE );
763
/* If no memory for data area then say undo is not available */
764
store_operand( ( zword_t ) - 1 );
767
} /* z_restore_undo */
773
* Swap the low and high bytes in every word of the specified array.
774
* The length is specified in BYTES!
776
* This routine added by Mark Phillips(msp@bnr.co.uk), Thanks Mark!
778
#if !defined(USE_QUETZAL)
779
void swap_bytes( zword_t * ptr, int len )
781
unsigned char *pbyte;
784
len /= 2; /* convert len into number of 2 byte words */
786
pbyte = ( unsigned char * ) ptr;
803
* Common save and restore code. Just save or restore the game stack and the
804
* writeable data area.
808
static int save_restore( const char *file_name, int flag )
812
#if defined BUFFER_FILES
813
char tfpbuffer[BUFSIZ];
815
int scripting_flag = 0, status = 0;
817
#if !defined(USE_QUETZAL)
819
int little_endian = 0;
821
/* Find out if we are big-endian */
823
if ( *( zbyte_t * ) & zw )
824
{ /* We are little-endian, like an Intel 80x86 chip. */
829
/* Open the save file and disable scripting */
831
if ( flag == GAME_SAVE || flag == GAME_RESTORE )
833
if ( ( tfp = fopen( file_name, ( flag == GAME_SAVE ) ? "wb" : "rb" ) ) == NULL )
835
output_line( "Cannot open SAVE file" );
838
#if defined BUFFER_FILES
839
setbuf( tfp, tfpbuffer );
841
scripting_flag = get_word( H_FLAGS ) & SCRIPTING_FLAG;
842
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
845
#if defined(USE_QUETZAL)
846
if ( flag == GAME_SAVE )
848
status = !save_quetzal( tfp, gfp );
850
else if ( flag == GAME_RESTORE )
852
status = !restore_quetzal( tfp, gfp );
856
#endif /* defined(USE_QUETZAL) */
857
/* Push PC, FP, version and store SP in special location */
859
stack[--sp] = ( zword_t ) ( pc / PAGE_SIZE );
860
stack[--sp] = ( zword_t ) ( pc % PAGE_SIZE );
862
stack[--sp] = h_version;
865
/* Save or restore stack */
867
#if !defined(USE_QUETZAL)
868
if ( flag == GAME_SAVE )
871
swap_bytes( stack, sizeof ( stack ) );
872
if ( status == 0 && fwrite( stack, sizeof ( stack ), 1, tfp ) != 1 )
875
swap_bytes( stack, sizeof ( stack ) );
877
else if ( flag == GAME_RESTORE )
880
swap_bytes( stack, sizeof ( stack ) );
881
if ( status == 0 && fread( stack, sizeof ( stack ), 1, tfp ) != 1 )
884
swap_bytes( stack, sizeof ( stack ) );
887
#endif /* !defined(USE_QUETZAL) */
889
if ( flag == UNDO_SAVE )
891
memmove( undo_stack, stack, sizeof ( stack ) );
893
else /* if (flag == UNDO_RESTORE) */
895
memmove( stack, undo_stack, sizeof ( stack ) );
899
/* Restore SP, check version, restore FP and PC */
903
if ( stack[sp++] != h_version )
905
fatal( "save_restore(): Wrong game or version" );
910
pc += ( unsigned long ) stack[sp++] * PAGE_SIZE;
912
/* Save or restore writeable game data area */
914
#if !defined(USE_QUETZAL)
915
if ( flag == GAME_SAVE )
917
if ( status == 0 && fwrite( datap, h_restart_size, 1, tfp ) != 1 )
920
else if ( flag == GAME_RESTORE )
922
if ( status == 0 && fread( datap, h_restart_size, 1, tfp ) != 1 )
926
#endif /* !defined(USE_QUETZAL) */
928
if ( flag == UNDO_SAVE )
930
memmove( undo_datap, datap, h_restart_size );
932
else /* if (flag == UNDO_RESTORE) */
934
memmove( datap, undo_datap, h_restart_size );
938
#if defined(USE_QUETZAL)
940
#endif /* defined(USE_QUETZAL) */
943
/* Close the save file and restore scripting */
945
if ( flag == GAME_SAVE )
948
if ( scripting_flag )
950
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
953
else if ( flag == GAME_RESTORE )
957
restart_interp( scripting_flag );
960
/* Handle read or write errors */
964
if ( flag == GAME_SAVE )
966
output_line( "Write to SAVE file failed" );
971
fatal( "save_restore(): Read from SAVE file failed" );
982
* Open the scripting file.
986
void open_script( void )
988
char new_script_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
990
/* Open scripting file if closed */
991
if ( scripting == OFF )
993
if ( script_file_valid == TRUE )
995
sfp = fopen( script_name, "a" );
997
/* Turn on scripting if open succeeded */
1000
#if defined BUFFER_FILES
1001
setbuf( sfp, sfpbuffer );
1007
output_line( "Script file open failed" );
1011
{ /* Get scripting file name and record it */
1012
if ( get_file_name( new_script_name, script_name, GAME_SCRIPT ) == 0 )
1014
/* Open scripting file */
1015
sfp = fopen( new_script_name, "w" );
1017
/* Turn on scripting if open succeeded */
1020
#if defined BUFFER_FILES
1021
setbuf( sfp, sfpbuffer );
1023
script_file_valid = TRUE;
1025
/* Make file name the default name */
1026
strcpy( script_name, new_script_name );
1028
/* Turn on scripting */
1033
output_line( "Script file create failed" );
1039
/* Set the scripting flag in the game file flags */
1040
if ( scripting == ON )
1042
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
1046
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
1053
* Flush the scripting file.
1056
void flush_script( void )
1058
/* Flush scripting file if open */
1059
if ( scripting == ON )
1069
* Close the scripting file.
1072
void close_script( void )
1074
/* Close scripting file if open */
1075
if ( scripting == ON )
1080
file_cleanup( script_name, GAME_SCRIPT );
1082
/* Turn off scripting */
1086
/* Set the scripting flag in the game file flags */
1087
if ( scripting == OFF )
1089
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
1093
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
1096
} /* close_script */
1101
* Write one character to scripting file.
1103
* Check the state of the scripting flag first. Older games only set the
1104
* scripting flag in the game flags instead of calling the set_print_modes
1105
* function. This is because they expect a physically attached printer that
1106
* doesn't need opening like a file.
1109
void script_char( int c )
1112
/* Check the state of the scripting flag in the game flags. If it is on
1113
* then check to see if the scripting file is open as well */
1115
if ( ( get_word( H_FLAGS ) & SCRIPTING_FLAG ) != 0 && scripting == OFF )
1120
/* Check the state of the scripting flag in the game flags. If it is off
1121
* then check to see if the scripting file is closed as well */
1123
if ( ( get_word( H_FLAGS ) & SCRIPTING_FLAG ) == 0 && scripting == ON )
1128
/* If scripting file is open, we are in the text window and the character is
1129
* printable then write the character */
1131
if ( scripting == ON && scripting_disable == OFF && ( c == '\n' || ( isprint( c ) ) ) )
1141
* Write a string to the scripting file.
1145
void script_string( const char *s )
1150
script_char( *s++ );
1153
} /* script_string */
1158
* Write a string followed by a new line to the scripting file.
1162
void script_line( const char *s )
1168
/* Write new line */
1176
* Write a new line to the scripting file.
1180
void script_new_line( void )
1183
script_char( '\n' );
1185
} /* script_new_line */
1190
* Turn on recording of all input to an output file.
1194
void open_record( void )
1196
char new_record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
1198
/* If recording or playback is already on then complain */
1200
if ( recording == ON || replaying == ON )
1202
output_line( "Recording or playback are already active." );
1205
{ /* Get recording file name */
1206
if ( get_file_name( new_record_name, record_name, GAME_RECORD ) == 0 )
1208
/* Open recording file */
1209
rfp = fopen( new_record_name, "w" );
1211
/* Turn on recording if open succeeded */
1214
#if defined BUFFER_FILES
1215
setbuf( rfp, rfpbuffer );
1217
/* Make file name the default name */
1218
strcpy( record_name, new_record_name );
1220
/* Set recording on */
1225
output_line( "Record file create failed" );
1235
* Write a string followed by a new line to the recording file.
1239
void record_line( const char *s )
1241
if ( recording == ON && replaying == OFF )
1244
fprintf( rfp, "%s\n", s );
1252
* Write a key followed by a new line to the recording file.
1256
void record_key( int c )
1258
if ( recording == ON && replaying == OFF )
1261
fprintf( rfp, "<%0o>\n", c );
1269
* Turn off recording of all input to an output file.
1273
void close_record( void )
1275
/* Close recording file */
1283
if ( recording == ON )
1285
file_cleanup( record_name, GAME_RECORD );
1287
else /* (replaying == ON) */
1289
file_cleanup( record_name, GAME_PLAYBACK );
1293
/* Set recording and replaying off */
1298
} /* close_record */
1303
* Take input from command file instead of keyboard.
1307
void z_input_stream( int arg )
1309
char new_record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
1313
/* If recording or replaying is already on then complain */
1315
if ( recording == ON || replaying == ON )
1317
output_line( "Recording or replaying is already active." );
1320
{ /* Get recording file name */
1322
if ( get_file_name( new_record_name, record_name, GAME_PLAYBACK ) == 0 )
1324
/* Open recording file */
1325
rfp = fopen( new_record_name, "r" );
1327
/* Turn on recording if open succeeded */
1330
#if defined BUFFER_FILES
1331
setbuf( rfp, rfpbuffer );
1333
/* Make file name the default name */
1334
strcpy( record_name, new_record_name );
1336
/* Set replaying on */
1341
output_line( "Record file open failed" );
1346
} /* z_input_stream */
1351
* Get a line of input from the command file.
1355
int playback_line( int buflen, char *buffer, int *read_size )
1359
if ( recording == ON || replaying == OFF )
1364
if ( fgets( buffer, buflen, rfp ) == NULL )
1371
cp = strrchr( buffer, '\n' );
1376
*read_size = strlen( buffer );
1377
output_line( buffer );
1382
} /* playback_line */
1387
* Get a key from the command file.
1391
int playback_key( void )
1395
if ( recording == ON || replaying == OFF )
1400
if ( fscanf( rfp, "<%o>\n", &c ) == EOF )
1408
} /* playback_key */