/*
* 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
*
* [email protected]
*/
#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;
}