1 /*  Sarien - A Sierra AGI resource interpreter engine
2  *  Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka
3  *
4  *  $Id: id.c,v 1.34 2001/11/04 02:33:45 cmatsuoka Exp $
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; see docs/COPYING for further details.
9  */
10 
11 #ifndef PALMOS
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include "sarien.h"
16 #include "agi.h"
17 #include "opcodes.h"
18 
19 /*
20  * Determine what AGI v2 system to emulate, these are the major version
21  * to emulate, thus 2.915 comes under 2.917, 2.4xxx is 2.440, etc.
22  *
23  * 0x2089
24  * 0x2272
25  * 0x2440
26  * 0x2917
27  * 0x2936
28  */
29 
30 int setup_v2_game(int ver, UINT32 crc);
31 int setup_v3_game(int ver, UINT32 crc);
32 int v4id_game (UINT32 crc);
33 
list_games()34 void list_games ()
35 {
36 	FILE *f;
37 	char *c, *t, buf[256];
38 	UINT32 id, ver;
39 	int min, maj, i = 0;
40 
41 	/**/
42 	f = fopen (get_config_file(), "r");
43 
44 	printf (
45 "Game#  AGI ver.   Title                                    CRC\n"
46 "------ ---------- ---------------------------------------- -------\n"
47 	);
48 
49 	while (!feof (f)) {
50 		fgets (buf, 256, f);
51 		c = strchr (buf, '#');
52 		if (c) *c = 0;
53 
54 		/* Remove spaces at end of line */
55 		if (strlen (buf)) {
56 			for (c = buf + strlen (buf) - 1;
57 				*c == ' ' || *c == '\t'; *c-- = 0) {}
58 		}
59 
60 
61 		t = strtok (buf, " \t\r\n");
62 		if (t == NULL)
63 			continue;
64 		id = strtoul (t, NULL, 0);
65 
66 		t = strtok (NULL, " \t\r\n");
67 		if (t == NULL)
68 			continue;
69 		ver = strtoul (t, NULL, 0);
70 		maj = (ver >> 12) & 0xf;
71 		min = ver & 0xfff;
72 
73 		t = strtok (NULL, "\n\r");
74 
75 		if (maj == 2) {
76 			printf ("[%3d]  %x.%03x      %-40.40s 0x%05x\n",
77 				++i, maj, min, t, id);
78 		} else {
79 			printf ("[%3d]  %x.002.%03x  %-40.40s 0x%05x\n",
80 				++i, maj, min, t, id);
81 		}
82 	}
83 
84 	fclose (f);
85 }
86 
match_crc(UINT32 crc,char * path)87 static UINT32 match_crc (UINT32 crc, char *path)
88 {
89 	FILE *f;
90 	char *c, *t, buf[256];
91 	UINT32 id, ver;
92 
93 	if ((f = fopen (path, "r")) == NULL)
94 		return 0;
95 
96 	while (!feof (f)) {
97 		fgets (buf, 256, f);
98 		c = strchr (buf, '#');
99 		if (c) *c = 0;
100 
101 		/* Remove spaces at end of line */
102 		if (strlen (buf)) {
103 			for (c = buf + strlen (buf) - 1;
104 				*c == ' ' || *c == '\t'; *c-- = 0) {}
105 		}
106 
107 
108 		t = strtok (buf, " \t\r\n");
109 		if (t == NULL)
110 			continue;
111 		id = strtoul (t, NULL, 0);
112 
113 		t = strtok (NULL, " \t\r\n");
114 		if (t == NULL)
115 			continue;
116 		ver = strtoul (t, NULL, 0);
117 
118 		t = strtok (NULL, "\n\r");
119 
120 		if (id == crc) {
121 			/* Now we must check options enclosed in brackets
122 		 	 * like [A] for Amiga
123 			 */
124 
125 			if (*t == '[') {
126 				while (*t != ']') {
127 					switch (*t++) {
128 					case 'A':
129 						opt.amiga = TRUE;
130 						break;
131 					case 'a':
132 						opt.agds = TRUE;
133 						break;
134 #ifdef USE_MOUSE
135 					case 'm':
136 						opt.agimouse = TRUE;
137 						break;
138 #endif
139 					}
140 				}
141 				t++;
142 
143 				for (; *t == ' ' || *t == '\t'; t++) {}
144 			}
145 
146 			report ("AGI game detected: %s\n\n", t);
147 			fclose (f);
148 			return ver;
149 		}
150 	}
151 
152 	fclose (f);
153 
154 	return 0;
155 }
156 
157 
match_version(UINT32 crc)158 static UINT32 match_version (UINT32 crc)
159 {
160 	int ver;
161 	char *fname;
162 
163 	fname = get_config_file();
164 	ver = match_crc(crc, fname);
165 
166 	return ver;
167 }
168 
169 
v2id_game()170 int v2id_game ()
171 {
172 #ifdef __MPW__
173 	return err_OK;		/* FIXME! */
174 #else
175 	int y, ver;
176 	UINT32 len, c, crc;
177 	UINT8 *buff;
178 	FILE *fp;
179 	char *fn[] = { "viewdir", "logdir", "picdir", "snddir",
180 		"words.tok", "object", "" };
181 
182 	/*_D (_D_WARN);*/
183 	buff = malloc (8192);
184 
185 	for (crc = y = 0; fn[y][0]; y++) {
186 		char *path = fixpath (NO_GAMEDIR, fn[y]);
187 		if ((fp = fopen (path, "rb")) != NULL) {
188 			for (len = 1; len > 0; ) {
189 				memset (buff, 0, 8192);
190 				len = fread (buff, 1, 8000, fp);
191 				for (c = 0; c < len; c++)
192 					crc += *(buff + c);
193 			}
194 			fclose (fp);
195 		}
196 	}
197 	free (buff);
198 
199 	report ("Computed CRC: 0x%05x\n", crc);
200 	ver = match_version (crc);
201 	game.crc = crc;
202 	game.ver = ver;
203 	agi_set_release (ver);
204 	return setup_v2_game(ver, crc);
205 #endif
206 }
207 
208 /*
209  * Currently, there is no known difference between v3.002.098 -> v3.002.149
210  * So version emulated;
211  *
212  * 0x0086,
213  * 0x0149
214  */
215 
v3id_game()216 int v3id_game ()
217 {
218 	int ec = err_OK, y, ver;
219 	UINT32 len, c, crc;
220 	UINT8 *buff;
221 	FILE *fp;
222 	char *path, *fn[] = { "words.tok", "object", "" };
223 
224 	buff = malloc (8192);
225 
226 	for (crc = 0, y = 0; fn[y][0]!=0x0; y++) {
227 		path = fixpath (NO_GAMEDIR, fn[y]);
228 		if ((fp = fopen (path, "rb")) != NULL) {
229 			len = 1;
230 			while (len > 0) {
231 				memset (buff, 0, 8192);
232 				len = fread (buff, 1, 8000, fp);
233 				for (c = 0; c < len; c++)
234 					crc += *(buff + c);
235 			}
236 			fclose(fp);
237 		}
238 	}
239 
240 	/* no do the directory file */
241 
242 	path = fixpath (GAMEDIR, DIR_);
243 
244 	if ((fp = fopen(path, "rb")) != NULL) {
245 		for (len = 1; len > 0; ) {
246 			memset (buff, 0, 8192);
247 			len = fread (buff, 1, 8000, fp);
248 			for (c = 0; c < len; c++)
249 				crc += *(buff + c);
250 		}
251 		fclose (fp);
252 	}
253 
254 	free (buff);
255 
256 	report ("Computed CRC: 0x%05x\n", crc);
257 	ver = match_version (crc);
258 	game.crc = crc;
259 	game.ver = ver;
260 	agi_set_release (ver);
261 
262 	ec = setup_v3_game(ver, crc);
263 
264 
265 	return ec;
266 }
267 
268 
269 #ifdef PALMOS
270 
v4id_game(UINT32 crc)271 int v4id_game (UINT32 crc)
272 {
273 	int ec = err_OK, ver;
274 
275 	ver = match_version (crc);
276 	agi_set_release (ver);
277 
278 	switch ((ver>>12)&0xFF) {
279 	case 2:
280 		ec = setup_v2_game (ver, crc);
281 		break;
282 	case 3:
283 		ec = setup_v3_game (ver, crc);
284 		break;
285 	}
286 
287 	return ec;
288 }
289 
290 #endif
291 
292 /**
293  *
294  */
setup_v2_game(int ver,UINT32 crc)295 int setup_v2_game (int ver, UINT32 crc)
296 {
297 	int ec=err_OK;
298 
299 	if (ver == 0) {
300 		report ("Unknown v2 Sierra game: %08x\n\n", crc);
301 		agi_set_release (0x2917);
302 	}
303 
304 	/* setup the differences in the opcodes and other bits in the
305 	 * AGI v2 specs
306 	 */
307 	if (opt.emuversion)
308 		agi_set_release (opt.emuversion);
309 
310 	if (opt.agds)
311 		agi_set_release (0x2440);/* ALL AGDS games built for 2.440 */
312 
313 	switch(agi_get_release ()) {
314 	case 0x2089:
315 		logic_names_cmd[0x86].num_args = 0;	/* quit: 0 args */
316 	case 0x2272:
317 		logic_names_cmd[0x97].num_args = 3;	/* print.at: 3 args */
318 		logic_names_cmd[0x98].num_args = 3;	/* print.at.v: 3 args*/
319 		break;
320 	case 0x2440:
321 		break;
322 	case 0x2917:
323 		break;
324 	case 0x2936:
325 		break;
326 	default:
327 		report ("** Cannot setup for unknown version\n");
328 		ec = err_UnknownAGIVersion;
329 		break;
330 	}
331 
332 	return ec;
333 }
334 
335 /**
336  *
337  */
setup_v3_game(int ver,UINT32 crc)338 int setup_v3_game (int ver, UINT32 crc)
339 {
340 	int ec = err_OK;
341 
342 	if (ver == 0) {
343 		report ("Unknown v3 Sierra game: %08x\n\n", crc);
344 		agi_set_release (ver = 0x3149);
345 	}
346 
347 	if (opt.emuversion)
348 		agi_set_release (ver = opt.emuversion);
349 
350 	switch(ver) {
351 	case 0x3086:
352 		logic_names_cmd[0xad].num_args = 1;	/* 173 : 1 args */
353 		break;
354 	case 0x3149:
355 		logic_names_cmd[0xad].num_args = 0;	/* 173 : 0 args */
356 		break;
357 	default:
358 		report ("Error: cannot setup for unknown version\n");
359 		ec = err_UnknownAGIVersion;
360 		break;
361 	}
362 
363 	return ec;
364 }
365 
366 #endif
367