aboutsummaryrefslogtreecommitdiff
path: root/tools/cine_tools/cine_unpack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cine_tools/cine_unpack.cpp')
-rw-r--r--tools/cine_tools/cine_unpack.cpp325
1 files changed, 0 insertions, 325 deletions
diff --git a/tools/cine_tools/cine_unpack.cpp b/tools/cine_tools/cine_unpack.cpp
deleted file mode 100644
index ab9142ad3b..0000000000
--- a/tools/cine_tools/cine_unpack.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/* 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.
- *
- * FIXME: Make this code endian safe.
- */
-
-#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;
-}