Files
scummvm-tools/extract_scumm_mac.cpp
T
Hampus Nilsson 168e91e076 *Started on CLI interface, already works but there are many edges to sort out.
*Added a common 'Tools' class to be used by both the CLI and the GUI, right now it's NOT in use by the GUI, so there is some code clutter.
*Rename gui/tools.h to gui/tools.cpp
*Tools now know their own type.
*Some other small changes.

svn-id: r42670
2009-07-23 01:41:14 +00:00

140 lines
4.0 KiB
C++

/* extract_scumm_mac - Split one-big-file Macintosh game data into seperate .00x files for ScummVM
* Copyright (C) 2001-2003 Casey Hutchinson
* Copyright (C) 2004-2006 The ScummVM Team
*
* 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$
*
*/
#include "extract_scumm_mac.h"
/* this makes extract_scumm_mac convert extracted file names to lower case */
#define CHANGECASE
ExtractScummMac::ExtractScummMac(const std::string &name) : Tool(name, TOOLTYPE_EXTRACTION) {
ToolInput input;
input.format = "*.*";
_inputPaths.push_back(input);
_helptext =
"\nUsage: " + _name + " [-o <output dir> = out/] <file>\n"
"\tSome Lucas Arts CDs appear to contains only an application.\n"
"\tThey actually contain a seperate data file as a hidden file.\n";
}
void ExtractScummMac::execute() {
unsigned long file_record_off, file_record_len;
unsigned long file_off, file_len;
unsigned long data_file_len;
char file_name[0x20];
char *buf;
unsigned long i;
int j;
Filename inpath(_inputPaths[0].path);
Filename outpath(_outputPath);
if (outpath.empty())
outpath.setFullPath("out/");
File ifp(inpath, "rb");
/* Get the length of the data file to use for consistency checks */
data_file_len = ifp.size();
/* Read offset and length to the file records */
file_record_off = ifp.readUint32BE();
file_record_len = ifp.readUint32BE();
/* Do a quick check to make sure the offset and length are good */
if (file_record_off + file_record_len > data_file_len) {
error("\'%s\'. file records out of bounds.", inpath.getFullPath().c_str());
}
/* Do a little consistancy check on file_record_length */
if (file_record_len % 0x28) {
error("\'%s\'. file record length not multiple of 40.", inpath.getFullPath().c_str());
}
/* Extract the files */
for (i = 0; i < file_record_len; i += 0x28) {
/* read a file record */
ifp.seek(file_record_off + i, SEEK_SET);
file_off = ifp.readUint32BE();
file_len = ifp.readUint32BE();
ifp.read(file_name, 0x20, 1);
if (!file_name[0])
error("\'%s\'. file has no name.", inpath.getFullPath().c_str());
print("extracting \'%s\'", file_name);
/* For convenience compatibility with scummvm (and case sensitive
* file systems) change the file name to lowercase.
*
* if i ever add the ability to pass flags on the command
* line, i will make this optional, but i really don't
* see the point to bothering
*/
for (j = 0; j < 0x20; j++) {
if (!file_name[j]) {
break;
}
#ifdef CHANGECASE
file_name[j] = tolower(file_name[j]);
#endif
}
if (j == 0x20) {
file_name[0x1f] = 0;
warning("\'%s\'. file name not null terminated.\n", file_name);
print("data file \'%s\' may be not a file extract_scumm_mac can extract.\n", inpath.getFullPath().c_str());
}
print(", saving as \'%s\'\n", file_name);
/* Consistency check. make sure the file data is in the file */
if (file_off + file_len > data_file_len) {
error("\'%s\'. file out of bounds.", inpath.getFullPath().c_str());
}
/* Write a file */
ifp.seek(file_off, SEEK_SET);
outpath.setFullName(file_name);
File ofp(outpath, "wb");
if (!(buf = (char *)malloc(file_len))) {
error("Could not allocate %ld bytes of memory.", file_len);
}
ifp.read(buf, 1, file_len);
ofp.write(buf, 1, file_len);
free(buf);
}
}
#ifdef STANDALONE_MAIN
int main(int argc, char *argv[]) {
return export_main(extract_scumm_mac)(argc, argv);
}
#endif