1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "stdafx.h"
24 #include "cpthelp.h"
25 #include "TextFile.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 uint32 crop(char *line);
31 uint16 findCptId(char *name, TextFile *cptFile);
32 
33 #define MAX_CPTS 0xA000
34 #define MAX_OBJ_SIZE (0x2000 * 2)
35 #define NUM_DATA_LISTS 9
36 #define ASCII_SIZE (65536 * 2)
37 
38 enum CptType {
39 	PTR_NULL = 0,
40 	COMPACT,
41 	TURNTAB,
42 	ANIMSEQ,
43 	MISCBIN,
44 	GETTOTAB,
45 	ROUTEBUF,
46 	MAINLIST
47 };
48 
processMainLists(FILE * inf,CptObj * destArr,uint16 * idList)49 void processMainLists(FILE *inf, CptObj *destArr, uint16 *idList) {
50 	char line[1024];
51 	dofgets(line, 1024, inf);
52 	assert(lineMatchSection(line, "MAINLISTS"));
53 	uint16 *resBuf = (uint16 *)malloc(MAX_OBJ_SIZE);
54 	uint32 idNum = 0;
55 	do {
56 		dofgets(line, 1024, inf);
57 		if (!isEndOfSection(line)) {
58 			char cptName[50];
59 			uint16 id = getInfo(line, "MAINLST", cptName);
60 			CptObj *dest = destArr + id;
61 			assertEmpty(dest);
62 			dest->type = MAINLIST;
63 			dest->dbgName = (char *)malloc(strlen(cptName) + 1);
64 			strcpy(dest->dbgName, cptName);
65 			memset(resBuf, 0, MAX_OBJ_SIZE);
66 			uint32 resPos = 0;
67 			idList[idNum] = id;
68 			idNum++;
69 
70 			do {
71 				dofgets(line, 1024, inf);
72 				if (!isEndOfObject(line, "MAINLST", id)) {
73 					assert((line[0] == '\t') && (line[1] == '\t'));
74 					char *stopCh;
75 					uint16 destId = (uint16)strtoul(line + 2, &stopCh, 16);
76 					assert(stopCh == (line + 6));
77 					assert((stopCh[0] == ':') && (stopCh[1] == ':'));
78 					resBuf[resPos] = destId;
79 					resPos++;
80 				} else
81 					break;
82 			} while (1);
83 			assert(resPos < (MAX_OBJ_SIZE / 2));
84 			dest->len = resPos;
85 			dest->data = (uint16 *)malloc(resPos * 2);
86 			memcpy(dest->data, resBuf, resPos * 2);
87 		} else
88 			break;
89 	} while (1);
90 
91 	free(resBuf);
92 }
93 
processCpts(FILE * inf,CptObj * destArr)94 void processCpts(FILE *inf, CptObj *destArr) {
95 	char line[1024];
96 	dofgets(line, 1024, inf);
97 	assert(lineMatchSection(line, "COMPACTS"));
98 	uint16 *resBuf = (uint16 *)malloc(MAX_OBJ_SIZE);
99 	do {
100 		dofgets(line, 1024, inf);
101 		if (!isEndOfSection(line)) {
102 			char cptName[50];
103 			uint16 id = getInfo(line, "COMPACT", cptName);
104 			CptObj *dest = destArr + id;
105 			assertEmpty(dest);
106 			dest->dbgName = (char *)malloc(strlen(cptName) + 1);
107 			dest->type = COMPACT;
108 			strcpy(dest->dbgName, cptName);
109 			memset(resBuf, 0, MAX_OBJ_SIZE);
110 			uint32 resPos = 0;
111 
112 			do {
113 				dofgets(line, 1024, inf);
114 				if (!isEndOfObject(line, "COMPACT", id)) {
115 					assert((line[0] == '\t') && (line[1] == '\t'));
116 					char *stopCh;
117 					uint16 destId = (uint16)strtoul(line + 2, &stopCh, 16);
118 					assert(stopCh != (line + 2));
119 					assert((stopCh[0] == '-') && (stopCh[1] == '>'));
120 					if (resPos == 23) { // grafixProg
121 						assert(destId == 0);
122 						resBuf[resPos] = resBuf[resPos + 1] = 0;
123 						resPos += 2;
124 					} else if (resPos == 48) {	// turnProg. shouldn't it be 49?
125 						assert(destId == 0);
126 						resBuf[resPos] = resBuf[resPos + 1] = 0;
127 						resPos += 2;
128 					} else {
129 						resBuf[resPos] = destId;
130 						resPos++;
131 					}
132 				} else
133 					break;
134 			} while (1);
135 			assert(resPos < (MAX_OBJ_SIZE / 2));
136 			dest->len = resPos;
137 			dest->data = (uint16 *)malloc(resPos * 2);
138 			memcpy(dest->data, resBuf, resPos * 2);
139 		} else
140 			break;
141 	} while (1);
142 
143 	free(resBuf);
144 }
145 
processTurntabs(FILE * inf,CptObj * destArr)146 void processTurntabs(FILE *inf, CptObj *destArr) {
147 	char line[1024];
148 	dofgets(line, 1024, inf);
149 	assert(lineMatchSection(line, "TURNTABS"));
150 	uint16 *resBuf = (uint16 *)malloc(MAX_OBJ_SIZE);
151 	do {
152 		dofgets(line, 1024, inf);
153 		if (!isEndOfSection(line)) {
154 			char cptName[50];
155 			uint16 id = getInfo(line, "TURNTAB", cptName);
156 			CptObj *dest = destArr + id;
157 			assertEmpty(dest);
158 			dest->dbgName = (char *)malloc(strlen(cptName) + 1);
159 			dest->type = TURNTAB;
160 			strcpy(dest->dbgName, cptName);
161 			memset(resBuf, 0, MAX_OBJ_SIZE);
162 			uint32 resPos = 0;
163 
164 			do {
165 				dofgets(line, 1024, inf);
166 				if (!isEndOfObject(line, "TURNTAB", id)) {
167 					assert((line[0] == '\t') && (line[1] == '\t'));
168 					char *stopCh;
169 					uint16 destId = (uint16)strtoul(line + 2, &stopCh, 16);
170 					assert(stopCh == (line + 6));
171 					assert((stopCh[0] == '-') && (stopCh[1] == '>'));
172 					resBuf[resPos] = destId;
173 					resPos++;
174 				} else
175 					break;
176 			} while (1);
177 			assert(resPos < (MAX_OBJ_SIZE / 2));
178 			dest->len = resPos;
179 			dest->data = (uint16 *)malloc(resPos * 2);
180 			memcpy(dest->data, resBuf, resPos * 2);
181 		} else
182 			break;
183 	} while (1);
184 
185 	free(resBuf);
186 }
187 
processBins(FILE * inf,CptObj * destArr,const char * typeName,const char * objName,uint8 cTypeId)188 void processBins(FILE *inf, CptObj *destArr, const char *typeName, const char *objName, uint8 cTypeId) {
189 	char line[1024];
190 	dofgets(line, 1024, inf);
191 	assert(lineMatchSection(line, typeName));
192 	uint16 *resBuf = (uint16 *)malloc(MAX_OBJ_SIZE);
193 	do {
194 		dofgets(line, 1024, inf);
195 		if (!isEndOfSection(line)) {
196 			char cptName[50];
197 			uint16 id = getInfo(line, objName, cptName);
198 			CptObj *dest = destArr + id;
199 			assertEmpty(dest);
200 			dest->dbgName = (char *)malloc(strlen(cptName) + 1);
201 			dest->type = cTypeId;
202 			strcpy(dest->dbgName, cptName);
203 			memset(resBuf, 0, MAX_OBJ_SIZE);
204 			uint32 resPos = 0;
205 
206 			do {
207 				dofgets(line, 1024, inf);
208 				if (!isEndOfObject(line, objName, id)) {
209 					assert((line[0] == '\t') && (line[1] == '\t'));
210 					char *stopCh;
211 					uint16 destId = (uint16)strtoul(line + 2, &stopCh, 16);
212 					assert(stopCh == (line + 6));
213 					assert(*stopCh == '\0');
214 					resBuf[resPos] = destId;
215 					resPos++;
216 				} else
217 					break;
218 			} while (1);
219 			assert(resPos < (MAX_OBJ_SIZE / 2));
220 			dest->len = resPos;
221 			dest->data = (uint16 *)malloc(resPos * 2);
222 			memcpy(dest->data, resBuf, resPos * 2);
223 		} else
224 			break;
225 	} while (1);
226 
227 	free(resBuf);
228 }
229 
230 uint16 dlinkCount = 0;
231 static uint16 dlinks[1024];
232 static char* dlinkNames[512];
233 
processSymlinks(FILE * inf,CptObj * destArr,uint16 * baseLists)234 void processSymlinks(FILE *inf, CptObj *destArr, uint16 *baseLists) {
235 	char line[1024];
236 	dofgets(line, 1024, inf);
237 	assert(lineMatchSection(line, "SYMLINKS"));
238 	do {
239 		dofgets(line, 1024, inf);
240 		if (!isEndOfSection(line)) {
241 			char cptName[50];
242 			uint16 fromId = getInfo(line, "SYMLINK", cptName);
243 			CptObj *from = destArr + fromId;
244 			assertEmpty(from);
245 			dlinkNames[dlinkCount] = (char *)malloc(strlen(cptName) + 1);
246 			strcpy(dlinkNames[dlinkCount], cptName);
247 
248 			dofgets(line, 1024, inf);
249 			assert((line[0] == '\t') && (line[1] == '\t') && (line[2] == '-') && (line[3] == '>'));
250 			char *stopCh;
251 			uint16 destId = (uint16)strtoul(line + 4, &stopCh, 16);
252 			assert(stopCh == (line + 8));
253 			assert((stopCh[0] == ':') && (stopCh[1] == ':'));
254 
255 			dlinks[dlinkCount * 2 + 0] = fromId;
256 			dlinks[dlinkCount * 2 + 1] = destId;
257 
258 			dlinkCount++;
259 
260 			dofgets(line, 1024, inf);
261 			assert(isEndOfObject(line, "SYMLINK", fromId));
262 		} else
263 			break;
264 	} while (1);
265 }
266 
doCompile(FILE * inf,FILE * debOutf,FILE * resOutf,TextFile * cptDef,FILE * sve)267 void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *sve) {
268 	uint16 maxStrl = 0;
269 	uint16 maxCptl = 0;
270 
271 	printf("Processing...\n");
272 	CptObj *resCpts;
273 	uint16 baseLists[NUM_DATA_LISTS];
274 	memset(baseLists, 0, NUM_DATA_LISTS * 2);
275 	resCpts = (CptObj *)malloc(MAX_CPTS * sizeof(CptObj));
276 	memset(resCpts, 0, MAX_CPTS * sizeof(CptObj));
277 	printf(" MainLists...\n");
278 	processMainLists(inf, resCpts, baseLists);
279 	printf(" Compacts...\n");
280 	processCpts(inf, resCpts);
281 	printf(" Turntables...\n");
282 	processTurntabs(inf, resCpts);
283 	printf(" Animation tables...\n");
284 	processBins(inf, resCpts, "ANIMSEQS", "ANIMSEQ", ANIMSEQ);
285 	printf(" Unknown binaries...\n");
286 	processBins(inf, resCpts, "MISCBINS", "MISCBIN", MISCBIN);
287 	printf(" Get To tables...\n");
288 	processBins(inf, resCpts, "GETTOTAB", "GET_TOS", GETTOTAB);
289 	printf(" Scratch buffers...\n");
290 	processBins(inf, resCpts, "SCRATCHR", "SCRATCH", ROUTEBUF);
291 	printf(" Symbolic links...\n");
292 	processSymlinks(inf, resCpts, baseLists);
293 	printf("Converting to binary data...\n");
294 	uint32 numCpts = 1;
295 	for (uint32 cnt = 1; cnt < MAX_CPTS; cnt++)
296 		if (resCpts[cnt].data || resCpts[cnt].dbgName || resCpts[cnt].len)
297 			numCpts++;
298 
299 	uint16 dataListLen[NUM_DATA_LISTS];
300 	for (uint32 cnt = 0; cnt < NUM_DATA_LISTS; cnt++)
301 		for (uint16 elemCnt = 0; elemCnt < 0x1000; elemCnt++) {
302 			uint32 id = (cnt << 12) | elemCnt;
303 			if (resCpts[id].data || resCpts[id].dbgName || resCpts[id].len)
304 				dataListLen[cnt] = elemCnt + 1;
305 		}
306 
307 	// write the header
308 	uint32 rev = 0;
309 	fwrite(&rev, 2, 1, debOutf);
310 	fwrite(&rev, 2, 1, resOutf);
311 	rev = NUM_DATA_LISTS;
312 	fwrite(&rev, 2, 1, debOutf);
313 	fwrite(&rev, 2, 1, resOutf);
314 	for (uint32 cnt = 0; cnt < NUM_DATA_LISTS; cnt++) {
315 		fwrite(dataListLen + cnt, 2, 1, debOutf);
316 		fwrite(dataListLen + cnt, 2, 1, resOutf);
317 	}
318 
319 	uint32 binSize = 0;
320 	uint32 binDest = ftell(debOutf);
321 	fwrite(&binSize, 1, 4, debOutf);
322 	fwrite(&binSize, 1, 4, resOutf);
323 	fwrite(&binSize, 1, 4, debOutf);
324 	fwrite(&binSize, 1, 4, resOutf);
325 
326 	char *asciiBuf = (char *)malloc(ASCII_SIZE);
327 	char *asciiPos = asciiBuf;
328 
329 	// now process all the compacts
330 	uint32 cptSize[2];
331 	cptSize[0] = ftell(debOutf);
332 	cptSize[1] = ftell(resOutf);
333 	for (uint32 lcnt = 0; lcnt < NUM_DATA_LISTS; lcnt++) {
334 		for (uint32 eCnt = 0; eCnt < dataListLen[lcnt]; eCnt++) {
335 			uint32 cId = (lcnt << 12) | eCnt;
336 			CptObj *cpt = resCpts + cId;
337 			if (resCpts[cId].data || resCpts[cId].dbgName || resCpts[cId].len || resCpts[cId].type) {
338 				strcpy(asciiPos, cpt->dbgName);
339 				asciiPos += strlen(cpt->dbgName) + 1;
340 
341 				assert(cpt->len < 0xFFFF);
342 				uint16 dlen = (uint16)cpt->len;
343 				if (dlen > maxCptl)
344 					maxCptl = dlen;
345 				binSize += dlen;
346 				assert(dlen != 0);
347 
348 				fwrite(&dlen, 2, 1, debOutf);
349 				fwrite(&dlen, 2, 1, resOutf);
350 
351 				uint16 field = resCpts[cId].type;
352 				fwrite(&field, 2, 1, debOutf);
353 
354 				fwrite(cpt->data, 2, dlen, debOutf);
355 				fwrite(cpt->data, 2, dlen, resOutf);
356 			} else {
357 				uint16 tmp = 0;
358 				fwrite(&tmp, 2, 1, debOutf);
359 				fwrite(&tmp, 2, 1, resOutf);
360 			}
361 		}
362 		printf("DEBUG lcnt: %lu Output File Position: 0x%08lX\r\n", lcnt, ftell(debOutf));
363 	}
364 	cptSize[0] = ftell(debOutf) - cptSize[0];
365 	cptSize[1] = ftell(resOutf) - cptSize[1];
366 	assert(!(cptSize[0] & 1));
367 	assert(!(cptSize[1] & 1));
368 	cptSize[0] /= 2;
369 	cptSize[1] /= 2;
370 
371 	for (uint32 cnt = 0; cnt < dlinkCount; cnt++) {
372 		strcpy(asciiPos, dlinkNames[cnt]);
373 		asciiPos += strlen(dlinkNames[cnt]) + 1;
374 	}
375 
376 	uint32 asciiSize = (uint32)(asciiPos - asciiBuf);
377 	fwrite(&asciiSize, 1, 4, debOutf);
378 	fwrite(asciiBuf, 1, asciiSize, debOutf);
379 	free(asciiBuf);
380 
381 	// the direct links...
382 	fwrite(&dlinkCount, 2, 1, debOutf);
383 	fwrite(&dlinkCount, 2, 1, resOutf);
384 	for (uint32 cnt = 0; cnt < dlinkCount; cnt++) {
385 		fwrite(dlinks + cnt * 2 + 0, 2, 1, debOutf);
386 		fwrite(dlinks + cnt * 2 + 0, 2, 1, resOutf);
387 
388 		fwrite(dlinks + cnt * 2 + 1, 2, 1, debOutf);
389 		fwrite(dlinks + cnt * 2 + 1, 2, 1, resOutf);
390 	}
391 	printf("Processing diff data...\n");
392 	printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
393 	// 288 diffdata
394 	FILE *dif = fopen("288diff.txt", "r");
395 	assert(dif);
396 	char line[1024];
397 	uint16 diff[8192];
398 	uint16 diffDest = 0;
399 	uint16 diffNo = 0;
400 	while (fgets(line, 1024, dif)) {
401 		crop(line);
402 		if (line[0] != '$') {
403 			assert(memcmp(line, "data_", 5) == 0);
404 			char *pos = line + 5;
405 			char *stopCh;
406 			uint16 lId = (uint16)strtoul(pos, &stopCh, 10);
407 			assert(*stopCh == '[');
408 			uint16 eId = (uint16)strtoul(stopCh + 1, &stopCh, 10);
409 			assert((stopCh[0] == ']') && (stopCh[1] == '[') && (eId <= 0xFFF) && (lId <= 7));
410 			uint16 id = (lId << 12) | eId;
411 			uint16 elemNo = (uint16)strtoul(stopCh + 2, &stopCh, 10);
412 			assert(*stopCh == ']');
413 			stopCh = strstr(stopCh, "0x") + 2;
414 			uint16 val = (uint16)strtoul(stopCh, &stopCh, 16);
415 			assert(*stopCh == ';');
416 			diff[diffDest++] = id;
417 			diff[diffDest++] = elemNo;
418 			diff[diffDest++] = 1;
419 			diff[diffDest++] = val;
420 			diffNo++;
421 		} else {
422 			char *pos = strchr(line, ' ');
423 			*pos = '\0';
424 			uint16 id = findCptId(line + 1, cptDef);
425 			assert(id);
426 			diff[diffDest++] = id;
427 			diff[diffDest++] = 0;
428 			pos++;
429 			uint16 len = (uint16)strtoul(pos, &pos, 10);
430 			diff[diffDest++] = len;
431 			assert(len);
432 			assert(resCpts[id].len == len);
433 			for (uint16 cnt = 0; cnt < len; cnt++) {
434 				assert(*pos == ' ');
435 				pos++;
436 				diff[diffDest++] = (uint16)strtoul(pos, &pos, 16);
437 			}
438 			assert(diff[diffDest - 1] == 0xFFFF);
439 			diffNo++;
440 		}
441 	}
442 	fclose(dif);
443 	free(resCpts);
444 	assert(diffDest <= 8192);
445 	fwrite(&diffNo, 1, 2, debOutf);
446 	fwrite(&diffDest, 1, 2, debOutf);
447 	fwrite(diff, 2, diffDest, debOutf);
448 	fwrite(&diffNo, 1, 2, resOutf);
449 	fwrite(&diffDest, 1, 2, resOutf);
450 	fwrite(diff, 2, diffDest, resOutf);
451 
452 	printf("Converting Save data...\n");
453 	printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
454 	// the IDs of the compacts to be saved
455 	char cptName[1024];
456 	uint16 saveIds[2048];
457 	uint16 numIds = 0;
458 	while (fgets(cptName, 1024, sve)) {
459 		crop(cptName);
460 		uint16 resId = findCptId(cptName, cptDef);
461 		if (!resId)
462 			printf("ERROR: Can't find definition of %s\n", cptName);
463 		else {
464 			saveIds[numIds] = resId;
465 			numIds++;
466 		}
467 	}
468 	printf("%d saveIds\n", numIds);
469 	fwrite(&numIds, 2, 1, debOutf);
470 	fwrite(saveIds, 2, numIds, debOutf);
471 	fwrite(&numIds, 2, 1, resOutf);
472 	fwrite(saveIds, 2, numIds, resOutf);
473 
474 	printf("Converting Reset data...\n");
475 	// now append the reset data
476 	uint16 gameVers[7] = { 303, 331, 348, 365, 368, 372, 288 };
477 	// make sure all files exist
478 	bool filesExist = true;
479 	char inName[32];
480 	for (int i = 0; i < 7; i++) {
481 		sprintf(inName, "RESET.%03d", gameVers[i]);
482 		FILE *test = fopen(inName, "rb");
483 		if (test)
484 			fclose(test);
485 		else {
486 			filesExist = false;
487 			printf("File %s not found\n", inName);
488 		}
489 	}
490 
491 	if (filesExist) {
492 		FILE *res288 = fopen("RESET.288", "rb");
493 		fseek(res288, 0, SEEK_END);
494 		assert((ftell(res288) / 2) < 65536);
495 		uint16 resSize = (uint16)(ftell(res288) / 2);
496 		fseek(res288, 0, SEEK_SET);
497 		uint16 *buf288 = (uint16 *)malloc(resSize * 2);
498 		fread(buf288, 2, resSize, res288);
499 		fclose(res288);
500 		fwrite(&resSize, 1, 2, debOutf);
501 		fwrite(buf288, 2, resSize, debOutf);
502 
503 		uint16 tmp = 7;
504 		fwrite(&tmp, 2, 1, debOutf);
505 		tmp = 288;
506 		fwrite(&tmp, 2, 1, debOutf);
507 		tmp = 0;
508 		fwrite(&tmp, 2, 1, debOutf);
509 
510 		printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
511 		printf("reset destination: %ld\n", ftell(debOutf));
512 		for (int cnt = 0; cnt < 6; cnt++) {
513 			printf("Processing diff v0.0%03d\n", gameVers[cnt]);
514 			uint16 diffPos = 0;
515 			sprintf(inName, "RESET.%03d", gameVers[cnt]);
516 			FILE *resDiff = fopen(inName, "rb");
517 			fseek(resDiff, 0, SEEK_END);
518 			assert(ftell(resDiff) == (resSize * 2));
519 			fseek(resDiff, 0, SEEK_SET);
520 			uint16 *bufDif = (uint16 *)malloc(resSize *2);
521 			fread(bufDif, 2, resSize, resDiff);
522 			fclose(resDiff);
523 			for (uint16 eCnt = 0; eCnt < resSize; eCnt++)
524 				if (buf288[eCnt] != bufDif[eCnt]) {
525 					diff[diffPos++] = eCnt;
526 					diff[diffPos++] = bufDif[eCnt];
527 				}
528 			free(bufDif);
529 			fwrite(gameVers + cnt, 1, 2, debOutf);
530 			assert(!(diffPos & 1));
531 			diffPos /= 2;
532 			fwrite(&diffPos, 1, 2, debOutf);
533 			fwrite(diff, 2, 2 * diffPos, debOutf);
534 			printf("diff v0.0%03d: 2 * 2 * %d\n", gameVers[cnt], diffPos);
535 			printf("DEBUG Output File Position: 0x%08lX\r\n", ftell(debOutf));
536 		}
537 		free(buf288);
538 	} else {
539 		printf("Creating CPT file with Dummy reset data @ %ld\n", ftell(debOutf));
540 		uint16 resetFields16 = 4;
541 		fwrite(&resetFields16, 2, 1, debOutf);
542 		uint32 blah = 8;
543 		fwrite(&blah, 4, 1, debOutf); // size field: 8 bytes
544 		blah = (uint32)-1;
545 		fwrite(&blah, 4, 1, debOutf); // save file revision. -1 is unknown to scummvm, so it'll refuse to load it.
546 		resetFields16 = 0;
547 		fwrite(&resetFields16, 2, 1, debOutf); // numDiffs: 0, no further reset blocks.
548 	}
549 
550 	// now fill the raw-compact-data-size header field
551 	fseek(resOutf, binDest, SEEK_SET);
552 	fseek(debOutf, binDest, SEEK_SET);
553 	fwrite(&binSize, 1, 4, debOutf);
554 	fwrite(&binSize, 1, 4, resOutf);
555 	fwrite(cptSize + 0, 1, 4, debOutf);
556 	fwrite(cptSize + 1, 1, 4, resOutf);
557 
558 	printf("%d diffs\n", diffNo);
559 	printf("%ld Compacts in total\n", numCpts);
560 	printf("max strlen = %d\n", maxStrl);
561 	printf("raw size = 2 * %ld\n", binSize);
562 	printf("max cptlen = %d\n", maxCptl);
563 }
564