/*  Sarien - A Sierra AGI resource interpreter engine
 *  Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka
 *  
 *  $Id: id.c,v 1.34 2001/11/04 02:33:45 cmatsuoka Exp $
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; see docs/COPYING for further details.
 */

#ifndef PALMOS

#include <stdio.h>
#include <string.h>
#include "sarien.h"
#include "agi.h"
#include "opcodes.h"

/*
 * Determine what AGI v2 system to emulate, these are the major version
 * to emulate, thus 2.915 comes under 2.917, 2.4xxx is 2.440, etc.
 *
 * 0x2089
 * 0x2272
 * 0x2440
 * 0x2917
 * 0x2936
 */

int setup_v2_game(int ver, UINT32 crc);
int setup_v3_game(int ver, UINT32 crc);
int v4id_game (UINT32 crc);

void list_games ()
{
	FILE *f;
	char *c, *t, buf[256];
	UINT32 id, ver;
	int min, maj, i = 0;

	/**/
	f = fopen (get_config_file(), "r");

	printf (
"Game#  AGI ver.   Title                                    CRC\n"
"------ ---------- ---------------------------------------- -------\n"
	);

	while (!feof (f)) {
		fgets (buf, 256, f);
		c = strchr (buf, '#');
		if (c) *c = 0;

		/* Remove spaces at end of line */
		if (strlen (buf)) {
			for (c = buf + strlen (buf) - 1;
				*c == ' ' || *c == '\t'; *c-- = 0) {}
		}


		t = strtok (buf, " \t\r\n");
		if (t == NULL)
			continue;
		id = strtoul (t, NULL, 0);

		t = strtok (NULL, " \t\r\n");
		if (t == NULL)
			continue;
		ver = strtoul (t, NULL, 0);
		maj = (ver >> 12) & 0xf;
		min = ver & 0xfff;

		t = strtok (NULL, "\n\r");

		if (maj == 2) {
			printf ("[%3d]  %x.%03x      %-40.40s 0x%05x\n",
				++i, maj, min, t, id);
		} else {
			printf ("[%3d]  %x.002.%03x  %-40.40s 0x%05x\n",
				++i, maj, min, t, id);
		}
	}

	fclose (f);
}

static UINT32 match_crc (UINT32 crc, char *path)
{
	FILE *f;
	char *c, *t, buf[256];
	UINT32 id, ver;

	if ((f = fopen (path, "r")) == NULL)
		return 0;

	while (!feof (f)) {
		fgets (buf, 256, f);
		c = strchr (buf, '#');
		if (c) *c = 0;

		/* Remove spaces at end of line */
		if (strlen (buf)) {
			for (c = buf + strlen (buf) - 1;
				*c == ' ' || *c == '\t'; *c-- = 0) {}
		}


		t = strtok (buf, " \t\r\n");
		if (t == NULL)
			continue;
		id = strtoul (t, NULL, 0);

		t = strtok (NULL, " \t\r\n");
		if (t == NULL)
			continue;
		ver = strtoul (t, NULL, 0);

		t = strtok (NULL, "\n\r");

		if (id == crc) {
			/* Now we must check options enclosed in brackets
		 	 * like [A] for Amiga
			 */

			if (*t == '[') {
				while (*t != ']') {
					switch (*t++) {
					case 'A':
						opt.amiga = TRUE;
						break;
					case 'a':
						opt.agds = TRUE;
						break;
#ifdef USE_MOUSE
					case 'm':
						opt.agimouse = TRUE;
						break;
#endif
					}
				}
				t++;

				for (; *t == ' ' || *t == '\t'; t++) {}
			}

			report ("AGI game detected: %s\n\n", t);
			fclose (f);
			return ver;
		}
	}

	fclose (f);

	return 0;
}


static UINT32 match_version (UINT32 crc)
{
	int ver;
	char *fname;

	fname = get_config_file();
	ver = match_crc(crc, fname);

	return ver;
}


int v2id_game ()
{
#ifdef __MPW__
	return err_OK;		/* FIXME! */
#else
	int y, ver;
	UINT32 len, c, crc;
	UINT8 *buff;
	FILE *fp;
	char *fn[] = { "viewdir", "logdir", "picdir", "snddir",
		"words.tok", "object", "" };

	/*_D (_D_WARN);*/
	buff = malloc (8192);

	for (crc = y = 0; fn[y][0]; y++) {
		char *path = fixpath (NO_GAMEDIR, fn[y]);
		if ((fp = fopen (path, "rb")) != NULL) {
			for (len = 1; len > 0; ) {
				memset (buff, 0, 8192);
				len = fread (buff, 1, 8000, fp);
				for (c = 0; c < len; c++)
					crc += *(buff + c);
			}
			fclose (fp);
		}
	}
	free (buff);

	report ("Computed CRC: 0x%05x\n", crc);
	ver = match_version (crc);
	game.crc = crc;
	game.ver = ver;
	agi_set_release (ver);
	return setup_v2_game(ver, crc);
#endif
}

/*
 * Currently, there is no known difference between v3.002.098 -> v3.002.149
 * So version emulated;
 *
 * 0x0086,
 * 0x0149
 */

int v3id_game ()
{
	int ec = err_OK, y, ver;
	UINT32 len, c, crc;
	UINT8 *buff;
	FILE *fp;
	char *path, *fn[] = { "words.tok", "object", "" };

	buff = malloc (8192);

	for (crc = 0, y = 0; fn[y][0]!=0x0; y++) {
		path = fixpath (NO_GAMEDIR, fn[y]);
		if ((fp = fopen (path, "rb")) != NULL) {
			len = 1;
			while (len > 0) {
				memset (buff, 0, 8192);
				len = fread (buff, 1, 8000, fp);
				for (c = 0; c < len; c++)
					crc += *(buff + c);
			}
			fclose(fp);
		}
	}

	/* no do the directory file */

	path = fixpath (GAMEDIR, DIR_);

	if ((fp = fopen(path, "rb")) != NULL) {
		for (len = 1; len > 0; ) {
			memset (buff, 0, 8192);
			len = fread (buff, 1, 8000, fp);
			for (c = 0; c < len; c++)
				crc += *(buff + c);
		}
		fclose (fp);
	}

	free (buff);

	report ("Computed CRC: 0x%05x\n", crc);
	ver = match_version (crc);
	game.crc = crc;
	game.ver = ver;
	agi_set_release (ver);

	ec = setup_v3_game(ver, crc);

	
	return ec;
}


#ifdef PALMOS

int v4id_game (UINT32 crc)
{
	int ec = err_OK, ver;	

	ver = match_version (crc);
	agi_set_release (ver);
	
	switch ((ver>>12)&0xFF) {
	case 2:
		ec = setup_v2_game (ver, crc);
		break;
	case 3:
		ec = setup_v3_game (ver, crc);
		break;
	}

	return ec;
}

#endif

/**
 *
 */
int setup_v2_game (int ver, UINT32 crc)
{
	int ec=err_OK;

	if (ver == 0) {
		report ("Unknown v2 Sierra game: %08x\n\n", crc);
		agi_set_release (0x2917);
	}

	/* setup the differences in the opcodes and other bits in the
	 * AGI v2 specs
	 */
	if (opt.emuversion)
		agi_set_release (opt.emuversion);

	if (opt.agds)
		agi_set_release (0x2440);/* ALL AGDS games built for 2.440 */

	switch(agi_get_release ()) {
	case 0x2089:
		logic_names_cmd[0x86].num_args = 0;	/* quit: 0 args */
	case 0x2272:
		logic_names_cmd[0x97].num_args = 3;	/* print.at: 3 args */
		logic_names_cmd[0x98].num_args = 3;	/* print.at.v: 3 args*/
		break;
	case 0x2440:
		break;
	case 0x2917:
		break;
	case 0x2936:
		break;
	default:
		report ("** Cannot setup for unknown version\n");
		ec = err_UnknownAGIVersion;
		break;
	}

	return ec;
}

/**
 *
 */
int setup_v3_game (int ver, UINT32 crc)
{
	int ec = err_OK;
	
	if (ver == 0) {
		report ("Unknown v3 Sierra game: %08x\n\n", crc);
		agi_set_release (ver = 0x3149);
	}

	if (opt.emuversion)
		agi_set_release (ver = opt.emuversion);

	switch(ver) {
	case 0x3086:
		logic_names_cmd[0xad].num_args = 1;	/* 173 : 1 args */
		break;
	case 0x3149:
		logic_names_cmd[0xad].num_args = 0;	/* 173 : 0 args */
		break;
	default:
		report ("Error: cannot setup for unknown version\n");
		ec = err_UnknownAGIVersion;
		break;
	}
	
	return ec;
}

#endif
