Initial checking of Gob engine
svn-id: r17388
This commit is contained in:
parent
b399a052f1
commit
1758c5b211
50 changed files with 15896 additions and 2 deletions
356
gob/dataio.cpp
Normal file
356
gob/dataio.cpp
Normal file
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
** Gobliiins 1
|
||||
** Original game by CoktelVision
|
||||
**
|
||||
** Reverse engineered by Ivan Dubrov <WFrag@yandex.ru>
|
||||
**
|
||||
*/
|
||||
#include "gob/gob.h"
|
||||
#include "gob/global.h"
|
||||
#include "gob/dataio.h"
|
||||
#include "gob/debug.h"
|
||||
#include "gob/pack.h"
|
||||
|
||||
namespace Gob {
|
||||
|
||||
int16 file_write(int16 handle, char *buf, int16 size) {
|
||||
return filesHandles[handle].write(buf, size);
|
||||
}
|
||||
|
||||
int16 file_open(const char *path, File::AccessMode mode) {
|
||||
int16 i;
|
||||
|
||||
for (i = 0; i < MAX_FILES; i++) {
|
||||
if (!filesHandles[i].isOpen())
|
||||
break;
|
||||
}
|
||||
if (i == MAX_FILES)
|
||||
return -1;
|
||||
|
||||
filesHandles[i].open(path, mode);
|
||||
|
||||
if (filesHandles[i].isOpen())
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
File *file_getHandle(int16 handle) {
|
||||
return &filesHandles[handle];
|
||||
}
|
||||
|
||||
int16 data_getChunk(const char *chunkName) {
|
||||
int16 file;
|
||||
int16 slot;
|
||||
int16 chunk;
|
||||
struct ChunkDesc *dataDesc;
|
||||
|
||||
for (file = 0; file < MAX_DATA_FILES; file++) {
|
||||
if (dataFiles[file] == 0)
|
||||
return -1;
|
||||
|
||||
for (slot = 0; slot < MAX_SLOT_COUNT; slot++)
|
||||
if (chunkPos[file * MAX_SLOT_COUNT + slot] == -1)
|
||||
break;
|
||||
|
||||
if (slot == MAX_SLOT_COUNT)
|
||||
return -1;
|
||||
|
||||
dataDesc = dataFiles[file];
|
||||
for (chunk = 0; chunk < numDataChunks[file];
|
||||
chunk++, dataDesc++) {
|
||||
if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)
|
||||
continue;
|
||||
|
||||
isCurrentSlot[file * MAX_SLOT_COUNT + slot] = 0;
|
||||
chunkSize[file * MAX_SLOT_COUNT + slot] =
|
||||
dataDesc->size;
|
||||
chunkOffset[file * MAX_SLOT_COUNT + slot] =
|
||||
dataDesc->offset;
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot] = 0;
|
||||
return file * 10 + slot + 50;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char data_freeChunk(int16 handle) {
|
||||
if (handle >= 50 && handle < 100) {
|
||||
handle -= 50;
|
||||
chunkPos[(handle / 10) * MAX_SLOT_COUNT + (handle % 10)] = -1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32 data_readChunk(int16 handle, char *buf, int16 size) {
|
||||
int16 file;
|
||||
int16 slot;
|
||||
int16 i;
|
||||
int32 offset;
|
||||
|
||||
if (handle < 50 || handle >= 100)
|
||||
return -2;
|
||||
|
||||
file = (handle - 50) / 10;
|
||||
slot = (handle - 50) % 10;
|
||||
if (isCurrentSlot[file * MAX_SLOT_COUNT + slot] == 0) {
|
||||
for (i = 0; i < MAX_SLOT_COUNT; i++)
|
||||
isCurrentSlot[file * MAX_SLOT_COUNT + i] = 0;
|
||||
|
||||
offset =
|
||||
chunkOffset[file * MAX_SLOT_COUNT + slot] +
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot];
|
||||
debug(0, "seek: %ld, %ld", chunkOffset[file * MAX_SLOT_COUNT + slot], chunkPos[file * MAX_SLOT_COUNT + slot]);
|
||||
file_getHandle(dataFileHandles[file])->seek(offset, SEEK_SET);
|
||||
}
|
||||
|
||||
isCurrentSlot[file * MAX_SLOT_COUNT + slot] = 1;
|
||||
if (chunkPos[file * MAX_SLOT_COUNT + slot] + size >
|
||||
chunkSize[file * MAX_SLOT_COUNT + slot])
|
||||
size =
|
||||
chunkSize[file * MAX_SLOT_COUNT + slot] -
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot];
|
||||
|
||||
file_getHandle(dataFileHandles[file])->read(buf, size);
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot] += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
int16 data_seekChunk(int16 handle, int32 pos, int16 from) {
|
||||
int16 file;
|
||||
int16 slot;
|
||||
|
||||
if (handle < 50 || handle >= 100)
|
||||
return -1;
|
||||
|
||||
file = (handle - 50) / 10;
|
||||
slot = (handle - 50) % 10;
|
||||
isCurrentSlot[file * MAX_SLOT_COUNT + slot] = 0;
|
||||
if (from == SEEK_SET)
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot] = pos;
|
||||
else
|
||||
chunkPos[file * MAX_SLOT_COUNT + slot] += pos;
|
||||
|
||||
return chunkPos[file * MAX_SLOT_COUNT + slot];
|
||||
}
|
||||
|
||||
int32 data_getChunkSize(const char *chunkName) {
|
||||
int16 file;
|
||||
int16 chunk;
|
||||
struct ChunkDesc *dataDesc;
|
||||
int16 slot;
|
||||
int32 realSize;
|
||||
|
||||
for (file = 0; file < MAX_DATA_FILES; file++) {
|
||||
if (dataFiles[file] == 0)
|
||||
return -1;
|
||||
|
||||
dataDesc = dataFiles[file];
|
||||
for (chunk = 0; chunk < numDataChunks[file];
|
||||
chunk++, dataDesc++) {
|
||||
if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0)
|
||||
continue;
|
||||
|
||||
if (dataDesc->packed == 0) {
|
||||
packedSize = -1;
|
||||
return dataDesc->size;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < MAX_SLOT_COUNT; slot++)
|
||||
isCurrentSlot[slot] = 0;
|
||||
|
||||
file_getHandle(dataFileHandles[file])->seek(dataDesc->offset, SEEK_SET);
|
||||
realSize = file_getHandle(dataFileHandles[file])->readUint32LE();
|
||||
packedSize = dataDesc->size;
|
||||
return realSize;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void data_openDataFile(const char *src) {
|
||||
char path[128];
|
||||
int16 i;
|
||||
int16 file;
|
||||
struct ChunkDesc *dataDesc;
|
||||
|
||||
strcpy(path, src);
|
||||
for (i = 0; path[i] != '.' && path[i] != 0; i++);
|
||||
if (path[i] == 0)
|
||||
strcat(path, ".stk");
|
||||
|
||||
for (file = 0; file < MAX_DATA_FILES; file++)
|
||||
if (dataFiles[file] == 0)
|
||||
break;
|
||||
|
||||
if (file == MAX_DATA_FILES)
|
||||
error("data_dataFileOpen: Data file slots are full\n");
|
||||
dataFileHandles[file] = file_open(path);
|
||||
|
||||
if (dataFileHandles[file] == -1)
|
||||
error("data_dataFileOpen: Can't open %s data file\n", path);
|
||||
|
||||
numDataChunks[file] = file_getHandle(dataFileHandles[file])->readUint16LE();
|
||||
|
||||
debug(0, "DataChunks: %d [for %s]", numDataChunks[file], path);
|
||||
|
||||
dataFiles[file] = dataDesc =
|
||||
(struct ChunkDesc *)malloc(sizeof(struct ChunkDesc) *
|
||||
numDataChunks[file]);
|
||||
|
||||
for (i = 0; i < numDataChunks[file]; i++) {
|
||||
file_getHandle(dataFileHandles[file])->read(dataDesc[i].chunkName, 13);
|
||||
dataDesc[i].size = file_getHandle(dataFileHandles[file])->readUint32LE();
|
||||
dataDesc[i].offset = file_getHandle(dataFileHandles[file])->readUint32LE();
|
||||
dataDesc[i].packed = file_getHandle(dataFileHandles[file])->readByte();
|
||||
}
|
||||
|
||||
for (i = 0; i < numDataChunks[file]; i++)
|
||||
debug(0, "%d: %s %d", i, dataDesc[i].chunkName, dataDesc[i].size);
|
||||
|
||||
for (i = 0; i < MAX_SLOT_COUNT; i++)
|
||||
chunkPos[file * MAX_SLOT_COUNT + i] = -1;
|
||||
|
||||
}
|
||||
|
||||
void data_closeDataFile() {
|
||||
int16 file;
|
||||
for (file = MAX_DATA_FILES - 1; file >= 0; file--) {
|
||||
if (dataFiles[file] != 0) {
|
||||
free((char *)dataFiles[file]);
|
||||
dataFiles[file] = 0;
|
||||
file_getHandle(dataFileHandles[file])->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *data_getUnpackedData(const char *name) {
|
||||
int32 realSize;
|
||||
int16 chunk;
|
||||
char *unpackBuf;
|
||||
char *packBuf;
|
||||
char *ptr;
|
||||
int32 sizeLeft;
|
||||
|
||||
realSize = data_getChunkSize(name);
|
||||
if (packedSize == -1 || realSize == -1)
|
||||
return 0;
|
||||
|
||||
chunk = data_getChunk(name);
|
||||
if (chunk == -1)
|
||||
return 0;
|
||||
|
||||
unpackBuf = (char *)malloc(realSize);
|
||||
if (unpackBuf == 0)
|
||||
return 0;
|
||||
|
||||
packBuf = (char *)malloc(packedSize);
|
||||
if (packBuf == 0) {
|
||||
free(unpackBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sizeLeft = packedSize;
|
||||
ptr = packBuf;
|
||||
while (sizeLeft > 0x4000) {
|
||||
data_readChunk(chunk, (char *)ptr, 0x4000);
|
||||
sizeLeft -= 0x4000;
|
||||
ptr += 0x4000;
|
||||
}
|
||||
data_readChunk(chunk, (char *)ptr, sizeLeft);
|
||||
data_freeChunk(chunk);
|
||||
unpackData((char *)packBuf, (char *)unpackBuf);
|
||||
free(packBuf);
|
||||
return unpackBuf;
|
||||
}
|
||||
|
||||
void data_closeData(int16 handle) {
|
||||
if (data_freeChunk(handle) != 0)
|
||||
file_getHandle(handle)->close();
|
||||
}
|
||||
|
||||
int16 data_openData(const char *path, File::AccessMode mode) {
|
||||
int16 handle;
|
||||
|
||||
if (mode != File::kFileReadMode)
|
||||
return file_open(path, mode);
|
||||
|
||||
handle = data_getChunk(path);
|
||||
if (handle >= 0)
|
||||
return handle;
|
||||
|
||||
return file_open(path, mode);
|
||||
}
|
||||
|
||||
int32 data_readData(int16 handle, char *buf, int16 size) {
|
||||
int32 res;
|
||||
|
||||
res = data_readChunk(handle, buf, size);
|
||||
if (res >= 0)
|
||||
return res;
|
||||
|
||||
return file_getHandle(handle)->read(buf, size);
|
||||
}
|
||||
|
||||
void data_seekData(int16 handle, int32 pos, int16 from) {
|
||||
int32 resPos;
|
||||
|
||||
resPos = data_seekChunk(handle, pos, from);
|
||||
if (resPos != -1)
|
||||
return;
|
||||
|
||||
file_getHandle(handle)->seek(pos, from);
|
||||
}
|
||||
|
||||
int32 data_getDataSize(const char *name) {
|
||||
char buf[128];
|
||||
int32 chunkSz;
|
||||
struct stat statBuf;
|
||||
|
||||
strcpy(buf, name);
|
||||
chunkSz = data_getChunkSize(buf);
|
||||
if (chunkSz >= 0)
|
||||
return chunkSz;
|
||||
|
||||
if (stat(buf, &statBuf) == -1)
|
||||
error("data_getDataSize: Can't find data (%s)", name);
|
||||
|
||||
return statBuf.st_size;
|
||||
}
|
||||
|
||||
char *data_getData(const char *path) {
|
||||
char *data;
|
||||
char *ptr;
|
||||
int32 size;
|
||||
int16 handle;
|
||||
|
||||
data = data_getUnpackedData(path);
|
||||
if (data != 0)
|
||||
return data;
|
||||
|
||||
size = data_getDataSize(path);
|
||||
data = (char *)malloc(size);
|
||||
if (data == 0)
|
||||
return 0;
|
||||
|
||||
handle = data_openData(path);
|
||||
|
||||
ptr = data;
|
||||
while (size > 0x4000) {
|
||||
data_readData(handle, (char *)ptr, 0x4000);
|
||||
size -= 0x4000;
|
||||
ptr += 0x4000;
|
||||
}
|
||||
data_readData(handle, (char *)ptr, size);
|
||||
data_closeData(handle);
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
char *data_getSmallData(const char *path) {
|
||||
return data_getData(path);
|
||||
}
|
||||
|
||||
} // End of namespace Gob
|
Loading…
Add table
Add a link
Reference in a new issue