[Scummvm-cvs-logs] scummvm-tools master -> 44ae74f78c3ff80b9a5778c5599cbff47c8053f9
criezy
criezy at scummvm.org
Thu Mar 20 23:34:51 CET 2014
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm-tools' repo located at https://github.com/scummvm/scummvm-tools .
Summary:
44ae74f78c CGE: Upgrade extraction and packing tools so they can handle CGE2's files.
Commit: 44ae74f78c3ff80b9a5778c5599cbff47c8053f9
https://github.com/scummvm/scummvm-tools/commit/44ae74f78c3ff80b9a5778c5599cbff47c8053f9
Author: Peter BozsoĢ (koppirnyo at gmail.com)
Date: 2014-03-20T22:32:14Z
Commit Message:
CGE: Upgrade extraction and packing tools so they can handle CGE2's files.
Changed paths:
README
engines/cge/cge_structs.h
engines/cge/extract_cge.cpp
engines/cge/extract_cge.h
engines/cge/pack_cge.cpp
engines/cge/pack_cge.h
diff --git a/README b/README
index 647d5f7..70822e3 100644
--- a/README
+++ b/README
@@ -53,12 +53,12 @@ Extraction Tools:
./scummvm-tools-cli --tool extract_agos <infile 1> ... <infile n>
extract_cge
- Unpack Soltys game data files.
+ Unpack Soltys and Sfinx game data files.
Example of usage:
./scummvm-tools-cli --tool extract_cge [-o outputdir] <inputfile>
pack_cge
- Pack Soltys game data files.
+ Pack Soltys and Sfinx game data files.
Example of usage:
./scummvm-tools-cli --tool pack_cge [-o outputdir] <inputdir>
diff --git a/engines/cge/cge_structs.h b/engines/cge/cge_structs.h
index 0fe9431..8d4efcd 100644
--- a/engines/cge/cge_structs.h
+++ b/engines/cge/cge_structs.h
@@ -29,9 +29,10 @@
/**
* The following defines are copied from the cge engine file btfile.h
*/
-#define kBtSize 1024
#define kBtKeySize 13
#define kBtLevel 2
+#define kBtPageSize 1024
+#define kBtPageSize2 2048
struct CgeBtKeypack {
char _key[kBtKeySize];
@@ -39,6 +40,12 @@ struct CgeBtKeypack {
uint16 _size;
};
+struct CgeBtKeypack2 {
+ char _key[kBtKeySize];
+ uint32 _mark;
+ uint32 _size;
+};
+
struct CgeInner {
uint8 _key[kBtKeySize];
uint16 _down;
@@ -49,18 +56,27 @@ struct CgeHea {
uint16 _down;
};
-#define CGE_INN_SIZE ((kBtSize - sizeof(CgeHea)) / sizeof(CgeInner))
-#define CGE_LEA_SIZE ((kBtSize - sizeof(CgeHea)) / sizeof(CgeBtKeypack))
-
struct BtPage {
CgeHea _hea;
union {
// dummy filler to make proper size of union
- uint8 _data[kBtSize - sizeof(CgeHea)];
+ uint8 _data[kBtPageSize - sizeof(CgeHea)];
+ // inner version of data: key + word-sized page link
+ CgeInner _inn[(kBtPageSize - sizeof(CgeHea)) / sizeof(CgeInner)];
+ // leaf version of data: key + all user data
+ CgeBtKeypack _lea[(kBtPageSize - sizeof(CgeHea)) / sizeof(CgeBtKeypack)];
+ };
+};
+
+struct BtPage2 {
+ CgeHea _hea;
+ union {
+ // dummy filler to make proper size of union
+ uint8 _data[kBtPageSize2 - sizeof(CgeHea)];
// inner version of data: key + word-sized page link
- CgeInner _inn[(kBtSize - sizeof(CgeHea)) / sizeof(CgeInner)];
+ CgeInner _inn[(kBtPageSize2 - sizeof(CgeHea)) / sizeof(CgeInner)];
// leaf version of data: key + all user data
- CgeBtKeypack _lea[(kBtSize - sizeof(CgeHea)) / sizeof(CgeBtKeypack)];
+ CgeBtKeypack2 _lea[(kBtPageSize2 - sizeof(CgeHea)) / sizeof(CgeBtKeypack2)];
};
};
diff --git a/engines/cge/extract_cge.cpp b/engines/cge/extract_cge.cpp
index 3593e84..517fecd 100644
--- a/engines/cge/extract_cge.cpp
+++ b/engines/cge/extract_cge.cpp
@@ -25,22 +25,56 @@
#include "extract_cge.h"
#include "cge_structs.h"
-#define BUFFER_SIZE 8192
-#define SEED 0xA5
+#define SEED 0xA5
ExtractCge::ExtractCge(const std::string &name) : Tool(name, TOOLTYPE_EXTRACTION) {
ToolInput input;
input.format = "vol.*";
_inputPaths.push_back(input);
-
+
_outputToDirectory = true;
- _shorthelp = "Used to extract Soltys data files.";
+ _shorthelp = "Used to extract Soltys and Sfinx data files.";
_helptext = "\nUsage: " + getName() + " [-o /path/to/output/dir/] <inputfile>\n";
}
void ExtractCge::execute() {
- unpack();
+ Common::Filename filename = _inputPaths[0].path;
+
+ filename.setFullName("vol.cat");
+ _volCat.open(filename, "rb");
+ if (!_volCat.isOpen()) {
+ error("Unable to open vol.cat");
+ }
+
+ filename.setFullName("vol.dat");
+ _volDat.open(filename, "rb");
+ if (!_volDat.isOpen()) {
+ _volCat.close();
+ error("Unable to open vol.dat");
+ }
+
+ // We always need to setup default output path, since there is no obligation to specify it
+ if (_outputPath.empty())
+ _outputPath.setFullPath("./");
+
+ _outputPath.setFullName("files.txt");
+ _fFiles.open(_outputPath, "w");
+ if (!_fFiles.isOpen()) {
+ _volCat.close();
+ _volDat.close();
+ error("Unable to create files.txt");
+ }
+
+ if (!unpack()) {
+ _volCat.seek(0, SEEK_SET);
+ _volDat.seek(0, SEEK_SET);
+ unpack2();
+ }
+
+ _volCat.close();
+ _volDat.close();
+ _fFiles.close();
}
InspectionMatch ExtractCge::inspectInput(const Common::Filename &filename) {
@@ -60,70 +94,62 @@ void ExtractCge::readData(Common::File &f, byte *buff, int size) {
buff[i] ^= SEED;
}
-void ExtractCge::unpack() {
- print("Unpacking...");
-
+bool ExtractCge::unpack() {
BtPage btPage;
- Common::Filename filename = _inputPaths[0].path;
- filename.setFullName("vol.cat");
- Common::File volCat(filename, "rb");
- if (!volCat.isOpen()) {
- error("Unable to open vol.cat");
- }
-
- filename.setFullName("vol.dat");
- Common::File volDat(filename, "rb");
- if (!volDat.isOpen()) {
- error("Unable to open vol.dat");
- }
-
- // We always need to setup default output path, since there is no obligation to specify it
- if (_outputPath.empty())
- _outputPath.setFullPath("./");
-
- _outputPath.setFullName("files.txt");
- Common::File fFiles(_outputPath, "w");
- if (!fFiles.isOpen()) {
- error("Unable to create files.txt");
- }
-
// Get in a list of pages individual files will be on
- readData(volCat, (byte *)&btPage, sizeof(BtPage));
+ readData(_volCat, (byte *)&btPage, sizeof(BtPage));
int pageList[1000];
int pageCount = btPage._hea._count;
+ if (pageCount > 998) {
+ print("CAT/DAT file not detected as CGE1...");
+ return false; // If it's a mess, we stop trying with CGE1.
+ }
pageList[0] = btPage._hea._down;
for (int i = 0; i < pageCount; ++i)
pageList[i + 1] = btPage._inn[i]._down;
-
- bool first = true;
+
+ for (int i = 0; i <= pageCount; ++i) {
+ // Move to correct page and read it
+ _volCat.seek(pageList[i] * sizeof(BtPage), SEEK_SET);
+ readData(_volCat, (byte *)&btPage, sizeof(BtPage));
+
+ // Process the files
+ for (unsigned int fileNum = 0; fileNum < btPage._hea._count; ++fileNum) {
+ // If it's bigger than the upper limit of the array...
+ if (fileNum > ((kBtPageSize - sizeof(CgeHea)) / sizeof(CgeBtKeypack) - 1)) {
+ print("CAT/DAT file not detected as CGE1...");
+ return false; // ...we stop trying with CGE1.
+ }
+ }
+ }
+
+ // Otherwise it's all ok:
+ print("Unpacking as CGE1...");
+ _fFiles.print("CGE1");
+
Common::File fOut;
// Loop through the pages of individual files
for (int i = 0; i <= pageCount; ++i) {
// Move to correct page and read it
- volCat.seek(pageList[i] * sizeof(BtPage), SEEK_SET);
- readData(volCat, (byte *)&btPage, sizeof(BtPage));
-
+ _volCat.seek(pageList[i] * sizeof(BtPage), SEEK_SET);
+ readData(_volCat, (byte *)&btPage, sizeof(BtPage));
+
// Process the files
for (unsigned int fileNum = 0; fileNum < btPage._hea._count; ++fileNum) {
char fname[256];
strcpy(fname, btPage._lea[fileNum]._key);
-
+
// Add filename to files list
- if (!first)
- fFiles.print("\n%s", btPage._lea[fileNum]._key);
- else {
- fFiles.print("%s", btPage._lea[fileNum]._key);
- first = false;
- }
+ _fFiles.print("\n%s", btPage._lea[fileNum]._key);
_outputPath.setFullName(fname);
fOut.open(_outputPath, "wb");
byte *buffer = (byte *)malloc(btPage._lea[fileNum]._size);
- volDat.seek(btPage._lea[fileNum]._mark, SEEK_SET);
- readData(volDat, buffer, btPage._lea[fileNum]._size);
+ _volDat.seek(btPage._lea[fileNum]._mark, SEEK_SET);
+ readData(_volDat, buffer, btPage._lea[fileNum]._size);
fOut.write(buffer, btPage._lea[fileNum]._size);
fOut.close();
@@ -131,16 +157,56 @@ void ExtractCge::unpack() {
}
}
- volCat.close();
- volDat.close();
- fFiles.close();
+ return true;
}
+void ExtractCge::unpack2() {
+ BtPage2 btPage2;
+
+ print("Unpacking as CGE2...");
+ // Get in a list of pages individual files will be on
+ readData(_volCat, (byte *)&btPage2, sizeof(BtPage2));
+
+ int pageList[1000];
+ int pageCount = btPage2._hea._count;
+ pageList[0] = btPage2._hea._down;
+ for (int i = 0; i < pageCount; ++i)
+ pageList[i + 1] = btPage2._inn[i]._down;
+
+ Common::File fOut;
+ _fFiles.print("CGE2");
+
+ // Loop through the pages of individual files
+ for (int i = 0; i <= pageCount; ++i) {
+ // Move to correct page and read it
+ _volCat.seek(pageList[i] * sizeof(BtPage2), SEEK_SET);
+ readData(_volCat, (byte *)&btPage2, sizeof(BtPage2));
+
+ // Process the files
+ for (unsigned int fileNum = 0; fileNum < btPage2._hea._count; ++fileNum) {
+ char fname[256];
+ strcpy(fname, btPage2._lea[fileNum]._key);
+
+ // Add filename to files list
+ _fFiles.print("\n%s", fname);
+
+ _outputPath.setFullName(fname);
+ fOut.open(_outputPath, "wb");
+ byte *buffer = (byte *)malloc(btPage2._lea[fileNum]._size);
+
+ _volDat.seek(btPage2._lea[fileNum]._mark, SEEK_SET);
+ readData(_volDat, buffer, btPage2._lea[fileNum]._size);
+ fOut.write(buffer, btPage2._lea[fileNum]._size);
+
+ fOut.close();
+ free(buffer);
+ }
+ }
+}
+
#ifdef STANDALONE_MAIN
int main(int argc, char *argv[]) {
ExtractCge cge(argv[0]);
return cge.run(argc, argv);
}
#endif
-
-
diff --git a/engines/cge/extract_cge.h b/engines/cge/extract_cge.h
index 4c4bc5c..d2a2006 100644
--- a/engines/cge/extract_cge.h
+++ b/engines/cge/extract_cge.h
@@ -34,7 +34,10 @@ public:
protected:
void readData(Common::File &f, byte *buff, int size);
- void unpack();
+ bool unpack();
+ void unpack2();
+
+ Common::File _volCat, _volDat, _fFiles;
};
#endif
diff --git a/engines/cge/pack_cge.cpp b/engines/cge/pack_cge.cpp
index 240ac54..ba74a41 100644
--- a/engines/cge/pack_cge.cpp
+++ b/engines/cge/pack_cge.cpp
@@ -23,14 +23,8 @@
#include <stdlib.h>
#include <string.h>
#include "pack_cge.h"
-#include "cge_structs.h"
-#define SEED 0xA5
-#define MAX_FILES 5000
-
-// TODO:
-// - Use output directory instead of current directory
-// - Use input directory instead of current directory
+#define SEED 0xA5
PackCge::PackCge(const std::string &name) : Tool(name, TOOLTYPE_EXTRACTION/*TOOLTYPE_UNKNOWN*/) {
ToolInput input;
@@ -40,12 +34,77 @@ PackCge::PackCge(const std::string &name) : Tool(name, TOOLTYPE_EXTRACTION/*TOOL
_outputToDirectory = true;
- _shorthelp = "Used to repackage Soltys data files.";
+ _shorthelp = "Used to repackage Soltys and Sfinx data files.";
_helptext = "\nUsage: " + getName() + " [-o /path/to/output/dir/] /path/to/one_game_file\n";
}
void PackCge::execute() {
- pack();
+ // Load in the list of _files to recompress
+ inPath.setFullPath(_inputPaths[0].path);
+ inPath.setFullName("files.txt");
+ _fIn.open(inPath, "r");
+ if (!_fIn.isOpen()) {
+ error("Unable to open %s", inPath.getFullPath().c_str());
+ }
+
+ // Define the version and the depending size of a leaf in the tree.
+ _leaSize = 0;
+ int version = 0;
+ char versionLine[kBtKeySize];
+ _fIn.scanString(&versionLine[0]);
+ std::string sversion(versionLine);
+ std::string verHeader("CGE2");
+ if (sversion.compare(verHeader) == 0) {
+ version = 2;
+ _leaSize = (kBtPageSize2 - sizeof(CgeHea)) / sizeof(CgeBtKeypack2);
+ } else {
+ version = 1;
+ _leaSize = (kBtPageSize - sizeof(CgeHea)) / sizeof(CgeBtKeypack);
+
+ // Handle the old CGE1 format:
+ verHeader = std::string("CGE1");
+ if (sversion.compare(verHeader) != 0)
+ _fIn.seek(0, SEEK_SET); // So we have to rewind the file, since there's no header.
+ }
+
+ _fileCount = 0;
+ while (!_fIn.eos()) {
+ _fIn.scanString(&_files[_fileCount++][0]);
+ if (_fileCount == MAX_FILES) {
+ _fIn.close();
+ error("Max files reached");
+ }
+ }
+ _fIn.close();
+
+ // Open vol cat and dat files for writing
+ if (_outputPath.empty())
+ _outputPath.setFullPath("./");
+ _outputPath.setFullName("vol.cat");
+ _volCat.open(_outputPath, "wb");
+ if (!_volCat.isOpen()) {
+ error("Unable to create %s", _outputPath.getFullPath().c_str());
+ }
+ _outputPath.setFullName("vol.dat");
+ _volDat.open(_outputPath, "wb");
+ if (!_volDat.isOpen()) {
+ _volCat.close();
+ error("Unable to create %s", _outputPath.getFullPath().c_str());
+ }
+
+ switch (version) {
+ case 1:
+ pack();
+ break;
+ case 2:
+ pack2();
+ break;
+ default:
+ break;
+ }
+
+ _volCat.close();
+ _volDat.close();
}
InspectionMatch PackCge::inspectInput(const Common::Filename &filename) {
@@ -69,67 +128,34 @@ void PackCge::writeData(Common::File &f, byte *buff, int size) {
void PackCge::pack() {
BtPage btPage;
- print("Packing...");
+ print("Packing as CGE1...");
- Common::Filename inPath(_inputPaths[0].path);
-
- // Load in the list of files to recompress
- char files[MAX_FILES][kBtKeySize];
- int fileCount = 0;
- inPath.setFullName("files.txt");
- Common::File fIn(inPath, "r");
- if (!fIn.isOpen()) {
- error("Unable to open %s", inPath.getFullPath().c_str());
- }
-
- while (!fIn.eos()) {
- fIn.scanString(&files[fileCount++][0]);
- if (fileCount == MAX_FILES) {
- error("Max files reached");
- }
- }
- fIn.close();
-
- // Open vol cat and dat files for writing
- if (_outputPath.empty())
- _outputPath.setFullPath("./");
- _outputPath.setFullName("vol.cat");
- Common::File volCat(_outputPath, "wb");
- if (!volCat.isOpen()) {
- error("Unable to create %s", _outputPath.getFullPath().c_str());
- }
- _outputPath.setFullName("vol.dat");
- Common::File volDat(_outputPath, "wb");
- if (!volDat.isOpen()) {
- error("Unable to create %s", _outputPath.getFullPath().c_str());
- }
-
/* Build the index page */
// Header
memset(&btPage, 0, sizeof(BtPage));
- int pageCount = fileCount / CGE_LEA_SIZE;
+ int pageCount = _fileCount / _leaSize;
btPage._hea._count = pageCount;
btPage._hea._down = 1;
// Innert file list - lists the first file of the next page
for (int pageNum = 0; pageNum < pageCount; ++pageNum) {
- int nextFile = (pageNum + 1) * CGE_LEA_SIZE;
+ int nextFile = (pageNum + 1) * _leaSize;
btPage._inn[pageNum]._down = pageNum + 2;
- strcpy((char *)&btPage._inn[pageNum]._key[0], files[nextFile]);
+ strcpy((char *)&btPage._inn[pageNum]._key[0], _files[nextFile]);
}
// Write out the index page
- writeData(volCat, (byte *)&btPage, sizeof(BtPage));
+ writeData(_volCat, (byte *)&btPage, sizeof(BtPage));
// Loop through processing each page and the dat file
- pageCount = (fileCount + CGE_LEA_SIZE - 1) / CGE_LEA_SIZE;
+ pageCount = (_fileCount + _leaSize - 1) / _leaSize;
int fileIndex = 0;
for (int pageNum = 0; pageNum < pageCount; ++pageNum) {
- int startFile = pageNum * CGE_LEA_SIZE;
- int lastFile = (pageNum + 1) * CGE_LEA_SIZE - 1;
- if (lastFile >= fileCount)
- lastFile = fileCount - 1;
+ int startFile = pageNum * _leaSize;
+ int lastFile = (pageNum + 1) * _leaSize - 1;
+ if (lastFile >= _fileCount)
+ lastFile = _fileCount - 1;
// Header
memset(&btPage, 0, sizeof(BtPage));
@@ -138,40 +164,108 @@ void PackCge::pack() {
for (int fileNum = 0; fileNum < btPage._hea._count; ++fileNum, ++fileIndex) {
// Set filename and offset in dat file
- strcpy(btPage._lea[fileNum]._key, &files[fileIndex][0]);
- btPage._lea[fileNum]._mark = volDat.pos();
+ strcpy(btPage._lea[fileNum]._key, &_files[fileIndex][0]);
+ btPage._lea[fileNum]._mark = _volDat.pos();
// Load the given file and write it into the dat file
char fname[32];
- strcpy(fname, files[fileIndex]);
+ strcpy(fname, _files[fileIndex]);
// Open the file and get the size
inPath.setFullName(fname);
- fIn.open(inPath, "rb");
- if (!fIn.isOpen()) {
+ _fIn.open(inPath, "rb");
+ if (!_fIn.isOpen()) {
error("Error opening %s", inPath.getFullPath().c_str());
}
- int fileSize = fIn.size();
- fIn.seek(0, SEEK_SET);
- btPage._lea[fileNum]._size = fileSize;
+ int _filesize = _fIn.size();
+ _fIn.seek(0, SEEK_SET);
+ btPage._lea[fileNum]._size = _filesize;
// Allocate buffer space for the file
- byte *buffer = (byte *)malloc(fileSize);
+ byte *buffer = (byte *)malloc(_filesize);
// Read it in, encrypt it, and write it out
- fIn.read_noThrow(buffer, fileSize);
- writeData(volDat, buffer, fileSize);
+ _fIn.read_noThrow(buffer, _filesize);
+ writeData(_volDat, buffer, _filesize);
free(buffer);
- fIn.close();
+ _fIn.close();
}
// Write out the page
- writeData(volCat, (byte *)&btPage, sizeof(BtPage));
+ writeData(_volCat, (byte *)&btPage, sizeof(BtPage));
+ }
+}
+
+void PackCge::pack2() {
+ BtPage2 btPage2;
+ print("Packing as CGE2...");
+
+ /* Build the index page */
+ // Header
+ memset(&btPage2, 0, sizeof(BtPage2));
+ int pageCount = _fileCount / _leaSize;
+ btPage2._hea._count = pageCount;
+ btPage2._hea._down = 1;
+
+ // Innert file list - lists the first file of the next page
+ for (int pageNum = 0; pageNum < pageCount; ++pageNum) {
+ int nextFile = (pageNum + 1) * _leaSize;
+
+ btPage2._inn[pageNum]._down = pageNum + 2;
+ strcpy((char *)&btPage2._inn[pageNum]._key[0], _files[nextFile]);
}
- volCat.close();
- volDat.close();
+ // Write out the index page
+ writeData(_volCat, (byte *)&btPage2, sizeof(BtPage2));
+
+ // Loop through processing each page and the dat file
+ pageCount = (_fileCount + _leaSize - 1) / _leaSize;
+ int fileIndex = 0;
+ for (int pageNum = 0; pageNum < pageCount; ++pageNum) {
+ int startFile = pageNum * _leaSize;
+ int lastFile = (pageNum + 1) * _leaSize - 1;
+ if (lastFile >= _fileCount)
+ lastFile = _fileCount - 1;
+
+ // Header
+ memset(&btPage2, 0, sizeof(BtPage2));
+ btPage2._hea._count = lastFile - startFile + 1;
+ btPage2._hea._down = 0xffff;
+
+ for (int fileNum = 0; fileNum < btPage2._hea._count; ++fileNum, ++fileIndex) {
+ // Set filename and offset in dat file
+ strcpy(btPage2._lea[fileNum]._key, &_files[fileIndex][0]);
+ btPage2._lea[fileNum]._mark = _volDat.pos();
+
+ // Load the given file and write it into the dat file
+ char fname[32];
+ strcpy(fname, _files[fileIndex]);
+
+ // Open the file and get the size
+ inPath.setFullName(fname);
+ _fIn.open(inPath, "rb");
+ if (!_fIn.isOpen()) {
+ error("Error opening %s", inPath.getFullPath().c_str());
+ }
+ int _filesize = _fIn.size();
+ _fIn.seek(0, SEEK_SET);
+ btPage2._lea[fileNum]._size = _filesize;
+
+ // Allocate buffer space for the file
+ byte *buffer = (byte *)malloc(_filesize);
+
+ // Read it in, encrypt it, and write it out
+ _fIn.read_noThrow(buffer, _filesize);
+ writeData(_volDat, buffer, _filesize);
+
+ free(buffer);
+ _fIn.close();
+ }
+
+ // Write out the page
+ writeData(_volCat, (byte *)&btPage2, sizeof(BtPage2));
+ }
}
#ifdef STANDALONE_MAIN
diff --git a/engines/cge/pack_cge.h b/engines/cge/pack_cge.h
index 6124959..df171f4 100644
--- a/engines/cge/pack_cge.h
+++ b/engines/cge/pack_cge.h
@@ -23,6 +23,9 @@
#define PACK_CGE_H
#include "tool.h"
+#include "cge_structs.h"
+
+#define MAX_FILES 6000
class PackCge : public Tool {
public:
@@ -35,6 +38,12 @@ public:
protected:
void writeData(Common::File &f, byte *buff, int size);
void pack();
+ void pack2();
+
+ Common::Filename inPath;
+ Common::File _volCat, _volDat, _fIn;
+ int _leaSize, _fileCount;
+ char _files[MAX_FILES][kBtKeySize];
};
#endif
More information about the Scummvm-git-logs
mailing list