[Scummvm-cvs-logs] SF.net SVN: scummvm:[34153] scummvm/trunk/tools

buddha_ at users.sourceforge.net buddha_ at users.sourceforge.net
Mon Aug 25 17:04:52 CEST 2008


Revision: 34153
          http://scummvm.svn.sourceforge.net/scummvm/?rev=34153&view=rev
Author:   buddha_
Date:     2008-08-25 15:04:48 +0000 (Mon, 25 Aug 2008)

Log Message:
-----------
Added Cinematique archive file unpacker and script disassembler to tools. NOT polished code so caveat emptor.

Added Paths:
-----------
    scummvm/trunk/tools/cine_tools/
    scummvm/trunk/tools/cine_tools/Makefile
    scummvm/trunk/tools/cine_tools/cine_decode.cpp
    scummvm/trunk/tools/cine_tools/cine_unpack.cpp
    scummvm/trunk/tools/cine_tools/cine_unpack.h
    scummvm/trunk/tools/cine_tools/endian.h
    scummvm/trunk/tools/cine_tools/typedefs.h

Added: scummvm/trunk/tools/cine_tools/Makefile
===================================================================
--- scummvm/trunk/tools/cine_tools/Makefile	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/Makefile	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,6 @@
+# $URL$
+# $Id$
+
+all:
+	g++ cine_decode.cpp -o cine_decode
+	g++ cine_unpack.cpp -o cine_unpack


Property changes on: scummvm/trunk/tools/cine_tools/Makefile
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/tools/cine_tools/cine_decode.cpp
===================================================================
--- scummvm/trunk/tools/cine_tools/cine_decode.cpp	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/cine_decode.cpp	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,864 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ * This is a utility to decode Delphine's Cinematique engine's script files.
+ * The script files can be recognized from their extension .prc or .rel.
+ * Should at least work with Future Wars and Operation Stealth.
+ *
+ * Note that this isn't polished code so caveat emptor.
+ *
+ * TODO: Unify opcode namings between ScummVM's Cine engine and this utility.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "typedefs.h"
+#include "endian.h"
+
+static const uint8 *_baseScriptData, *_scriptData;
+
+static uint8 fetchScriptByte() {
+	return *_scriptData++;
+}
+
+static uint16 fetchScriptWord() {
+	uint16 w = READ_BE_UINT16(_scriptData);
+	_scriptData += 2;
+	return w;
+}
+
+static const char *fetchScriptString() {
+	const char *str = (const char *)_scriptData;
+	_scriptData += strlen(str) + 1;
+	return str;
+}
+
+//typedef void (*DecodeOpcode)();
+
+static const char *objectField[] = {
+	"<null>",
+	"x",
+	"y",
+	"mask",
+	"frame",
+	"costume",
+	"part"
+};
+
+static bool decodeOpcode(int isV2) {
+	uint8 opcode;
+	unsigned int addr = _scriptData - _baseScriptData;
+	
+	opcode = fetchScriptByte();
+	if (opcode == 0) {
+		printf("[%04X] (FF) ", addr);
+	} else {
+		--opcode;
+		printf("[%04X] (%02X) ", addr, opcode);
+		switch (opcode) {
+		case 0x00: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				int16 value = fetchScriptWord();
+				if (field >= 7) return false;
+				printf("SET object[%d].%s, %d", num, objectField[field], value);
+			}
+			break;
+		case 0x01: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				uint8 var = fetchScriptByte();
+				if (field >= 7) return false;
+				printf("LOAD localvars[%d], object[%d].%s", var, num, objectField[field]);
+			}		
+			break;
+		case 0x02: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				int16 value = fetchScriptWord();
+				if (field >= 7) return false;
+				printf("ADD object[%d].%s, %d", num, objectField[field], value);
+			}
+			break;
+		case 0x03: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				int16 value = fetchScriptWord();
+				if (field >= 7) return false;
+				printf("SUB object[%d].%s, %d", num, objectField[field], value);
+			}
+			break;
+		case 0x06: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				int16 value = fetchScriptWord();
+				if (field >= 7) return false;
+				printf("CMP object[%d].%s, %d", num, objectField[field], value);
+			}
+			break;
+		case 0x07: {
+				uint8 num = fetchScriptByte();
+				int16 x = fetchScriptWord();
+				int16 y = fetchScriptWord();
+				int16 mask = fetchScriptWord();
+				int16 frame = fetchScriptWord();
+				printf("SETUP object[%d] x=%d y=%d mask=%d frame=%d", num, x, y, mask, frame);
+			}
+			break;
+		case 0x08: {
+				uint8 num = fetchScriptByte();
+				int16 x = fetchScriptWord();
+				int16 y = fetchScriptWord();
+				int16 count = fetchScriptWord();
+				int16 index = fetchScriptWord();
+				printf("CHECK_COLLISION objects[%d] x=%d y=%d count=%d index=%d", num, x, y, count, index);
+			}
+			break;
+		case 0x09: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("SET localvars[%d], %d", var, value);
+				} else {
+					uint8 num = fetchScriptByte();
+				 	switch (type) {
+					case 1:
+						printf("localvars[%d] = localvars[%d]", var, num);
+						break;
+					case 2:
+						printf("localvars[%d] = globalvars[%d]", var, num);
+						break;
+					case 3:
+						printf("localvars[%d] = mouse.x", var);
+						break;
+					case 4:
+						printf("localvars[%d] = mouse.y", var);
+						break;
+					case 5:
+						printf("localvars[%d] = random(%d)", var, num);
+						break;
+					case 8:
+						printf("localvars[%d] = datas[%d].packed_size", var, num);
+						break;
+					case 9:
+						printf("localvars[%d] = datas[%d].unpacked_size", var, num);
+						break;
+					default:
+						return false;
+						break;
+					}
+				}
+			}
+			break;
+		case 0x0A: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("ADD localvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					printf("ADD localvars[%d], localvars[%d]", var, var2);
+				}
+			}
+			break;
+		case 0x0B: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("SUB localvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					printf("SUB localvars[%d], localvars[%d]", var, var2);
+				}
+			}
+			break;
+		case 0x0C: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("MUL localvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					printf("MUL localvars[%d], localvars[%d]", var, var2);
+				}
+			}
+			break;
+		case 0x0D: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("DIV localvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					printf("DIV localvars[%d], localvars[%d]", var, var2);
+				}
+			}
+			break;
+		case 0x0E: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("CMP localvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					if (type == 1) {
+						printf("CMP localvars[%d], localvars[%d]", var, var2);
+					} else if (type == 2) {
+						printf("CMP localvars[%d], globalvars[%d]", var, var2);
+					} else {
+						return false;
+					}
+				}
+			}
+			break;
+		case 0x0F: {
+				uint8 num = fetchScriptByte();
+				uint8 field = fetchScriptByte();
+				int16 var = fetchScriptByte();				
+				if (field >= 7) return false;
+				printf("SET object[%d].%s, localvars[%d]", num, objectField[field], var);
+			}
+			break;
+		case 0x13: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OVERLAY object=%d, type=0", num);
+			}
+			break;
+		case 0x14: {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_OVERLAY object=%d, type=0", num);
+			}
+			break;
+		case 0x15: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OBJECT_TO_BACKGROUND_LIST objects[%d]", num);
+			}
+			break;
+		case 0x16: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OVERLAY object=%d, type=1", num);
+			}
+			break;
+		case 0x17: {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_OVERLAY object=%d, type=1", num);
+			}
+			break;
+		case 0x18: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OVERLAY object=%d, type=4", num);
+			}
+			break;
+		case 0x19: {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_OVERLAY object=%d, type=4", num);
+			}
+			break;
+		case 0x1A: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_SPRITE_TO_BACKGROUND_LIST objects[%d], type=4", num);
+			}
+			break;
+		case 0x1B: {
+				printf("CLEAR_BACKGROUND_LIST");
+			}
+			break;
+		case 0x1D: {
+				uint8 num = fetchScriptByte();
+				printf("LABEL_%d:", num);
+			}
+			break;
+		case 0x1E: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP LABEL_%d", num);
+			}
+			break;
+		case 0x1F: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP G LABEL_%d", num);
+			}
+			break;
+		case 0x20: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP GEQ LABEL_%d", num);
+			}
+			break;
+		case 0x21: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP L LABEL_%d", num);
+			}
+			break;
+		case 0x22: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP LEQ LABEL_%d", num);
+			}
+			break;
+		case 0x23: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP EQ LABEL_%d", num);
+			}
+			break;
+		case 0x24: {
+				uint8 num = fetchScriptByte();
+				printf("JUMP NOT_EQ LABEL_%d", num);
+			}
+			break;
+		case 0x26: {
+				uint8 var = fetchScriptByte();
+				uint8 num = fetchScriptByte();
+				printf("--localvars[%d]; JUMP GEQ LABEL_%d", var, num);
+			}
+			break;
+		case 0x31: {
+				uint8 num = fetchScriptByte();
+				printf("START_GLOBAL_SCRIPT num=%d", num);
+			}
+			break;
+		case 0x32: {
+				uint8 num = fetchScriptByte();
+				printf("END_GLOBAL_SCRIPT num=%d", num);
+			}
+			break;
+		case 0x3B: {
+				const char *name = fetchScriptString();
+				printf("LOAD_ANIM name='%s'", name);
+			}
+			break;
+		case 0x3C: {
+				const char *name = fetchScriptString();
+				printf("LOAD_BACKGROUND_IMAGE name='%s'", name);
+			}
+			break;
+		case 0x3D: {
+				const char *name = fetchScriptString();
+				printf("LOAD_CT name='%s'", name);
+			}
+			break;
+		case 0x3F: {
+				const char *name = fetchScriptString();
+				printf("OPEN_RESOURCE_FILE name='%s'", name);
+			}
+			break;
+		case 0x40: {
+				printf("CLOSE_RESOURCE_FILE");
+			}
+			break;
+		case 0x41: {
+				static const char *dataType[] = { "prc", "rel", "obj", "msg" };
+				uint8 type = fetchScriptByte();
+				const char *name = fetchScriptString();
+				if (type >= 4) return false;
+				printf("SET_LOADING_DATA type='%s', name='%s'", dataType[type], name);
+			}
+			break;
+		case 0x42: {
+				printf("LOAD_PENDING_DATA");
+			}
+			break;
+		case 0x45: {
+				printf("FADE_IN");
+			}
+			break;
+		case 0x46: {
+				printf("FADE_OUT");
+			}
+			break;
+		case 0x47: {
+				uint8 start = fetchScriptByte();
+				uint8 count = fetchScriptByte();
+				int16 r = fetchScriptWord();
+				int16 g = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				printf("TRANSFORM_PALETTE start=%d, count=%d, delta_red=%d, delta_green=%d, delta_blue=%d", start, count, r, g, b);
+			}
+			break;
+		case 0x49: {
+				uint8 color = fetchScriptByte();
+				printf("SET_MENU_COLOR_1 %d", color);
+			}
+			break;
+		case 0x4A: {
+				uint8 firstColor = fetchScriptByte();
+				uint8 endColor = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				printf("ROTATE_PALETTE first_color=%d, end_color=%d, type=%d", firstColor, endColor, type);
+			}
+			break;			
+		case 0x4F: {
+				printf("BREAK");
+			}
+			break;
+		case 0x50: {
+				printf("END");
+				_baseScriptData = 0;
+			}
+			break;
+		case 0x51: {
+				uint8 num = fetchScriptByte();
+				int16 x = fetchScriptWord();
+				int16 y = fetchScriptWord();
+				int16 width = fetchScriptWord();
+				int16 color = fetchScriptWord();
+				printf("ADD_MESSAGE num=%d x=%d y=%d width=%d color=%d", num, x, y, width, color);
+			}
+			break;		
+		case 0x52: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("SET globalvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					if (type == 1) {
+						printf("SET globalvars[%d], localvars[%d]", var, var2);
+					} else {
+						printf("SET globalvars[%d], globalvars[%d]", var, var2);
+					}
+				}
+				break;
+			}
+		case 0x53: {
+				uint8 var = fetchScriptByte();
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("CMP globalvars[%d], %d", var, value);
+				} else {
+					uint8 var2 = fetchScriptByte();
+					printf("CMP globalvars[%d], localvars[%d]", var, var2);
+				}
+			}
+			break;
+		case 0x59: {
+				const char *str = fetchScriptString();
+				printf("/* %s */", str);
+			}
+			break;
+		case 0x5A: {
+				uint8 start = fetchScriptByte();
+				uint8 count = fetchScriptByte();
+				printf("FREE_FRAMES start=%d, count=%d", start, count);
+			}
+			break;
+		case 0x5B: {
+				printf("UNLOAD_OVERLAYS");
+			}
+			break;
+		case 0x65: {
+				printf("CLEAR_ZONE_DATA");
+			}
+			break;
+		case 0x66: {
+				uint8 num = fetchScriptByte();
+				int16 value = fetchScriptWord();
+				printf("SET zones[%d], %d", num, value);
+			}
+			break;			
+		case 0x68: {
+				uint8 color = fetchScriptByte();
+				printf("SET_MENU_COLOR_2 %d", color);
+			}
+			break;		
+		case 0x69: {
+				printf("ENABLE_PLAYER_INPUT");
+			}
+			break;
+		case 0x6A: {
+				printf("DISABLE_PLAYER_INPUT");
+			}
+			break;
+		case 0x6B: {
+				uint8 num = fetchScriptByte();
+				printf("SET_CURRENT_DISK num=%d", num);
+			}
+			break;
+		case 0x6D: {
+				const char *name = fetchScriptString();
+				printf("LOAD_MUSIC name='%s'", name);
+			}
+			break;
+		case 0x6E: {
+				printf("PLAY_MUSIC");
+			}
+			break;
+		case 0x6F: {
+				printf("FADE_OUT_MUSIC");
+			}
+			break;
+		case 0x70: {
+				printf("STOP_MUSIC");
+			}
+			break;
+		case 0x77: 
+		case 0x78: {
+				uint8 frame = fetchScriptByte();
+				uint8 channel = fetchScriptByte();
+				int16 freq = fetchScriptWord();
+				uint8 repeat = fetchScriptByte();
+				int16 volume = fetchScriptWord();
+				int16 size = fetchScriptWord();
+				printf("PLAY_SOUND frame=%d channel=%d freq=%d repeat=%d volume=%d size=%d", frame, channel, freq, repeat, volume, size);
+			}
+			break;
+		case 0x79: {
+				uint8 param = fetchScriptByte();
+				printf("DISABLE_SYSTEM_MENU flag=%d", param);
+			}
+			break;
+		case 0x7A: {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OVERLAY object=%d, type=5", num);
+			}
+			break;
+		case 0x7B: {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_OVERLAY object=%d, type=5", num);
+			}
+			break;
+		case 0x7F:
+			assert(isV2); {
+				uint8 a = fetchScriptByte();
+				uint8 b = fetchScriptByte();
+				uint8 c = fetchScriptByte();
+				uint8 d = fetchScriptByte();
+				int16 e = fetchScriptWord();
+				int16 f = fetchScriptWord();
+				int16 g = fetchScriptWord();
+				printf("ADD_ANIM_SEQUENCE %d %d %d %d %d %d %d", a, b, c, d, e, f, g);
+			}			
+			break;
+		case 0x80:
+			assert(isV2); {
+				uint8 a = fetchScriptByte();
+				uint8 b = fetchScriptByte();
+				printf("REMOVE_ANIM_SEQUENCE %d %d", a, b);
+			}
+			break;
+		case 0x82:
+			assert(isV2); {
+				uint8 a = fetchScriptByte();
+				uint8 b = fetchScriptByte();
+				int16 c = fetchScriptWord();
+				int16 d = fetchScriptWord();
+				uint8 e = fetchScriptByte();
+				printf("OP_0x82 %d %d %d %d %d", a, b, c, d, e);
+			}
+			break;			
+		case 0x83:
+			assert(isV2); {
+				uint8 a = fetchScriptByte();
+				uint8 b = fetchScriptByte();
+				printf("IS_ANIM_SEQUENCE_PLAYING %d %d", a, b);				
+			}
+			break;
+		case 0x84:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("JUMP G LABEL_%d", num);
+			}
+			break;
+		case 0x85:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("JUMP GEQ LABEL_%d", num);	
+			}
+			break;	
+		case 0x86:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("JUMP L LABEL_%d", num);
+			}
+			break;		
+		case 0x88:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("JUMP EQ LABEL_%d", num);
+			}
+			break;
+		case 0x89:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("JUMP NOT_EQ LABEL_%d", num);
+			}
+			break;
+		case 0x8B:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("START_OBJECT_SCRIPT num=%d", num);
+			}
+			break;
+		case 0x8C:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("STOP_OBJECT_SCRIPT num=%d", num);
+			}
+			break;
+		case 0x8D:
+			assert(isV2); {
+				int16 a = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				int16 c = fetchScriptWord();
+				int16 d = fetchScriptWord();
+				int16 e = fetchScriptWord();
+				int16 f = fetchScriptWord();
+				int16 g = fetchScriptWord();
+				int16 h = fetchScriptWord();
+				printf("IS_OBJECT_INTERSECTING_OBJECT %d %d %d %d %d %d %d %d", a, b, c, d, e, f, g, h);
+			}
+			break;
+		case 0x8E:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				const char *name = fetchScriptString();
+				printf("ADD_BACKGROUND name='%s' num=%d", name, num);
+			}
+			break;
+		case 0x8F:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_BACKGROUND num=%d", num);
+			}
+			break;
+		case 0x90:
+			assert(isV2); {
+				uint8 pos = fetchScriptByte();
+				const char *name = fetchScriptString();
+				printf("LOAD_DATA_ABSOLUTE name='%s' pos=%d", name, pos);
+			}
+			break;
+		case 0x91:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("SET_CURRENT_BACKGROUND num=%d", num);
+			}
+			break;
+		case 0x9A:
+			assert(isV2); {				
+				uint8 a = fetchScriptByte();
+				printf("OP_0x9A %d", a);
+			}
+			break;
+		case 0x9D:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("SET_NEXT_BACKGROUND %d", num);
+			}
+			break;
+		case 0x9E:
+			assert(isV2); {
+				uint8 type = fetchScriptByte();
+				if (type == 0) {
+					int16 value = fetchScriptWord();
+					printf("SET_SCROLLING_BACKGROUND %d", value);
+				} else {
+					uint8 var = fetchScriptByte();
+					printf("SET_SCROLLING_BACKGROUND localvars[%d]", var);
+				}
+			}
+			break;
+		case 0xA0:
+			assert(isV2); {
+				int16 a = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				printf("OP_0xA0 %d %d", a, b);
+			}
+			break;
+		case 0xA1:
+			assert(isV2); {
+				int16 a = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				printf("OP_0xA1 %d %d", a, b);
+			}
+			break;
+		case 0xA2:
+			assert(isV2); {
+				int16 a = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				printf("OP_0xA2 %d %d", a, b);
+			}
+			break;
+		case 0xA3:
+			assert(isV2); {
+				int16 a = fetchScriptWord();
+				int16 b = fetchScriptWord();
+				printf("OP_0xA3 %d %d", a, b);
+			}
+			break;
+		case 0xA4:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("ADD_OVERLAY object=%d, type=22", num);
+			}
+			break;
+		case 0xA5:
+			assert(isV2); {
+				uint8 num = fetchScriptByte();
+				printf("REMOVE_OVERLAY object=%d, type=22", num);
+			}
+			break;
+		default:
+			printf("Unhandled script opcode 0x%X", opcode);
+			return false;
+		}
+	}
+	printf("\n");
+	return true;
+}
+
+typedef void (*DecodeFile)(int isV2, const uint8 *data, int dataSize);
+
+/* .prc procedure */
+static void decodePrc(int isV2, const uint8 *data, int dataSize) {
+	int i, num;
+	struct {
+		uint16 size;
+	} hdr[256];
+
+	num = READ_BE_UINT16(data); data += 2;
+	if (num >= 256) {
+		printf("// Number of scripts (%d) in PRC-file is too large (i.e. >= 256)\n\n", num);
+		return;
+	}
+
+	for (i = 0; i < num; ++i) {
+		hdr[i].size = READ_BE_UINT16(data); data += 2;
+	}
+	for (i = 0; i < num; ++i) {
+		if (hdr[i].size != 0) {
+			printf("\n");
+			printf("// script.prc %d size 0x%X\n", i, hdr[i].size);
+			_baseScriptData = _scriptData = data; data += hdr[i].size;
+			bool status = true;
+			while (_baseScriptData && _scriptData < data && status) {
+				status = decodeOpcode(isV2);
+			}
+			if (!status) {
+				printf("// Error handling opcode\n\n");
+				return;
+			}
+			printf("\n");
+		}
+	}
+}
+
+/* .rel relation */
+static void decodeRel(int isV2, const uint8 *data, int dataSize) {
+	int i, num;
+	struct {
+		uint16 size;
+		uint16 param1;
+		uint16 index;
+		uint16 param2;
+	} hdr[256];
+
+	num = READ_BE_UINT16(data); data += 2;
+	if (num >= 256) {
+		printf("// Number of scripts (%d) in REL-file is too large (i.e. >= 256)\n\n", num);
+		return;
+	}	
+	for (i = 0; i < num; ++i) {
+		hdr[i].size = READ_BE_UINT16(data); data += 2;
+		hdr[i].param1 = READ_BE_UINT16(data); data += 2;
+		hdr[i].index = READ_BE_UINT16(data); data += 2;
+		hdr[i].param2 = READ_BE_UINT16(data); data += 2;
+	}
+	for (i = 0; i < num; ++i) {
+		if (hdr[i].size != 0) {
+			printf("\n");
+			printf("// script.rel %d size 0x%X param1 %d index %d param2 %d\n", i, hdr[i].size, hdr[i].param1, hdr[i].index, hdr[i].param2);
+			_baseScriptData = _scriptData = data; data += hdr[i].size;
+			bool status = true;
+			while (_baseScriptData && _scriptData < data && status) {
+				status = decodeOpcode(isV2);
+			}
+			if (!status) {
+				printf("// Error handling opcode\n\n");
+				return;
+			}
+			printf("\n");
+		}
+	}
+}
+
+int showUsage() {
+	printf("USAGE: cine_decode [type] [version] [filename]\n" \
+		"type: -prc or -rel (Use -prc for *.prc-files, -rel for *.rel-files)\n" \
+		"version: -v1 or -v2 (Use -v1 for Future Wars, -v2 for Operation Stealth)\n" \
+		"filename: The name of the script file to decode\n");
+	return -1;
+}
+
+int main(int argc, char *argv[]) {
+	if (argc == 4) {
+		FILE *fp;
+		uint8 *data;
+		int dataSize, isV2;
+		DecodeFile decodeFile;
+		
+		if (strcmp(argv[1], "-prc") == 0) {
+			decodeFile = decodePrc;
+		}  else if (strcmp(argv[1], "-rel") == 0) {
+			decodeFile = decodeRel;
+		} else {
+			return showUsage();
+		}
+		
+		if (strcmp(argv[2], "-v1") == 0) {
+			isV2 = 0;
+		}  else if (strcmp(argv[2], "-v2") == 0) {
+			isV2 = 1;
+		} else {
+			return showUsage();
+		}
+		
+		fp = fopen(argv[3], "rb");
+		if (fp) {
+			fseek(fp, 0, SEEK_END);
+			dataSize = ftell(fp);
+			fseek(fp, 0, SEEK_SET);
+			data = (uint8 *)malloc(dataSize);
+			if (data) {
+				fread(data, dataSize, 1, fp);
+				(*decodeFile)(isV2, data, dataSize);
+				free(data);
+			}
+			fclose(fp);
+		} else {
+			printf("Couldn't open script file '%s'\n", argv[3]);
+			return -1;
+		}
+	} else {
+		return showUsage();
+	}
+	return 0;
+}


Property changes on: scummvm/trunk/tools/cine_tools/cine_decode.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/tools/cine_tools/cine_unpack.cpp
===================================================================
--- scummvm/trunk/tools/cine_tools/cine_unpack.cpp	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/cine_unpack.cpp	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,323 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ * This is a utility to unpack Delphine's Cinematique engine's archive files.
+ * Should at least work with Future Wars and Operation Stealth.
+ * Supports using Operation Stealth's 'vol.cnf' file as input for selecting
+ * which archive files to unpack.
+ *
+ * Note that this isn't polished code so caveat emptor.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "cine_unpack.h"
+#include "typedefs.h"
+#include "endian.h"
+
+////////////////////////////////////////////////////////////////////////////
+
+uint32 CineUnpacker::readSource() {
+	if (_src < _srcBegin || _src + 4 > _srcEnd) {
+		_error = true;
+		return 0; // The source pointer is out of bounds, returning a default value
+	}
+	uint32 value = READ_BE_UINT32(_src);
+	_src -= 4;
+	return value;
+}
+
+uint CineUnpacker::rcr(bool inputCarry) {
+	uint outputCarry = (_chunk32b & 1);
+	_chunk32b >>= 1;
+	if (inputCarry) {
+		_chunk32b |= 0x80000000;
+	}
+	return outputCarry;
+}
+
+uint CineUnpacker::nextBit() {
+	uint carry = rcr(false);
+	// Normally if the chunk becomes zero then the carry is one as
+	// the end of chunk marker is always the last to be shifted out.
+	if (_chunk32b == 0) {
+		_chunk32b = readSource();
+		_crc ^= _chunk32b;
+		carry = rcr(true); // Put the end of chunk marker in the most significant bit
+	}
+	return carry;
+}
+
+uint CineUnpacker::getBits(uint numBits) {
+	uint c = 0;
+	while (numBits--) {
+		c <<= 1;
+		c |= nextBit();
+	}
+	return c;
+}
+
+void CineUnpacker::unpackRawBytes(uint numBytes) {
+	if (_dst >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
+		_error = true;
+		return; // Destination pointer is out of bounds for this operation
+	}
+	while (numBytes--) {
+		*_dst = (byte)getBits(8);
+		--_dst;
+	}
+}
+
+void CineUnpacker::copyRelocatedBytes(uint offset, uint numBytes) {
+	if (_dst + offset >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
+		_error = true;
+		return; // Destination pointer is out of bounds for this operation
+	}
+	while (numBytes--) {
+		*_dst = *(_dst + offset);
+		--_dst;
+	}
+}
+
+bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen) {
+	// Initialize variables used for detecting errors during unpacking
+	_error    = false;
+	_srcBegin = src;
+	_srcEnd   = src + srcLen;
+	_dstBegin = dst;
+	_dstEnd   = dst + dstLen;
+
+	// Initialize other variables
+	_src = _srcBegin + srcLen - 4;
+	uint32 unpackedLength = readSource(); // Unpacked length in bytes
+	_dst = _dstBegin + unpackedLength - 1;
+	_crc = readSource();
+	_chunk32b = readSource();
+	_crc ^= _chunk32b;
+
+	while (_dst >= _dstBegin && !_error) {
+		/*
+		Bits  => Action:
+		0 0   => unpackRawBytes(3 bits + 1)              i.e. unpackRawBytes(1..8)
+		1 1 1 => unpackRawBytes(8 bits + 9)              i.e. unpackRawBytes(9..264)
+		0 1   => copyRelocatedBytes(8 bits, 2)           i.e. copyRelocatedBytes(0..255, 2)
+		1 0 0 => copyRelocatedBytes(9 bits, 3)           i.e. copyRelocatedBytes(0..511, 3)
+		1 0 1 => copyRelocatedBytes(10 bits, 4)          i.e. copyRelocatedBytes(0..1023, 4)
+		1 1 0 => copyRelocatedBytes(12 bits, 8 bits + 1) i.e. copyRelocatedBytes(0..4095, 1..256)
+		*/
+		if (!nextBit()) { // 0...
+			if (!nextBit()) { // 0 0
+				uint numBytes = getBits(3) + 1;
+				unpackRawBytes(numBytes);
+			} else { // 0 1
+				uint numBytes = 2;
+				uint offset   = getBits(8);
+				copyRelocatedBytes(offset, numBytes);
+			}
+		} else { // 1...
+			uint c = getBits(2);
+			if (c == 3) { // 1 1 1
+				uint numBytes = getBits(8) + 9;
+				unpackRawBytes(numBytes);
+			} else if (c < 2) { // 1 0 x
+				uint numBytes = c + 3;
+				uint offset   = getBits(c + 9);
+				copyRelocatedBytes(offset, numBytes);
+			} else { // 1 1 0
+				uint numBytes = getBits(8) + 1;
+				uint offset   = getBits(12);
+				copyRelocatedBytes(offset, numBytes);
+			}
+		}
+	}
+	return !_error && (_crc == 0);
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static void unpackFile(FILE *fp, const char *outDir) {
+	char filePath[512], fileName[15];
+
+	uint entryCount = freadUint16BE(fp); // How many entries?
+	uint entrySize = freadUint16BE(fp); // How many bytes per entry?
+	assert(entrySize == 0x1e);
+	while (entryCount--) {
+		fread(fileName, 14, 1, fp);
+		fileName[14] = '\0';
+		sprintf(filePath, "%s/%s", outDir, fileName);
+		FILE *fpOut = fopen(filePath, "wb");
+		
+		uint32 offset = freadUint32BE(fp);
+		unsigned int packedSize = freadUint32BE(fp);
+		unsigned int unpackedSize = freadUint32BE(fp);
+		freadUint32BE(fp);
+		uint savedPos = ftell(fp);
+		
+		if (!fpOut) {
+			printf("ERROR: unable to open '%s' for writing\n", filePath);
+			continue;
+		}
+		printf("unpacking '%s' ... ", filePath);		
+		
+		fseek(fp, offset, SEEK_SET);		
+		assert(unpackedSize >= packedSize);
+		uint8 *data = (uint8 *)calloc(unpackedSize, 1);
+		uint8 *packedData = (uint8 *)calloc(packedSize, 1);
+		assert(data);
+		assert(packedData);
+		fread(packedData, packedSize, 1, fp);
+		bool status = true;
+		if (packedSize != unpackedSize) {
+			CineUnpacker cineUnpacker;
+			status = cineUnpacker.unpack(packedData, packedSize, data, unpackedSize);
+		} else {
+			memcpy(data, packedData, packedSize);
+		}
+		free(packedData);
+		fwrite(data, unpackedSize, 1, fpOut);
+		fclose(fpOut);
+		free(data);
+		
+		if (!status) {
+			printf("CRC ERROR");
+		} else {
+			printf("ok");
+		}
+		printf(", packedSize %u unpackedSize %u\n", packedSize, unpackedSize);
+		fseek(fp, savedPos, SEEK_SET);
+	}
+}
+
+void fixVolCnfFileName(char *dst, const uint8 *src) {
+	char *ext, *end;
+	
+	memcpy(dst, src, 8);
+	src += 8;
+	dst[8] = 0;	
+	ext = strchr(dst, ' ');	
+	if (!ext) {
+		ext = &dst[8];
+	}
+	if (*src == ' ') {
+		*ext = 0;
+	} else {
+		*ext++ = '.';
+		memcpy(ext, src, 3);
+		end = strchr(ext, ' ');
+		if (!end) {
+			end = &ext[3];
+		}
+		*end = 0;
+	}
+}
+
+void unpackAllResourceFiles(const char *filename, const char *outDir) { 
+	FILE *fp = fopen(filename, "rb");
+	if (!fp) {
+		printf("Unable to open file '%s'\n", filename);
+		exit(1);
+	}
+	
+	uint32 unpackedSize, packedSize;
+	{
+		char header[8];
+		fread(header, 8, 1, fp);
+		if (memcmp(header, "ABASECP", 7) == 0) {
+			unpackedSize = freadUint32BE(fp);
+			packedSize = freadUint32BE(fp);
+		} else {
+			fseek(fp, 0, SEEK_END);
+			unpackedSize = packedSize = ftell(fp); /* Get file size */
+			fseek(fp, 0, SEEK_SET);
+		}
+	}
+	assert(unpackedSize >= packedSize);
+	uint8 *buf = (uint8 *)calloc(unpackedSize, 1);
+	assert(buf);
+	fread(buf, packedSize, 1, fp);
+	fclose(fp);
+	if (packedSize != unpackedSize) {
+		CineUnpacker cineUnpacker;
+		if (!cineUnpacker.unpack(buf, packedSize, buf, unpackedSize)) {
+			printf("Error while unpacking 'vol.cnf' data");
+			exit(1);
+		}
+	}
+	uint resourceFilesCount = READ_BE_UINT16(&buf[0]);
+	uint entrySize = READ_BE_UINT16(&buf[2]);
+	printf("--- Unpacking all %d resource files from 'vol.cnf' (entrySize = %d):\n", resourceFilesCount, entrySize);
+	char resourceFileName[9];
+	for (unsigned int i = 0; i < resourceFilesCount; ++i) {
+		memcpy(resourceFileName, &buf[4 + i * entrySize], 8);
+		resourceFileName[8] = 0;
+		FILE *fpResFile = fopen(resourceFileName, "rb");
+		if (fpResFile) {
+			printf("--- Unpacking resource file %s:\n", resourceFileName);
+			unpackFile(fpResFile, outDir);
+			fclose(fpResFile);
+		} else {
+			printf("ERROR: Unable to open resource file %s\n", resourceFileName);
+		}
+	}
+
+	free(buf);
+}
+
+int showUsage() {
+	printf("USAGE: cine_unpack [input file] [output directory]\n" \
+		"Supports using Operation Stealth's 'vol.cnf' file as input.\n");
+	return -1;
+}
+
+int main(int argc, char *argv[]) {
+	int i;
+	char tmp[512];
+	
+	if (argc == 3) {
+		strcpy(tmp, argv[1]);
+		for (i = 0; tmp[i] != 0; i++) {
+			tmp[i] = toupper(tmp[i]);
+		}
+		if (!strcmp(tmp, "VOL.CNF")) {
+			/* Unpack all archive files listed in 'vol.cnf' */
+			unpackAllResourceFiles(argv[1], argv[2]);
+		} else {
+			/* Unpack a single archive file */
+			FILE *fp = fopen(argv[1], "rb");
+			if (fp) {
+				unpackFile(fp, argv[2]);
+				fclose(fp);
+			} else {
+				printf("Couldn't open input file '%s'\n", argv[1]);
+				return -1;
+			}
+		}
+	} else {
+		return showUsage();
+	}
+	return 0;
+}


Property changes on: scummvm/trunk/tools/cine_tools/cine_unpack.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/tools/cine_tools/cine_unpack.h
===================================================================
--- scummvm/trunk/tools/cine_tools/cine_unpack.h	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/cine_unpack.h	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,87 @@
+#ifndef CINE_UNPACK_H
+#define CINE_UNPACK_H
+
+#include "typedefs.h"
+
+/**
+ * A LZ77 style decompressor for Delphine's data files
+ * used in at least Future Wars and Operation Stealth.
+ * @note Works backwards in the source and destination buffers.
+ * @note Can work with source and destination in the same buffer if there's space.
+ */
+class CineUnpacker {
+public:
+	/**
+	 * Unpacks packed data from the source buffer to the destination buffer.
+	 * @warning Do NOT call this on data that is not packed.
+	 * @note Source and destination buffer pointers can be the same as long as there's space for the unpacked data.
+	 * @param src Pointer to the source buffer.
+	 * @param srcLen Length of the source buffer.
+	 * @param dst Pointer to the destination buffer.
+	 * @param dstLen Length of the destination buffer.
+	 * @return True if no errors were detected in the source data and unpacking was successful, otherwise false.
+	 */
+	bool unpack(const byte *src, uint srcLen, byte *dst, uint dstLen);
+private:
+	/**
+	 * Reads an unsigned big endian 32-bit integer from the source stream and goes backwards 4 bytes.
+	 * @return If the operation is valid, an unsigned big endian 32-bit integer read from the source stream.
+	 * @return If the operation is invalid, zero.
+	 * @note Sets internal error state if the read operation would be out of source bounds.
+	 */
+	uint32 readSource();
+
+	/**
+	 * Shifts the current internal 32-bit chunk to the right by one.
+	 * Puts input carry into internal chunk's topmost (i.e. leftmost) bit.
+	 * @return The least significant bit that was shifted out from the chunk.
+	 */
+	uint rcr(bool inputCarry);
+
+	/**
+	 * Get the next bit from the source stream.
+	 * @note Changes the bit position in the source stream.
+	 * @return The next bit from the source stream.
+	 */
+	uint nextBit();
+
+	/**
+	 * Get bits from the source stream.
+	 * @note Changes the bit position in the source stream.
+	 * @param numBits Number of bits to read from the source stream.	 
+	 * @return Integer value consisting of the bits read from the source stream (In range [0, (2 ** numBits) - 1]).
+	 * @return Later the bit was read from the source, the less significant it is in the return value.
+	 */
+	uint getBits(uint numBits);
+
+	/**
+	 * Copy raw bytes from the input stream and write them to the destination stream.
+	 * This is used when no adequately long match is found in the sliding window.
+	 * @note Sets internal error state if the operation would be out of bounds.
+	 * @param numBytes Amount of bytes to copy from the input stream
+	 */
+	void unpackRawBytes(uint numBytes);
+
+	/**
+	 * Copy bytes from the sliding window in the destination buffer.
+	 * This is used when a match of two bytes or longer is found.
+	 * @note Sets internal error state if the operation would be out of bounds.
+	 * @param offset Offset in the sliding window
+	 * @param numBytes Amount of bytes to copy
+	 */
+	void copyRelocatedBytes(uint offset, uint numBytes);
+private:
+	uint32 _crc;      //!< Error-detecting code (This should be zero after successful unpacking)
+	uint32 _chunk32b; //!< The current internal 32-bit chunk of source data
+	byte *_dst;       //!< Pointer to the current position in the destination buffer
+	const byte *_src; //!< Pointer to the current position in the source buffer
+
+	// These are used for detecting errors (e.g. out of bounds issues) during unpacking
+	bool _error;           //!< Did an error occur during unpacking?
+	const byte *_srcBegin; //!< Source buffer's beginning
+	const byte *_srcEnd;   //!< Source buffer's end
+	byte *_dstBegin;       //!< Destination buffer's beginning
+	byte *_dstEnd;         //!< Destination buffer's end
+};
+
+#endif


Property changes on: scummvm/trunk/tools/cine_tools/cine_unpack.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/tools/cine_tools/endian.h
===================================================================
--- scummvm/trunk/tools/cine_tools/endian.h	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/endian.h	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,30 @@
+#ifndef CINE_ENDIAN_H
+#define CINE_ENDIAN_H
+
+#include <stdio.h> // fread etc
+#include "typedefs.h" // uint8 etc
+
+/* NOTE: These big endian reading functions assume we're on a little endian machine. */
+static uint16 READ_BE_UINT16(const void *ptr) {
+	const uint8 *b = (const uint8 *)ptr;
+	return (b[0] << 8) | b[1];
+}
+
+static uint32 READ_BE_UINT32(const void *ptr) {
+	const uint8 *b = (const uint8 *)ptr;
+	return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+}
+
+static uint16 freadUint16BE(FILE *fp) {
+	char data[2];
+	fread(data, 2, 1, fp);
+	return READ_BE_UINT16(data);
+}
+
+static uint32 freadUint32BE(FILE *fp) {
+	char data[4];
+	fread(data, 4, 1, fp);
+	return READ_BE_UINT32(data);
+}
+
+#endif


Property changes on: scummvm/trunk/tools/cine_tools/endian.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/tools/cine_tools/typedefs.h
===================================================================
--- scummvm/trunk/tools/cine_tools/typedefs.h	                        (rev 0)
+++ scummvm/trunk/tools/cine_tools/typedefs.h	2008-08-25 15:04:48 UTC (rev 34153)
@@ -0,0 +1,14 @@
+#ifndef CINE_TYPEDEFS_H
+#define CINE_TYPEDEFS_H
+
+typedef unsigned char uint8;
+typedef signed char int8;
+typedef unsigned short uint16;
+typedef signed short int16;
+typedef unsigned long uint32;
+typedef signed long int32;
+
+typedef unsigned int uint;
+typedef unsigned char byte;
+
+#endif


Property changes on: scummvm/trunk/tools/cine_tools/typedefs.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list