Initial commit
This commit is contained in:
249
devtools/create_kyradat/pak.cpp
Normal file
249
devtools/create_kyradat/pak.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable symbol overrides so that we can use system headers.
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "pak.h"
|
||||
|
||||
bool PAKFile::loadFile(const char *file, const bool isAmiga) {
|
||||
_isAmiga = isAmiga;
|
||||
if (!file)
|
||||
return true;
|
||||
|
||||
delete _fileList;
|
||||
_fileList = nullptr;
|
||||
|
||||
FILE *pakfile = fopen(file, "rb");
|
||||
if (!pakfile)
|
||||
return false;
|
||||
|
||||
uint32 filesize = fileSize(pakfile);
|
||||
|
||||
// TODO: get rid of temp. buffer
|
||||
uint8 *buffer = new uint8[filesize];
|
||||
assert(buffer);
|
||||
|
||||
fread(buffer, filesize, 1, pakfile);
|
||||
|
||||
fclose(pakfile);
|
||||
|
||||
const char *currentName = nullptr;
|
||||
|
||||
uint32 startoffset = _isAmiga ? READ_BE_UINT32(buffer) : READ_LE_UINT32(buffer);
|
||||
uint32 endoffset = 0;
|
||||
uint8* position = buffer + 4;
|
||||
|
||||
while (true) {
|
||||
uint32 strlgt = strlen((const char*)position);
|
||||
currentName = (const char*)position;
|
||||
|
||||
if (!(*currentName))
|
||||
break;
|
||||
|
||||
position += strlgt + 1;
|
||||
endoffset = _isAmiga ? READ_BE_UINT32(position) : READ_LE_UINT32(position);
|
||||
if (endoffset > filesize) {
|
||||
endoffset = filesize;
|
||||
} else if (endoffset == 0) {
|
||||
endoffset = filesize;
|
||||
}
|
||||
position += 4;
|
||||
|
||||
uint8 *data = new uint8[endoffset - startoffset];
|
||||
assert(data);
|
||||
memcpy(data, buffer + startoffset, endoffset - startoffset);
|
||||
addFile(currentName, data, endoffset - startoffset);
|
||||
data = nullptr;
|
||||
|
||||
if (endoffset == filesize)
|
||||
break;
|
||||
|
||||
startoffset = endoffset;
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PAKFile::saveFile(const char *file) {
|
||||
if (!_fileList)
|
||||
return true;
|
||||
|
||||
FILE *f = fopen(file, "wb");
|
||||
if (!f) {
|
||||
error("couldn't open file '%s' for writing", file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: implement error handling
|
||||
uint32 startAddr = _fileList->getTableSize()+5+4;
|
||||
static const char *zeroName = "\0\0\0\0\0";
|
||||
|
||||
uint32 curAddr = startAddr;
|
||||
for (FileList *cur = _fileList; cur; cur = cur->next) {
|
||||
if (_isAmiga)
|
||||
writeUint32BE(f, curAddr);
|
||||
else
|
||||
writeUint32LE(f, curAddr);
|
||||
fwrite(cur->filename, 1, strlen(cur->filename) + 1, f);
|
||||
curAddr += cur->size;
|
||||
}
|
||||
if (_isAmiga)
|
||||
writeUint32BE(f, curAddr);
|
||||
else
|
||||
writeUint32LE(f, curAddr);
|
||||
fwrite(zeroName, 1, 5, f);
|
||||
|
||||
for (FileList *cur = _fileList; cur; cur = cur->next)
|
||||
fwrite(cur->data, 1, cur->size, f);
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PAKFile::drawFileList() {
|
||||
FileList *cur = _fileList;
|
||||
while (cur) {
|
||||
printf("Filename: '%s' size: %d\n", cur->filename, cur->size);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool PAKFile::outputAllFiles() {
|
||||
FileList *cur = _fileList;
|
||||
while (cur) {
|
||||
FILE *file = fopen(cur->filename, "wb");
|
||||
if (!file) {
|
||||
error("couldn't open file '%s' for writing", cur->filename);
|
||||
return false;
|
||||
}
|
||||
printf("Exracting file '%s'...", cur->filename);
|
||||
if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
|
||||
printf("OK\n");
|
||||
} else {
|
||||
printf("FAILED\n");
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
fclose(file);
|
||||
cur = cur->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PAKFile::outputFileAs(const char *f, const char *fn) {
|
||||
FileList *cur = (_fileList != nullptr) ? _fileList->findEntry(f) : nullptr;
|
||||
|
||||
if (!cur) {
|
||||
error("file '%s' not found", f);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *file = fopen(fn, "wb");
|
||||
if (!file) {
|
||||
error("couldn't open file '%s' in write mode", fn);
|
||||
return false;
|
||||
}
|
||||
printf("Exracting file '%s' to file '%s'...", cur->filename, fn);
|
||||
if (fwrite(cur->data, 1, cur->size, file) == cur->size) {
|
||||
printf("OK\n");
|
||||
} else {
|
||||
printf("FAILED\n");
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8 *PAKFile::getFileData(const char *file, uint32 *size) {
|
||||
FileList *cur = (_fileList != nullptr) ? _fileList->findEntry(file) : nullptr;
|
||||
|
||||
if (!cur)
|
||||
return nullptr;
|
||||
|
||||
if (size)
|
||||
*size = cur->size;
|
||||
return cur->data;
|
||||
}
|
||||
|
||||
bool PAKFile::addFile(const char *name, const char *file) {
|
||||
if (_fileList && _fileList->findEntry(name)) {
|
||||
error("entry '%s' already exists", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *f = fopen(file, "rb");
|
||||
if (!f) {
|
||||
error("couldn't open file '%s'", file);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 filesize = fileSize(f);
|
||||
uint8 *data = new uint8[filesize];
|
||||
assert(data);
|
||||
if (fread(data, 1, filesize, f) != filesize) {
|
||||
error("couldn't read from file '%s'", file);
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
return addFile(name, data, filesize);
|
||||
}
|
||||
|
||||
bool PAKFile::addFile(const char *name, uint8 *data, uint32 size) {
|
||||
if (_fileList && _fileList->findEntry(name)) {
|
||||
error("entry '%s' already exists", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
FileList *newEntry = new FileList;
|
||||
assert(newEntry);
|
||||
newEntry->filename = new char[strlen(name)+1];
|
||||
assert(newEntry->filename);
|
||||
strncpy(newEntry->filename, name, strlen(name)+1);
|
||||
newEntry->size = size;
|
||||
newEntry->data = data;
|
||||
|
||||
if (_fileList) {
|
||||
_fileList->addEntry(newEntry);
|
||||
} else {
|
||||
_fileList = newEntry;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PAKFile::removeFile(const char *name) {
|
||||
for (FileList *cur = _fileList, *last = nullptr; cur; last = cur, cur = cur->next) {
|
||||
if (scumm_stricmp(cur->filename, name) == 0) {
|
||||
FileList *next = cur->next;
|
||||
cur->next = nullptr;
|
||||
delete cur;
|
||||
if (last)
|
||||
last->next = next;
|
||||
else
|
||||
_fileList = next;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user