/*
 * Quick little program to turn your Zork 0 into a Zork 0 demonstration
 * Game. For those that don't know, the "Demo" version is contained in
 * the game file of Zork 0.  If a certain global variable was set, then
 * the game would run in "demonstration" mode, where it would start with
 * a preview of some graphics in the game, then switch to a limited
 * area of the game for the player to explore. 
 * 
 * Does anyone know if the demonstration mode was ever used, or was it
 * it just legacy code left over?
 * 
 * I wonder if Activision would mind people distributing demo zork 0's...
 *
 * Sept 28: Added fix for release 383.  Added line to modify checksum
 *
 * earendil@faeryland.tamu-commerce.edu
 */
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>

#define WORD(ad) ((unsigned char) fcontents[ad] * 256 + \
		  (unsigned char) fcontents[ad+1])

#define FATAL(str) { printf str; return 1; }

int file_size(char *f) {
  struct stat *statbuf;

  statbuf = (struct stat *) malloc(sizeof(struct stat));
  stat(f, statbuf);
  
  return statbuf->st_size;
}
  
int main(int argc, char *argv[]) {
  FILE *game, *dest;
  char *fcontents;

  int addr, release, sz, var;

  if( argc != 3 )
    FATAL(("Usage: %s [zork0 file] [newfile]\n", argv[0]));
  if( (game = fopen(argv[1], "r")) == NULL )
    FATAL(("Unable to open %s for reading\n", argv[1]));
  if( (dest = fopen(argv[2], "w")) == NULL ) 
    FATAL(("Unable to open %s\n", argv[2]));

  sz = file_size(argv[1]);
 
  fcontents = (char *) malloc(sizeof(char) * sz);
  if( fread(fcontents, 1,  sz, game) != sz )
    FATAL(("Unable to read %d bytes of %s\n", sz, argv[2]));

  switch( release = WORD(2) ) { 	/* Release # */
    case 366:
    case 383:
    case 393: var =   6; break;
    case 296: var = 107; break;
    default:  fprintf(stderr, "Unknown release number: %d\n", release);
	      return 1;
  }
  addr = WORD(12) + 2 * var;
  if( addr > sz )
    FATAL(("Eek! Global variable addr outside of file.  Game file corrupt?\n"));

  fcontents[addr] = 1;			/* Set demo variable */
  fcontents[0x1d]++;			/* Fix the checksum */

  fwrite(fcontents, sz, 1, dest);
  return 0;
}
