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