
/*
 * zip.c
 *
 * Z code interpreter main routine. Plays Infocom type 1, 2, 3, 4 and 5 games.
 *
 * Usage: zip [options] story-file-name
 *
 * options are:
 *
 *    -l n - number of lines in display
 *    -c n - number of columns in display
 *    -r n - right margin (default = 0)
 *    -t n - top margin (default = 0)
 *
 * This is a no bells and whistles Infocom interpreter for type 1 to 5 games.
 * It will automatically detect which type of game you want to play. It should
 * support all type 1 to 5 features and is based loosely on the MS-DOS version
 * with enhancements to aid portability. Read the readme.1st file for
 * information on building this program on your favourite operating system.
 * Please mail me, at the address below, if you find bugs in the code.
 *
 * Special thanks to David Doherty and Olaf Barthel for testing this program
 * and providing invaluable help and code to aid its portability.
 *
 * Mark Howell 10-Mar-93 V2.0 howell_ma@movies.enet.dec.com
 *
 * Disclaimer:
 *
 * You are expressly forbidden to use this program if in so doing you violate
 * the copyright notice supplied with the original Infocom game.
 *
 */


#include <stdlib.h>
#include <string.h>
#include "ztypes.h"

#ifdef __STDC__
static void configure (zbyte_t, zbyte_t, z_globals *);
#else
static void configure ();
#endif

/*
 * main
 *
 * Initialise environment, start interpreter, clean up.
 *
 */

#ifdef __STDC__
int main (int argc, char *argv[])
#else
int main (argc, argv)
int argc;
char *argv[];
#endif
{
  z_globals *gl;

  gl = init_globals();

    process_arguments (argc, argv, gl);

    configure (V1, V8, gl);

    initialize_screen (gl);

    load_cache (gl);

    restart (gl);

    do {
      interpret (gl);
      printf("\nGETTING INPUT HACK: ");
      fgets(input_hack, sizeof(input_hack), stdin);
      fprintf(stderr, "\n\n\nGETTING INPUT HACK: %s\n", input_hack);
      if (!strcmp(input_hack, "xyzzy")) break;
    } while(1);

    unload_cache (gl);

    close_story (gl);

    close_script (gl);

    reset_screen (gl);

    free_globals(gl);

    exit (EXIT_SUCCESS);

    return (0);

}/* main */

/*
 * configure
 *
 * Initialise global and type specific variables.
 *
 */

#ifdef __STDC__
static void configure (zbyte_t min_version, zbyte_t max_version, z_globals *gl)
#else
static void configure (min_version, max_version, gl)
zbyte_t min_version;
zbyte_t max_version;
z_globals *gl;
#endif
{
    zbyte_t header[PAGE_SIZE];

    read_page (0, header, gl);
    (gl->datap) = header;

    gl->h_type = get_byte (H_TYPE);

    if (gl->h_type < min_version || gl->h_type > max_version || (get_byte (H_CONFIG) & CONFIG_BYTE_SWAPPED))
        fatal ("wrong game or version", gl);

    if (gl->h_type == V6 || gl->h_type == V7)
        fatal ("Unsupported zcode version.", gl);

    if (gl->h_type < V4) {
        gl->story_scaler = 2;
        gl->story_shift = 1;
        gl->property_mask = P3_MAX_PROPERTIES - 1;
        gl->property_size_mask = 0xe0;
    } else {
        gl->story_scaler = 4;
        gl->story_shift = 2;
        gl->property_mask = P4_MAX_PROPERTIES - 1;
        gl->property_size_mask = 0x3f;
    }

    if (gl->h_type == V8) { 
      gl->h_type=V5; 
      gl->story_scaler = 8; 
    }

    gl->h_config = get_byte (H_CONFIG);
    gl->h_version = get_word (H_VERSION);
    gl->h_data_size = get_word (H_DATA_SIZE);
    gl->h_start_pc = get_word (H_START_PC);
    gl->h_words_offset = get_word (H_WORDS_OFFSET);
    gl->h_objects_offset = get_word (H_OBJECTS_OFFSET);
    gl->h_globals_offset = get_word (H_GLOBALS_OFFSET);
    gl->h_restart_size = get_word (H_RESTART_SIZE);
    gl->h_flags = get_word (H_FLAGS);
    gl->h_synonyms_offset = get_word (H_SYNONYMS_OFFSET);
    gl->h_file_size = get_word (H_FILE_SIZE);
    if (gl->h_file_size == 0)
        gl->h_file_size = get_story_size (gl);
    gl->h_checksum = get_word (H_CHECKSUM);
    gl->h_alternate_alphabet_offset = get_word (H_ALTERNATE_ALPHABET_OFFSET);

    (gl->datap) = NULL;

}/* configure */
