home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GAMES / infocom_src.lha / file.c < prev    next >
Text File  |  1993-07-15  |  13KB  |  563 lines

  1. /*
  2. **    File:    file.c
  3. **
  4. **    (C)opyright 1987-1992 InfoTaskforce.
  5. */
  6.  
  7. #include    <stdio.h>
  8. #include    "infocom.h"
  9.  
  10. #define        NAME_SIZE    80
  11.  
  12. extern int errno;
  13.  
  14. char    name[NAME_SIZE + 1] ;
  15. FILE    *game_file    = (FILE *)0 ;
  16.  
  17. Void
  18. read_header ( head )
  19. header    *head ;
  20. {
  21.     /*
  22.     **    Read the Data File Header.
  23.     **
  24.     **    This routine does not read the data-file header
  25.     **    directly into a header structure because certain
  26.     **    machines like the VAX 11/780 store integers in
  27.     **    a different way to machines based on processors
  28.     **    like the 68000 ( a 68000 stores the high byte
  29.     **    first, while a VAX stores the low byte first ).
  30.     **    Consequently, if the header is read directly
  31.     **    into a structure, the integer values are
  32.     **    interpreted differently by the two machines.
  33.     **
  34.     **    Note:
  35.     **        The parameter "head" is of type "header *"
  36.     **        NOT "header_ptr" - these definitions are
  37.     **        different for MSDOS Compilers ("header_ptr" is huge).
  38.     */
  39.  
  40.     header    buffer ;
  41.  
  42.     if ( fseek ( game_file,0L,0 ) < 0 )
  43.     {
  44.         display ( "Failed to Seek Start of File\n" ) ;
  45.         quit () ;
  46.     }
  47.     else
  48.     {
  49.         if ( fread ((char *)(&buffer),sizeof(header),1,game_file ) != 1 )
  50.         {
  51.             display ( "Failed to read File Header\n" ) ;
  52.             quit () ;
  53.         }
  54.         else
  55.         {
  56.             assign ( head,(byte_ptr)&buffer ) ;
  57.             if    (
  58.                     ( head -> z_code_version == 0 )
  59.                     ||
  60.                     ( head -> z_code_version > MAX_VERSION )
  61.                 )
  62.             {
  63.                 error ( ERR_HEADER ) ;
  64.             }
  65.         }
  66.     }
  67. }
  68.  
  69. Void
  70. assign ( head,buffer )
  71. header        *head ;
  72. byte_ptr    buffer ;
  73. {
  74.     /*
  75.     **    Process the raw header data in "buffer" and put
  76.     **    it into the appropriate fields in "head". This
  77.     **    processing is required because of the way different
  78.     **    machines internally represent 'words'.
  79.     **
  80.     **    Note:
  81.     **        The parameter "head" is of type "header *"
  82.     **        NOT "header_ptr" - these definitions are
  83.     **        different for MSDOS Compilers ("header_ptr" is huge).
  84.     */
  85.  
  86.     int            i ;
  87.  
  88.     head -> z_code_version        = *buffer++ ;
  89.     head -> mode_bits            = *buffer++ ;
  90.     head -> release                = make_word ( &buffer ) ;
  91.     head -> resident_bytes        = make_word ( &buffer ) ;
  92.     head -> start                = make_word ( &buffer ) ;
  93.     head -> vocab                = make_word ( &buffer ) ;
  94.     head -> object_list            = make_word ( &buffer ) ;
  95.     head -> globals                = make_word ( &buffer ) ;
  96.     head -> save_bytes            = make_word ( &buffer ) ;
  97.     head -> script_status        = make_word ( &buffer ) ;
  98.     for ( i = 0 ; i < 6 ; i++ )
  99.         head -> serial_no[i] = *buffer++ ;
  100.     head -> common_word            = make_word ( &buffer ) ;
  101.     head -> verify_length        = make_word ( &buffer ) ;
  102.     head -> verify_checksum        = make_word ( &buffer ) ;
  103.     head -> interpreter_number    = *buffer++ ;
  104.     head -> interpreter_version    = *buffer++ ;
  105.     head -> screen_height        = *buffer++ ;
  106.     head -> screen_width        = *buffer++ ;
  107.     head -> left                = *buffer++ ;
  108.     head -> right                = *buffer++ ;
  109.     head -> top                    = *buffer++ ;
  110.     head -> bottom                = *buffer++ ;
  111.     head -> unknown1            = *buffer++ ;
  112.     head -> unknown2            = *buffer++ ;
  113.     for ( i = 0 ; i < 2 ; i++ )
  114.         head -> padding1[i] = make_word ( &buffer ) ;
  115.     head -> unknown3            = *buffer++ ;
  116.     head -> unknown4            = *buffer++ ;
  117.     head -> unknown5            = make_word ( &buffer ) ;
  118.     for ( i = 0 ; i < 3 ; i++ )
  119.         head -> padding2[i] = make_word ( &buffer ) ;
  120.     head -> unknown6            = make_word ( &buffer ) ;
  121.     for ( i = 0 ; i < 4 ; i++ )
  122.         head -> padding3[i] = make_word ( &buffer ) ;
  123. }
  124.  
  125. word
  126. make_word ( ptr )
  127. byte_ptr    *ptr ;
  128. {
  129.     /*
  130.     **    Form a word from two bytes.
  131.     **    (High byte before Low byte)
  132.     */
  133.  
  134.     word    value ;
  135.  
  136.     value = *(*ptr)++ ;
  137.     value = ( value << 8 ) + *(*ptr)++ ;
  138.     return ( value ) ;
  139. }
  140.  
  141. int
  142. open_file ( filename )
  143. char    *filename ;
  144. {
  145.     /*
  146.     **    Open a File for Reading
  147.     */
  148.  
  149.     if (( game_file = fopen ( filename,READ_STRING )) == (FILE *)0 )
  150.         return ( FALSE ) ;
  151.     return ( TRUE ) ;
  152. }
  153.  
  154. Void
  155. close_file ()
  156. {
  157.     /*
  158.     **    Close an Open File
  159.     */
  160.  
  161.     if ( game_file != (FILE *)0 )
  162.     {
  163.         if ( fclose ( game_file ) )
  164.             display ( "Cannot Close Game File\n" ) ;
  165.         game_file = (FILE *)0 ;
  166.     }
  167. }
  168.  
  169. Void
  170. load_page ( block,num_blocks,ptr )
  171. word        block ;
  172. word        num_blocks ;
  173. byte_ptr    ptr ;
  174. {
  175.     long    offset ;
  176.  
  177.     /*
  178.     **    Read "num_block" blocks from Game File,
  179.     **    starting with block "block", at the
  180.     **    location pointed to by "ptr".
  181.     */
  182.  
  183.     offset = (long) block * BLOCK_SIZE ;
  184.     if ( fseek ( game_file,offset,0 ) < 0 )
  185.     {
  186.         display ( "Failed to Seek required Blocks\n" ) ;
  187.         quit () ;
  188.     }
  189.     else
  190.     {
  191.         if ( (int)fread ((char *)ptr,BLOCK_SIZE,(int)num_blocks,game_file) < 0 )
  192.         {
  193.                 display ( "Failed to Read required Blocks\n" ) ;
  194.                 quit () ;
  195.         }
  196.     }
  197. }
  198.  
  199. boolean
  200. filename ()
  201. {
  202.     char    ch ;
  203.     int        i ;
  204.  
  205.     display ( "Filename: " ) ;
  206.     i = 0 ;
  207.     while (( ch = read_char () ) != '\n' )
  208.     {
  209.         /* Handle backspaces */
  210.  
  211.         if (( ch == '\b' ) && ( i != 0 ))
  212.             --i ;
  213.  
  214.         /* Convert Uppercase to Lowercase */
  215.  
  216.         if (( ch >= 'A' ) && ( ch <= 'Z' ))
  217.             ch = ch - 'A' + 'a' ;
  218.  
  219.         /* Handle Alpha-numeric Characters */
  220.  
  221.         if (( ch >= 'a' ) && ( ch <= 'z' ) && ( i < NAME_SIZE ))
  222.             name[i++] = ch ;
  223.         if (( ch >= '0' ) && ( ch <= '9' ) && ( i < NAME_SIZE ))
  224.             name[i++] = ch ;
  225.  
  226.         /* Handle Pathname Characters */
  227.  
  228.         if ((ch == '/' || ch == ':' || ch == '.') && (i < NAME_SIZE))
  229.             name[i++] = ch ;
  230.     }
  231.     name[i] = '\0' ;
  232.     if ( i == 0 )
  233.     {
  234.         display ( "Bad Filename. Try Again...\n" ) ;
  235.         return ( FALSE ) ;
  236.     }
  237.     return ( TRUE ) ;
  238. }
  239.  
  240. boolean
  241. put_word ( save_file,number )
  242. FILE    *save_file ;
  243. word    number ;
  244. {
  245.     /*
  246.     **    Returns TRUE if an Error Occurred.
  247.     */
  248.  
  249.     byte    c ;
  250.  
  251.     c = MOST_SIGNIFICANT_BYTE ( number ) ;
  252.     if ( fwrite ((char *)&c,sizeof(byte),1,save_file) != 1 )
  253.         return ( TRUE ) ;
  254.     c = LEAST_SIGNIFICANT_BYTE ( number ) ;
  255.     if ( fwrite ((char *)&c,sizeof(byte),1,save_file) != 1 )
  256.         return ( TRUE ) ;
  257.     return ( FALSE ) ;
  258. }
  259.  
  260. boolean
  261. ld_word ( save_file,number )
  262. FILE    *save_file ;
  263. word    *number ;
  264. {
  265.     /*
  266.     **    Returns TRUE if an Error Occurred.
  267.     */
  268.  
  269.     byte    c ;
  270.  
  271.     if ( fread ((char *)&c,sizeof(byte),1,save_file) != 1 )
  272.         return ( TRUE ) ;
  273.     *number = c << 8 ;
  274.     if ( fread ((char *)&c,sizeof(byte),1,save_file) != 1 )
  275.         return ( TRUE ) ;
  276.     *number |= c ;
  277.     return ( FALSE ) ;
  278. }
  279.  
  280. Void
  281. save_game ()
  282. {
  283.     extern header        data_head ;
  284.     extern byte_ptr        base_ptr ;
  285.     extern word            *stack_base ;
  286.     extern word            *stack_var_ptr ;
  287.     extern word            *stack ;
  288.     extern word            stack_space[] ;
  289.     extern word            pc_page ;
  290.     extern word            pc_offset ;
  291.     extern word            save_blocks ;
  292.  
  293.     FILE                *save_file ;
  294.     boolean                err = FALSE ;
  295.     word                s_offset ;
  296.     int                    i ;
  297.  
  298.     /*
  299.     **    Save a Game.
  300.     **
  301.     **    Swapping Saved Game Files between machines is OK provided the
  302.     **    macro "STACK_SIZE" in file "infocom.h" is the same on each machine.
  303.     **
  304.     **    For the Standard & Enhanced Interpreters:
  305.     **                            "ret_value ( FALSE )" -> Save/Restore Error.
  306.     **                            "ret_value ( TRUE )"  -> Save/Restore was Ok.
  307.     **
  308.     **    For the PLUS Series Interpreter:
  309.     **                            "store ( (word)0 )" -> Save/Restore Error.
  310.     **                            "store ( (word)1 )" -> Save was Ok.
  311.     **                            "store ( (word)2 )" -> Restore was Ok.
  312.     */
  313.  
  314.     while ( ! filename () ) ;
  315.     if (( save_file = fopen ( name,WRITE_STRING )) == (FILE *)0 )
  316.     {
  317.         if ( data_head.z_code_version <= VERSION_3 )
  318.             ret_value ( FALSE ) ;
  319.         else
  320.             store ( (word)0 ) ;
  321.         return ;
  322.     }
  323.     if (fwrite((char *)base_ptr,BLOCK_SIZE,(int)save_blocks,save_file) != save_blocks)
  324.         err = TRUE ;
  325.  
  326.     /*
  327.     **    Save the Stack, Stack Pointers & Program Counter
  328.     */
  329.  
  330.     for ( i = 0 ; i < (int)STACK_SIZE ; i++ )
  331.         err |= put_word ( save_file,stack_space[i] ) ;
  332.     s_offset = stack_base - stack ;
  333.     err |= put_word ( save_file,s_offset ) ;
  334.     s_offset = stack_base - stack_var_ptr ;
  335.     err |= put_word ( save_file,s_offset ) ;
  336.     err |= put_word ( save_file,pc_page ) ;
  337.     err |= put_word ( save_file,pc_offset ) ;
  338.  
  339.     if ( fclose ( save_file ) )
  340.         err = TRUE ;
  341.     if ( data_head.z_code_version <= VERSION_3 )
  342.     {
  343.         if ( err )
  344.             ret_value ( FALSE ) ;
  345.         else
  346.             ret_value ( TRUE ) ;
  347.     }
  348.     else
  349.     {
  350.         if ( err )
  351.             store ( (word)0 ) ;
  352.         else
  353.             store ( (word)1 ) ;
  354.     }
  355. }
  356.  
  357. boolean
  358. check ( info )
  359. header    *info ;
  360. {
  361.     extern header    data_head ;
  362.  
  363.     register int    i ;
  364.  
  365.     /*
  366.     **
  367.     **    Note:
  368.     **        The parameter "info" is of type "header *"
  369.     **        NOT "header_ptr" - these definitions are
  370.     **        different for MSDOS Compilers ("header_ptr" is huge).
  371.     */
  372.  
  373.     if ( info -> z_code_version != data_head.z_code_version )
  374.         return ( FALSE ) ;
  375.     if ( info -> mode_bits != data_head.mode_bits )
  376.         return ( FALSE ) ;
  377.     if ( info -> release != data_head.release )
  378.         return ( FALSE ) ;
  379.     for ( i = 0 ; i < 6 ; i++ )
  380.         if ( info -> serial_no[i] != data_head.serial_no[i] )
  381.             return ( FALSE ) ;
  382.     if ( info -> verify_length != data_head.verify_length )
  383.         return ( FALSE ) ;
  384.     if ( info -> verify_checksum != data_head.verify_checksum )
  385.         return ( FALSE ) ;
  386.     return ( TRUE ) ;
  387. }
  388.  
  389. Void
  390. restore_game ()
  391. {
  392.     extern header        data_head ;
  393.     extern byte_ptr        base_ptr ;
  394.     extern word            *stack_base ;
  395.     extern word            *stack_var_ptr ;
  396.     extern word            *stack ;
  397.     extern word            stack_space[] ;
  398.     extern word            pc_page ;
  399.     extern word            pc_offset ;
  400.     extern word            save_blocks ;
  401.  
  402.     FILE                *save_file ;
  403.     header                test ;
  404.     boolean                err = FALSE ;
  405.     word                s_offset ;
  406.     int                    i ;
  407.  
  408.     /*
  409.     **    Restore a Saved Game
  410.     **
  411.     **    Swapping Saved Game Files between machines is OK provided the
  412.     **    macro "STACK_SIZE" in file "infocom.h" is the same on each machine.
  413.     **
  414.     **    For the Standard & Enhanced Interpreters:
  415.     **                            "ret_value ( FALSE )" -> Save/Restore Error.
  416.     **                            "ret_value ( TRUE )"  -> Save/Restore was Ok.
  417.     **
  418.     **    For the PLUS Series Interpreter:
  419.     **                            "store ( (word)0 )" -> Save/Restore Error.
  420.     **                            "store ( (word)1 )" -> Save was Ok.
  421.     **                            "store ( (word)2 )" -> Restore was Ok.
  422.     */
  423.  
  424.     while ( ! filename () ) ;
  425.     if (( save_file = fopen ( name,READ_STRING )) == (FILE *)0 )
  426.     {
  427.         if ( data_head.z_code_version <= VERSION_3 )
  428.             ret_value ( FALSE ) ;
  429.         else
  430.             store ( (word)0 ) ;
  431.         return ;
  432.     }
  433.     if (fread((char *)base_ptr,BLOCK_SIZE,(int)save_blocks,save_file) != save_blocks)
  434.         err = TRUE ;
  435.  
  436.     /*
  437.     **    Restore Stack, Stack Pointers & Program Counter
  438.     */
  439.  
  440.     for ( i = 0 ; i < (int)STACK_SIZE ; i++ )
  441.         err |= ld_word ( save_file,&stack_space[i] ) ;
  442.     err |= ld_word ( save_file,&s_offset ) ;
  443.     stack = stack_base - s_offset ;
  444.     err |= ld_word ( save_file,&s_offset ) ;
  445.     stack_var_ptr = stack_base - s_offset ;
  446.     err |= ld_word ( save_file,&pc_page ) ;
  447.     err |= ld_word ( save_file,&pc_offset ) ;
  448.  
  449.     if ( fclose ( save_file ) )
  450.         err = TRUE ;
  451.  
  452.     /*
  453.     **    Check the validity of the restored game file.
  454.     */
  455.  
  456.     assign ( &test,base_ptr ) ;
  457.     if (( ! err ) && check ( &test ))
  458.     {
  459.         init_interpreter ( FALSE ) ;
  460.         if ( data_head.z_code_version <= VERSION_3 )
  461.             ret_value ( TRUE );
  462.         else
  463.             store ( (word)2 ) ;
  464.     }
  465.     else
  466.     {
  467.         display ( "Wrong Game or Version ...\nRestarting ...\n" ) ;
  468.         restart () ;
  469.     }
  470. }
  471.  
  472. /*
  473. **    Scripting Routines and Variables.
  474. */
  475.  
  476. /*    Level 2 patch installed -mlk */
  477. FILE        *script_file        = (FILE *)0 ;
  478. byte        tmp_script_status       = 0 ;
  479. byte_ptr    script_status_ptr       = (byte_ptr)&tmp_script_status ;
  480.  
  481. Void
  482. init_script ()
  483. {
  484.     extern byte_ptr        base_ptr ;
  485.     extern byte_ptr        script_status_ptr ;
  486.     extern boolean        script_on ;
  487.  
  488.     script_status_ptr = (byte_ptr) &(((header_ptr)base_ptr) -> script_status) ;
  489.     script_status_ptr++ ;
  490.     script_on = FALSE ;
  491. }
  492.  
  493. boolean
  494. open_script ()
  495. {
  496.     extern char        name[] ;
  497.     extern FILE        *script_file ;
  498.  
  499.     while ( ! filename () ) ;
  500.     if (( script_file = fopen ( name,APPEND_STRING )) == (FILE *)0 )
  501.         return ( FALSE ) ;
  502.     return ( TRUE ) ;
  503. }
  504.  
  505. Void
  506. close_script ()
  507. {
  508.     extern FILE        *script_file ;
  509.  
  510.     if ( script_file != (FILE *)0 )
  511.     {
  512.         if ( fclose ( script_file ) )
  513.             display ( "Cannot Close Script File\n" ) ;
  514.         script_file = (FILE *)0 ;
  515.     }
  516. }
  517.  
  518. Void
  519. script_char ( c )
  520. char    c ;
  521. {
  522.     extern header    data_head ;
  523.     extern FILE        *script_file ;
  524.     extern boolean    disable_script ;
  525.     extern boolean    script_on ;
  526.     extern byte_ptr    script_status_ptr ;
  527.  
  528.     if ( data_head.z_code_version <= VERSION_3 )
  529.     {
  530.         if (( script_on ) && (( *script_status_ptr & SCRIPT_MODE_ON ) == 0 ))
  531.         {
  532.             script_on = FALSE ;
  533.             data_head.script_status &= SCRIPT_MODE_OFF ;
  534.             close_script () ;
  535.             return ;
  536.         }
  537.         if (( ! script_on ) && ( *script_status_ptr & SCRIPT_MODE_ON ))
  538.         {
  539.             /*
  540.             **    We must temporarily turn off the "SCRIPT_MODE" bit that
  541.             **    is pointed to by "script_status_ptr" because "script_on"
  542.             **    must remain "FALSE" until the script file is open and
  543.             **    "open_script ()" calls "filename ()" which calls
  544.             **    "read_char ()" which calls this routine which will try to
  545.             **    open a script file by calling "open_script ()" ...
  546.             **
  547.             **    The "SCRIPT_MODE" bit is turned back on if the script file
  548.             **    is successfully opened.
  549.             */
  550.  
  551.             *script_status_ptr &= SCRIPT_MODE_OFF ;
  552.             if (( script_on = open_script () ) == TRUE )
  553.             {
  554.                 *script_status_ptr |= SCRIPT_MODE_ON ;
  555.                 data_head.script_status |= SCRIPT_MODE_ON ;
  556.             }
  557.         }
  558.     }
  559.  
  560.     if (( script_on ) && ( ! disable_script ) && ( c >= 6 ))
  561.         putc ( c,script_file ) ;
  562. }
  563.