diff options
-rw-r--r-- | engines/sci/engine/kfile.cpp | 112 | ||||
-rw-r--r-- | engines/sci/include/sciresource.h | 119 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 4 | ||||
-rw-r--r-- | engines/sci/scicore/decompress0.cpp | 22 | ||||
-rw-r--r-- | engines/sci/scicore/decompress01.cpp | 12 | ||||
-rw-r--r-- | engines/sci/scicore/decompress1.cpp | 20 | ||||
-rw-r--r-- | engines/sci/scicore/decompress11.cpp | 17 | ||||
-rw-r--r-- | engines/sci/scicore/resource.cpp | 320 | ||||
-rw-r--r-- | engines/sci/scicore/resource_map.cpp | 137 | ||||
-rw-r--r-- | engines/sci/scicore/resource_patch.cpp | 169 | ||||
-rw-r--r-- | engines/sci/scicore/tools.cpp | 84 |
11 files changed, 399 insertions, 617 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 291fda4208..b66e8fd272 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -58,6 +58,30 @@ static FILE *f_open_mirrored(state_t *s, char *fname) { char *buf = NULL; int fsize; + + printf("f_open_mirrored(%s)\n", fname); +#if 0 + // TODO/FIXME: Use s->resource_dir to locate the file??? + File file; + if (!file.open(fname)) + return NULL; + + fsize = file.size(); + if (fsize > 0) { + buf = (char *)sci_malloc(fsize); + file.read(buf, fsize); + } + + file.close(); + + .... + copy the file to a savegame -> only makes sense to perform this change + if we at the same time change the code for loading files to look among the + savestates, and also change *all* file writing code to write to savestates, + as it should + ... +#endif + chdir(s->resource_dir); fd = sci_open(fname, O_RDONLY | O_BINARY); if (!IS_VALID_FD(fd)) { @@ -155,20 +179,28 @@ reg_t kFOpen(state_t *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -void file_close(state_t *s, int handle) { - SCIkdebug(SCIkFILE, "Closing file %d\n", handle); - +static FILE *getFileFromHandle(state_t *s, int handle) { if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt to close file handle 0\n"); - return; + SCIkwarn(SCIkERROR, "Attempt to use file handle 0\n"); + return 0; } if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt to close invalid/unused file handle %d\n", handle); - return; + SCIkwarn(SCIkERROR, "Attempt to use invalid/unused file handle %d\n", handle); + return 0; } + + return s->file_handles[handle]; +} + +void file_close(state_t *s, int handle) { + SCIkdebug(SCIkFILE, "Closing file %d\n", handle); - fclose(s->file_handles[handle]); + FILE *f = getFileFromHandle(s, handle); + if (!f) + return; + + fclose(f); s->file_handles[handle] = NULL; } @@ -181,33 +213,17 @@ reg_t kFClose(state_t *s, int funct_nr, int argc, reg_t *argv) { void fputs_wrapper(state_t *s, int handle, int size, char *data) { SCIkdebug(SCIkFILE, "FPuts'ing \"%s\" to handle %d\n", data, handle); - if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt to write to file handle 0\n"); - return; - } - - if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt to write to invalid/unused file handle %d\n", handle); - return; - } - - fwrite(data, 1, size, s->file_handles[handle]); + FILE *f = getFileFromHandle(s, handle); + if (f) + fwrite(data, 1, size, f); } void fwrite_wrapper(state_t *s, int handle, char *data, int length) { SCIkdebug(SCIkFILE, "fwrite()'ing \"%s\" to handle %d\n", data, handle); - if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt to write to file handle 0\n"); - return; - } - - if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt to write to invalid/unused file handle %d\n", handle); - return; - } - - fwrite(data, 1, length, s->file_handles[handle]); + FILE *f = getFileFromHandle(s, handle); + if (f) + fwrite(data, 1, length, f); } reg_t kFPuts(state_t *s, int funct_nr, int argc, reg_t *argv) { @@ -221,17 +237,11 @@ reg_t kFPuts(state_t *s, int funct_nr, int argc, reg_t *argv) { static void fgets_wrapper(state_t *s, char *dest, int maxsize, int handle) { SCIkdebug(SCIkFILE, "FGets'ing %d bytes from handle %d\n", maxsize, handle); - if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt to read from file handle 0\n"); + FILE *f = getFileFromHandle(s, handle); + if (!f) return; - } - if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt to read from invalid/unused file handle %d\n", handle); - return; - } - - fgets(dest, maxsize, s->file_handles[handle]); + fgets(dest, maxsize, f); SCIkdebug(SCIkFILE, "FGets'ed \"%s\"\n", dest); } @@ -239,31 +249,19 @@ static void fgets_wrapper(state_t *s, char *dest, int maxsize, int handle) { static void fread_wrapper(state_t *s, char *dest, int bytes, int handle) { SCIkdebug(SCIkFILE, "fread()'ing %d bytes from handle %d\n", bytes, handle); - if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt to read from file handle 0\n"); + FILE *f = getFileFromHandle(s, handle); + if (!f) return; - } - - if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt to read from invalid/unused file handle %d\n", handle); - return; - } - s->r_acc = make_reg(0, fread(dest, 1, bytes, s->file_handles[handle])); + s->r_acc = make_reg(0, fread(dest, 1, bytes, f)); } static void fseek_wrapper(state_t *s, int handle, int offset, int whence) { - if (handle == 0) { - SCIkwarn(SCIkERROR, "Attempt seek on file handle 0\n"); - return; - } - - if ((handle >= s->file_handles_nr) || (s->file_handles[handle] == NULL)) { - SCIkwarn(SCIkERROR, "Attempt seek on invalid/unused file handle %d\n", handle); + FILE *f = getFileFromHandle(s, handle); + if (!f) return; - } - s->r_acc = make_reg(0, fseek(s->file_handles[handle], offset, whence)); + s->r_acc = make_reg(0, fseek(f, offset, whence)); } static char *_chdir_savedir(state_t *s) { diff --git a/engines/sci/include/sciresource.h b/engines/sci/include/sciresource.h index c75e295ca9..fc9bec41e8 100644 --- a/engines/sci/include/sciresource.h +++ b/engines/sci/include/sciresource.h @@ -29,6 +29,9 @@ /*#define _SCI_RESOURCE_DEBUG */ /*#define _SCI_DECOMPRESS_DEBUG*/ +#include "common/stream.h" +#include "common/str.h" + #include "sci/include/resource.h" #include "sci/include/versions.h" @@ -89,7 +92,6 @@ #define SCI_VERSION_1 SCI_VERSION_1_EARLY #define RESSOURCE_TYPE_DIRECTORY 0 -#define RESSOURCE_TYPE_AUDIO_DIRECTORY 1 #define RESSOURCE_TYPE_VOLUME 2 #define RESSOURCE_TYPE_EXTERNAL_MAP 3 #define RESSOURCE_TYPE_INTERNAL_MAP 4 @@ -127,19 +129,10 @@ typedef struct resource_index_struct resource_index_t; struct ResourceSource { int source_type; - int scanned; - union { - struct { - char *name; - int volume_number; - } file; - struct { - char *name; - } dir; - struct { - struct _resource_struct *resource; - } internal_map; - } location; + bool scanned; + Common::String location_name; // FIXME: Replace by FSNode ? + Common::String location_dir_name; // FIXME: Get rid of this again, only a temporary HACK! + int volume_number; ResourceSource *associated_map; ResourceSource *next; }; @@ -184,45 +177,38 @@ struct ResourceManager { int memory_locked; /* Amount of resource bytes in locked memory */ int memory_lru; /* Amount of resource bytes under LRU control */ - char *resource_path; /* Path to the resource and patch files */ - resource_t *lru_first, *lru_last; /* Pointers to the first and last LRU queue entries */ /* LRU queue: lru_first points to the most recent entry */ + +public: + /** + * Creates a new FreeSCI resource manager. + * @param version The SCI version to look for; use SCI_VERSION_AUTODETECT + * in the default case. + * @param maxMemory Maximum number of bytes to allow allocated for resources + * + * @note maxMemory will not be interpreted as a hard limit, only as a restriction + * for resources which are not explicitly locked. However, a warning will be + * issued whenever this limit is exceeded. + */ + ResourceManager(int version, int maxMemory); + ~ResourceManager(); }; /**** FUNCTION DECLARATIONS ****/ /**--- New Resource manager ---**/ -ResourceManager * -scir_new_resource_manager(char *dir, int version, int maxMemory); -/* Creates a new FreeSCI resource manager -** Parameters: (char *) dir: Path to the resource and patch files (not modified or freed -** by the resource manager) -** (int) version: The SCI version to look for; use SCI_VERSION_AUTODETECT -** in the default case. -** (int) maxMemory: Maximum number of bytes to allow allocated for resources -** Returns : (ResourceManager *) A newly allocated resource manager -** maxMemory will not be interpreted as a hard limit, only as a restriction for resources -** which are not explicitly locked. However, a warning will be issued whenever this limit -** is exceeded. -*/ - -ResourceSource * -scir_add_patch_dir(ResourceManager *mgr, int type, char *path); +ResourceSource *scir_add_patch_dir(ResourceManager *mgr, const char *path); /* Add a path to the resource manager's list of sources. ** Parameters: (ResourceManager *) mgr: The resource manager to look up in -** (int) dirtype: The type of patch directory to add, -** either RESSOURCE_TYPE_DIRECTORY or RESSOURCE_TYPE_AUDIO_DIRECTORY -** (char *) path: The path to add +** (const char *) path: The path to add ** Returns: A pointer to the added source structure, or NULL if an error occurred. */ -ResourceSource * -scir_get_volume(ResourceManager *mgr, ResourceSource *map, int volume_nr); +ResourceSource *scir_get_volume(ResourceManager *mgr, ResourceSource *map, int volume_nr); -ResourceSource * -scir_add_volume(ResourceManager *mgr, ResourceSource *map, char *filename, +ResourceSource *scir_add_volume(ResourceManager *mgr, ResourceSource *map, const char *filename, int number, int extended_addressing); /* Add a volume to the resource manager's list of sources. ** Parameters: (ResourceManager *) mgr: The resource manager to look up in @@ -233,19 +219,10 @@ scir_add_volume(ResourceManager *mgr, ResourceSource *map, char *filename, ** Returns: A pointer to the added source structure, or NULL if an error occurred. */ -ResourceSource * -scir_add_external_map(ResourceManager *mgr, char *file_name); +ResourceSource *scir_add_external_map(ResourceManager *mgr, const char *file_name); /* Add an external (i.e. separate file) map resource to the resource manager's list of sources. ** Parameters: (ResourceManager *) mgr: The resource manager to look up in -** (char *) file_name: The name of the volume to add -** Returns: A pointer to the added source structure, or NULL if an error occurred. -*/ - -ResourceSource * -scir_add_internal_map(ResourceManager *mgr, resource_t *map); -/* Add an internal (i.e. a resource) map resource to the resource manager's list of sources. -** Parameters: (ResourceManager *) mgr: The resource manager to look up in -** (char *) file_name: The name of the volume to add +** (const char *) file_name: The name of the volume to add ** Returns: A pointer to the added source structure, or NULL if an error occurred. */ @@ -294,17 +271,9 @@ scir_test_resource(ResourceManager *mgr, int type, int number); ** Use scir_find_resource() if you want to use the data contained in the resource. */ -void -scir_free_resource_manager(ResourceManager *mgr); -/* Frees a resource manager and all memory handled by it -** Parameters: (ResourceManager *) mgr: The Manager to free -** Returns : (void) -*/ - /**--- Resource map decoding functions ---*/ -int -sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **resources, int *resource_nr_p, int *sci_version); +int sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **resources, int *resource_nr_p, int *sci_version); /* Reads the SCI0 resource.map file from a local directory ** Parameters: (char *) path: (unused) ** (resource_t **) resources: Pointer to a pointer @@ -317,8 +286,7 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise */ -int -sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource *vol, +int sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource *vol, resource_t **resource_p, int *resource_nr_p, int *sci_version); /* Reads the SCI1 resource.map file from a local directory ** Parameters: (char *) path: (unused) @@ -352,8 +320,7 @@ sci1_sprintf_patch_file_name(char *string, resource_t *res); ** Returns : (void) */ -int -sci0_read_resource_patches(ResourceSource *source, resource_t **resources, int *resource_nr_p); +int sci0_read_resource_patches(ResourceSource *source, resource_t **resources, int *resource_nr_p); /* Reads SCI0 patch files from a local directory ** Parameters: (char *) path: (unused) ** (resource_t **) resources: Pointer to a pointer @@ -365,8 +332,7 @@ sci0_read_resource_patches(ResourceSource *source, resource_t **resources, int * ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise */ -int -sci1_read_resource_patches(ResourceSource *source, resource_t **resources, int *resource_nr_p); +int sci1_read_resource_patches(ResourceSource *source, resource_t **resources, int *resource_nr_p); /* Reads SCI1 patch files from a local directory ** Parameters: (char *) path: (unused) ** (resource_t **) resources: Pointer to a pointer @@ -382,39 +348,39 @@ sci1_read_resource_patches(ResourceSource *source, resource_t **resources, int * /**--- Decompression functions ---**/ -int decompress0(resource_t *result, int resh, int sci_version); +int decompress0(resource_t *result, Common::ReadStream &stream, int sci_version); /* Decrypts resource data and stores the result for SCI0-style compression. ** Parameters : result: The resource_t the decompressed data is stored in. -** resh : File handle of the resource file +** stream: Stream of the resource file ** sci_version : Actual SCI resource version ** Returns : (int) 0 on success, one of SCI_ERROR_* if a problem was ** encountered. */ -int decompress01(resource_t *result, int resh, int sci_version); +int decompress01(resource_t *result, Common::ReadStream &stream, int sci_version); /* Decrypts resource data and stores the result for SCI01-style compression. ** Parameters : result: The resource_t the decompressed data is stored in. -** resh : File handle of the resource file +** stream: Stream of the resource file ** sci_version : Actual SCI resource version ** Returns : (int) 0 on success, one of SCI_ERROR_* if a problem was ** encountered. */ -int decompress1(resource_t *result, int resh, int sci_version); +int decompress1(resource_t *result, Common::ReadStream &stream, int sci_version); /* Decrypts resource data and stores the result for SCI1.1-style compression. ** Parameters : result: The resource_t the decompressed data is stored in. ** sci_version : Actual SCI resource version -** resh : File handle of the resource file +** stream: Stream of the resource file ** Returns : (int) 0 on success, one of SCI_ERROR_* if a problem was ** encountered. */ -int decompress11(resource_t *result, int resh, int sci_version); +int decompress11(resource_t *result, Common::ReadStream &stream, int sci_version); /* Decrypts resource data and stores the result for SCI1.1-style compression. ** Parameters : result: The resource_t the decompressed data is stored in. ** sci_version : Actual SCI resource version -** resh : File handle of the resource file +** stream: Stream of the resource file ** Returns : (int) 0 on success, one of SCI_ERROR_* if a problem was ** encountered. */ @@ -437,10 +403,10 @@ byte *pic_reorder(byte *inbuffer, int dsize); /*--- Internal helper functions ---*/ void -_scir_free_resources(resource_t *resources, int resourcesNr); +_scir_free_resources(resource_t *resources, int _resourcesNr); /* Frees a block of resources and associated data ** Parameters: (resource_t *) resources: The resources to free -** (int) resourcesNr: Number of resources in the block +** (int) _resourcesNr: Number of resources in the block ** Returns : (void) */ @@ -457,8 +423,7 @@ _scir_find_resource_unsorted(resource_t *res, int res_nr, int type, int number); ** Returns : (resource_t) The matching resource entry, or NULL if not found */ -void -_scir_add_altsource(resource_t *res, ResourceSource *source, unsigned int file_offset); +void _scir_add_altsource(resource_t *res, ResourceSource *source, unsigned int file_offset); /* Adds an alternative source to a resource ** Parameters: (resource_t *) res: The resource to add to ** (ResourceSource *) source: The source of the resource diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9de4942bb8..50bf26d51c 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -199,7 +199,7 @@ Common::Error SciEngine::go() { char resource_dir[MAXPATHLEN+1] = ""; getcwd(resource_dir, MAXPATHLEN); /* Store resource directory */ - resmgr = scir_new_resource_manager(resource_dir, res_version, 256 * 1024); + resmgr = new ResourceManager(res_version, 256 * 1024); if (!resmgr) { printf("No resources found in '%s'.\nAborting...\n", @@ -300,7 +300,7 @@ Common::Error SciEngine::go() { free(gamestate->work_dir); free(gamestate); - scir_free_resource_manager(resmgr); + delete resmgr; close_console_file(); diff --git a/engines/sci/scicore/decompress0.cpp b/engines/sci/scicore/decompress0.cpp index f65b7f9dd6..0c829ad3d8 100644 --- a/engines/sci/scicore/decompress0.cpp +++ b/engines/sci/scicore/decompress0.cpp @@ -225,18 +225,18 @@ int decrypt2(guint8* dest, guint8* src, int length, int complength) /* Carl Muckenhoupt's decompression code ends here */ /***************************************************************************/ -int sci0_get_compression_method(int resh) { +int sci0_get_compression_method(Common::ReadStream &stream) { guint16 compressedLength; guint16 compressionMethod; guint16 result_size; /* Dummy variable */ - if (read(resh, &result_size, 2) != 2) + if (stream.read(&result_size, 2) != 2) return SCI_ERROR_IO_ERROR; - if ((read(resh, &compressedLength, 2) != 2) || - (read(resh, &result_size, 2) != 2) || - (read(resh, &compressionMethod, 2) != 2)) + if ((stream.read(&compressedLength, 2) != 2) || + (stream.read(&result_size, 2) != 2) || + (stream.read(&compressionMethod, 2) != 2)) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -247,13 +247,13 @@ int sci0_get_compression_method(int resh) { } -int decompress0(resource_t *result, int resh, int sci_version) { +int decompress0(resource_t *result, Common::ReadStream &stream, int sci_version) { guint16 compressedLength; guint16 compressionMethod; guint16 result_size; guint8 *buffer; - if (read(resh, &(result->id), 2) != 2) + if (stream.read(&(result->id), 2) != 2) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -265,9 +265,9 @@ int decompress0(resource_t *result, int resh, int sci_version) { if ((result->number > sci_max_resource_nr[sci_version]) || (result->type > sci_invalid_resource)) return SCI_ERROR_DECOMPRESSION_INSANE; - if ((read(resh, &compressedLength, 2) != 2) || - (read(resh, &result_size, 2) != 2) || - (read(resh, &compressionMethod, 2) != 2)) + if ((stream.read(&compressedLength, 2) != 2) || + (stream.read(&result_size, 2) != 2) || + (stream.read(&compressionMethod, 2) != 2)) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -293,7 +293,7 @@ int decompress0(resource_t *result, int resh, int sci_version) { buffer = (guint8*)sci_malloc(compressedLength); result->data = (unsigned char*)sci_malloc(result->size); - if (read(resh, buffer, compressedLength) != compressedLength) { + if (stream.read(buffer, compressedLength) != compressedLength) { free(result->data); free(buffer); return SCI_ERROR_IO_ERROR; diff --git a/engines/sci/scicore/decompress01.cpp b/engines/sci/scicore/decompress01.cpp index 6f00bdfa73..e3219d3a5f 100644 --- a/engines/sci/scicore/decompress01.cpp +++ b/engines/sci/scicore/decompress01.cpp @@ -489,12 +489,12 @@ byte *view_reorder(byte *inbuffer, int dsize) { -int decompress01(resource_t *result, int resh, int sci_version) { +int decompress01(resource_t *result, Common::ReadStream &stream, int sci_version) { guint16 compressedLength, result_size; guint16 compressionMethod; guint8 *buffer; - if (read(resh, &(result->id), 2) != 2) + if (stream.read(&(result->id), 2) != 2) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -507,9 +507,9 @@ int decompress01(resource_t *result, int resh, int sci_version) { if ((result->number > sci_max_resource_nr[sci_version] || (result->type > sci_invalid_resource))) return SCI_ERROR_DECOMPRESSION_INSANE; - if ((read(resh, &compressedLength, 2) != 2) || - (read(resh, &result_size, 2) != 2) || - (read(resh, &compressionMethod, 2) != 2)) + if ((stream.read(&compressedLength, 2) != 2) || + (stream.read(&result_size, 2) != 2) || + (stream.read(&compressionMethod, 2) != 2)) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -538,7 +538,7 @@ int decompress01(resource_t *result, int resh, int sci_version) { buffer = (guint8*)sci_malloc(compressedLength); result->data = (unsigned char*)sci_malloc(result->size); - if (read(resh, buffer, compressedLength) != compressedLength) { + if (stream.read(buffer, compressedLength) != compressedLength) { free(result->data); free(buffer); return SCI_ERROR_IO_ERROR; diff --git a/engines/sci/scicore/decompress1.cpp b/engines/sci/scicore/decompress1.cpp index 4f480fda1e..e231c24f9d 100644 --- a/engines/sci/scicore/decompress1.cpp +++ b/engines/sci/scicore/decompress1.cpp @@ -145,7 +145,6 @@ static int decrypt4_hdyn(byte *dest, int length, struct bit_read_struct *reader) { int mode, length_param, value, val_length, val_distance; int write_pos = 0; - int M[] = {0x07, 0x08, 0x0A, 0x0E, 0x16, 0x26, 0x46, 0x86, 0x106}; CALLC(mode = getbits(reader, 8)); CALLC(length_param = getbits(reader, 8)); @@ -185,7 +184,7 @@ decrypt4_hdyn(byte *dest, int length, struct bit_read_struct *reader) { else { int length_bonus; - val_length = M[value - 7] + 2; + val_length = 1<<(value - 7) + 8; CALLC(length_bonus = getbits(reader, value - 7)); val_length += length_bonus; } @@ -272,16 +271,15 @@ decrypt4(guint8* dest, guint8* src, int length, int complength) { void decryptinit3(void); int decrypt3(guint8* dest, guint8* src, int length, int complength); -int decompress1(resource_t *result, int resh, int early); -int decompress1(resource_t *result, int resh, int sci_version) { +int decompress1(resource_t *result, Common::ReadStream &stream, int sci_version) { guint16 compressedLength; guint16 compressionMethod, result_size; guint8 *buffer; guint8 tempid; if (sci_version == SCI_VERSION_1_EARLY) { - if (read(resh, &(result->id), 2) != 2) + if (stream.read(&(result->id), 2) != 2) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -294,13 +292,13 @@ int decompress1(resource_t *result, int resh, int sci_version) { if ((result->number >= sci_max_resource_nr[SCI_VERSION_1_LATE]) || (result->type > sci_invalid_resource)) return SCI_ERROR_DECOMPRESSION_INSANE; } else { - if (read(resh, &tempid, 1) != 1) + if (stream.read(&tempid, 1) != 1) return SCI_ERROR_IO_ERROR; result->id = tempid; result->type = result->id & 0x7f; - if (read(resh, &(result->number), 2) != 2) + if (stream.read(&(result->number), 2) != 2) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -310,9 +308,9 @@ int decompress1(resource_t *result, int resh, int sci_version) { return SCI_ERROR_DECOMPRESSION_INSANE; } - if ((read(resh, &compressedLength, 2) != 2) || - (read(resh, &result_size, 2) != 2) || - (read(resh, &compressionMethod, 2) != 2)) + if ((stream.read(&compressedLength, 2) != 2) || + (stream.read(&result_size, 2) != 2) || + (stream.read(&compressionMethod, 2) != 2)) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -337,7 +335,7 @@ int decompress1(resource_t *result, int resh, int sci_version) { buffer = (guint8*)sci_malloc(compressedLength); result->data = (unsigned char*)sci_malloc(result->size); - if (read(resh, buffer, compressedLength) != compressedLength) { + if (stream.read(buffer, compressedLength) != compressedLength) { free(result->data); free(buffer); return SCI_ERROR_IO_ERROR; diff --git a/engines/sci/scicore/decompress11.cpp b/engines/sci/scicore/decompress11.cpp index be4fa9794c..99b1b9e22e 100644 --- a/engines/sci/scicore/decompress11.cpp +++ b/engines/sci/scicore/decompress11.cpp @@ -34,7 +34,7 @@ void decryptinit3(void); int decrypt3(guint8* dest, guint8* src, int length, int complength); int decrypt4(guint8* dest, guint8* src, int length, int complength); -int decompress11(resource_t *result, int resh, int sci_version) { +int decompress11(resource_t *result, Common::ReadStream &stream, int sci_version) { guint16 compressedLength; guint16 compressionMethod, result_size; guint8 *buffer; @@ -42,13 +42,13 @@ int decompress11(resource_t *result, int resh, int sci_version) { DDEBUG("d1"); - if (read(resh, &tempid, 1) != 1) + if (stream.read(&tempid, 1) != 1) return SCI_ERROR_IO_ERROR; result->id = tempid; result->type = result->id & 0x7f; - if (read(resh, &(result->number), 2) != 2) + if (stream.read(&(result->number), 2) != 2) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -57,9 +57,9 @@ int decompress11(resource_t *result, int resh, int sci_version) { if ((result->type > sci_invalid_resource)) return SCI_ERROR_DECOMPRESSION_INSANE; - if ((read(resh, &compressedLength, 2) != 2) || - (read(resh, &result_size, 2) != 2) || - (read(resh, &compressionMethod, 2) != 2)) + if ((stream.read(&compressedLength, 2) != 2) || + (stream.read(&result_size, 2) != 2) || + (stream.read(&compressionMethod, 2) != 2)) return SCI_ERROR_IO_ERROR; #ifdef WORDS_BIGENDIAN @@ -88,15 +88,14 @@ int decompress11(resource_t *result, int resh, int sci_version) { buffer = (guint8*)sci_malloc(compressedLength); result->data = (unsigned char*)sci_malloc(result->size); - if (read(resh, buffer, compressedLength) != compressedLength) { + if (stream.read(buffer, compressedLength) != compressedLength) { free(result->data); free(buffer); return SCI_ERROR_IO_ERROR; }; if (!(compressedLength & 1)) { /* Align */ - int foo; - read(resh, &foo, 1); + stream.readByte(); } #ifdef _SCI_DECOMPRESS_DEBUG diff --git a/engines/sci/scicore/resource.cpp b/engines/sci/scicore/resource.cpp index d23713f556..d6064abf25 100644 --- a/engines/sci/scicore/resource.cpp +++ b/engines/sci/scicore/resource.cpp @@ -25,6 +25,8 @@ /* Resource library */ +#include "common/archive.h" +#include "common/file.h" #include "common/util.h" #include "sci/include/sci_memory.h" @@ -88,7 +90,7 @@ const char *sci_resource_type_suffixes[] = {"v56", "p56", "scr", "tex", "snd", int resourcecmp(const void *first, const void *second); -typedef int decomp_funct(resource_t *result, int resh, int sci_version); +typedef int decomp_funct(resource_t *result, Common::ReadStream &stream, int sci_version); typedef void patch_sprintf_funct(char *string, resource_t *res); static decomp_funct *decompressors[] = { @@ -136,8 +138,7 @@ int resourcecmp(const void *first, const void *second) { /*-- Resmgr helper functions --*/ /*-----------------------------*/ -void -_scir_add_altsource(resource_t *res, ResourceSource *source, unsigned int file_offset) { +void _scir_add_altsource(resource_t *res, ResourceSource *source, unsigned int file_offset) { resource_altsource_t *rsrc = (resource_altsource_t*)sci_malloc(sizeof(resource_altsource_t)); rsrc->next = res->alt_sources; @@ -146,8 +147,7 @@ _scir_add_altsource(resource_t *res, ResourceSource *source, unsigned int file_o res->alt_sources = rsrc; } -resource_t * -_scir_find_resource_unsorted(resource_t *res, int res_nr, int type, int number) { +resource_t *_scir_find_resource_unsorted(resource_t *res, int res_nr, int type, int number) { int i; for (i = 0; i < res_nr; i++) if (res[i].number == number && res[i].type == type) @@ -159,64 +159,57 @@ _scir_find_resource_unsorted(resource_t *res, int res_nr, int type, int number) /** Resource source list management **/ /*-----------------------------------*/ -ResourceSource * -scir_add_external_map(ResourceManager *mgr, char *file_name) { - ResourceSource *newsrc = (ResourceSource *) - malloc(sizeof(ResourceSource)); +ResourceSource *scir_add_external_map(ResourceManager *mgr, const char *file_name) { + ResourceSource *newsrc = new ResourceSource(); /* Add the new source to the SLL of sources */ newsrc->next = mgr->_sources; mgr->_sources = newsrc; newsrc->source_type = RESSOURCE_TYPE_EXTERNAL_MAP; - newsrc->location.file.name = strdup(file_name); - newsrc->scanned = 0; + newsrc->location_name = file_name; + newsrc->scanned = false; newsrc->associated_map = NULL; return newsrc; } -ResourceSource * -scir_add_volume(ResourceManager *mgr, ResourceSource *map, char *filename, +ResourceSource *scir_add_volume(ResourceManager *mgr, ResourceSource *map, const char *filename, int number, int extended_addressing) { - ResourceSource *newsrc = (ResourceSource *) - malloc(sizeof(ResourceSource)); + ResourceSource *newsrc = new ResourceSource(); /* Add the new source to the SLL of sources */ newsrc->next = mgr->_sources; mgr->_sources = newsrc; newsrc->source_type = RESSOURCE_TYPE_VOLUME; - newsrc->scanned = 0; - newsrc->location.file.name = strdup(filename); - newsrc->location.file.volume_number = number; + newsrc->scanned = false; + newsrc->location_name = filename; + newsrc->volume_number = number; newsrc->associated_map = map; return 0; } -ResourceSource * -scir_add_patch_dir(ResourceManager *mgr, int type, char *dirname) { - ResourceSource *newsrc = (ResourceSource *) - malloc(sizeof(ResourceSource)); +ResourceSource *scir_add_patch_dir(ResourceManager *mgr, const char *dirname) { + ResourceSource *newsrc = new ResourceSource(); /* Add the new source to the SLL of sources */ newsrc->next = mgr->_sources; mgr->_sources = newsrc; newsrc->source_type = RESSOURCE_TYPE_DIRECTORY; - newsrc->scanned = 0; - newsrc->location.dir.name = strdup(dirname); + newsrc->scanned = false; + newsrc->location_name = dirname; return 0; } -ResourceSource * -scir_get_volume(ResourceManager *mgr, ResourceSource *map, int volume_nr) { +ResourceSource *scir_get_volume(ResourceManager *mgr, ResourceSource *map, int volume_nr) { ResourceSource *seeker = mgr->_sources; while (seeker) { if (seeker->source_type == RESSOURCE_TYPE_VOLUME && seeker->associated_map == map && - seeker->location.file.volume_number == volume_nr) + seeker->volume_number == volume_nr) return seeker; seeker = seeker->next; } @@ -229,34 +222,25 @@ scir_get_volume(ResourceManager *mgr, ResourceSource *map, int volume_nr) { /*------------------------------------------------*/ static void -_scir_init_trivial(ResourceManager *mgr) { - mgr->_resourcesNr = 0; - mgr->_resources = (resource_t*)sci_malloc(1); -} - - -static void -_scir_load_from_patch_file(int fh, resource_t *res, char *filename) { +_scir_load_from_patch_file(Common::File &file, resource_t *res, char *filename) { unsigned int really_read; res->data = (unsigned char*)sci_malloc(res->size); - really_read = read(fh, res->data, res->size); + really_read = file.read(res->data, res->size); if (really_read < res->size) { - sciprintf("Error: Read %d bytes from %s but expected %d!\n", + error("Read %d bytes from %s but expected %d!", really_read, filename, res->size); - exit(1); } res->status = SCI_STATUS_ALLOCATED; } static void -_scir_load_resource(ResourceManager *mgr, resource_t *res, int protect) { +_scir_load_resource(ResourceManager *mgr, resource_t *res, bool protect) { char filename[MAXPATHLEN]; - int fh; + Common::File file; resource_t backup; - char *save_cwd = sci_getcwd(); memcpy(&backup, res, sizeof(resource_t)); @@ -264,53 +248,37 @@ _scir_load_resource(ResourceManager *mgr, resource_t *res, int protect) { if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) { if (!patch_sprintfers[mgr->sci_version]) { - sciprintf("Resource manager's SCI version (%d) has no patch file name printers -> internal error!\n", + error("Resource manager's SCI version (%d) has no patch file name printers", mgr->sci_version); - exit(1); } /* Get patch file name */ patch_sprintfers[mgr->sci_version](filename, res); - chdir(res->source->location.dir.name); + + // FIXME: Instead of using SearchMan, maybe we should only search + // a single dir specified by this RESSOURCE_TYPE_DIRECTORY ResourceSource? } else - strcpy(filename, res->source->location.file.name); + strcpy(filename, res->source->location_name.c_str()); - fh = open(filename, O_RDONLY | O_BINARY); - - - if (!IS_VALID_FD(fh)) { - char *raiser = filename; - while (*raiser) { - *raiser = toupper(*raiser); /* Uppercasify */ - ++raiser; - } - fh = sci_open(filename, O_RDONLY | O_BINARY); - } /* Try case-insensitively name */ - - if (!IS_VALID_FD(fh)) { - sciprintf("Failed to open %s!\n", filename); + if (!file.open(filename)) { + warning("Failed to open %s", filename); res->data = NULL; res->status = SCI_STATUS_NOMALLOC; res->size = 0; - chdir(save_cwd); - free(save_cwd); return; } - lseek(fh, res->file_offset, SEEK_SET); + file.seek(res->file_offset, SEEK_SET); - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY || - res->source->source_type == RESSOURCE_TYPE_AUDIO_DIRECTORY) - _scir_load_from_patch_file(fh, res, filename); + if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) + _scir_load_from_patch_file(file, res, filename); else if (!decompressors[mgr->sci_version]) { /* Check whether we support this at all */ - sciprintf("Resource manager's SCI version (%d) is invalid!\n", - mgr->sci_version); - exit(1); + error("Resource manager's SCI version (%d) is invalid", mgr->sci_version); } else { int error = /* Decompress from regular resource file */ - decompressors[mgr->sci_version](res, fh, mgr->sci_version); + decompressors[mgr->sci_version](res, file, mgr->sci_version); if (error) { sciprintf("Error %d occured while reading %s.%03d" @@ -324,17 +292,12 @@ _scir_load_resource(ResourceManager *mgr, resource_t *res, int protect) { res->data = NULL; res->status = SCI_STATUS_NOMALLOC; res->size = 0; - chdir(save_cwd); - free(save_cwd); - return; } } - close(fh); } -resource_t * -scir_test_resource(ResourceManager *mgr, int type, int number) { +resource_t *scir_test_resource(ResourceManager *mgr, int type, int number) { resource_t binseeker; binseeker.type = type; binseeker.number = number; @@ -343,11 +306,10 @@ scir_test_resource(ResourceManager *mgr, int type, int number) { sizeof(resource_t), resourcecmp); } -int sci0_get_compression_method(int resh); +int sci0_get_compression_method(Common::ReadStream &stream); -int -sci_test_view_type(ResourceManager *mgr) { - int fh; +int sci_test_view_type(ResourceManager *mgr) { + Common::File file; char filename[MAXPATHLEN]; int compression; resource_t *res; @@ -355,65 +317,46 @@ sci_test_view_type(ResourceManager *mgr) { mgr->sci_version = SCI_VERSION_AUTODETECT; - for (i = 0;i < 1000;i++) { + for (i = 0; i < 1000; i++) { res = scir_test_resource(mgr, sci_view, i); - if (!res) continue; - - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY || - res->source->source_type == RESSOURCE_TYPE_AUDIO_DIRECTORY) + if (!res) continue; - strcpy(filename, res->source->location.file.name); - fh = open(filename, O_RDONLY | O_BINARY); + if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) + continue; - if (!IS_VALID_FD(fh)) { - char *raiser = filename; - while (*raiser) { - *raiser = toupper(*raiser); /* Uppercasify */ - ++raiser; - } - fh = sci_open(filename, O_RDONLY | O_BINARY); - } /* Try case-insensitively name */ + strcpy(filename, res->source->location_name.c_str()); - if (!IS_VALID_FD(fh)) continue; - lseek(fh, res->file_offset, SEEK_SET); + if (!file.open(filename)) + continue; + file.seek(res->file_offset, SEEK_SET); - compression = sci0_get_compression_method(fh); - close(fh); + compression = sci0_get_compression_method(file); + file.close(); if (compression == 3) return (mgr->sci_version = SCI_VERSION_01_VGA); } /* Try the same thing with pics */ - for (i = 0;i < 1000;i++) { + for (i = 0; i < 1000; i++) { res = scir_test_resource(mgr, sci_pic, i); - if (!res) continue; - - if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY || - res->source->source_type == RESSOURCE_TYPE_AUDIO_DIRECTORY) + if (!res) continue; - strcpy(filename, res->source->location.file.name); - fh = open(filename, O_RDONLY | O_BINARY); - + if (res->source->source_type == RESSOURCE_TYPE_DIRECTORY) + continue; - if (!IS_VALID_FD(fh)) { - char *raiser = filename; - while (*raiser) { - *raiser = toupper(*raiser); /* Uppercasify */ - ++raiser; - } - fh = sci_open(filename, O_RDONLY | O_BINARY); - } /* Try case-insensitively name */ + strcpy(filename, res->source->location_name.c_str()); - if (!IS_VALID_FD(fh)) continue; - lseek(fh, res->file_offset, SEEK_SET); + if (!file.open(filename)) + continue; + file.seek(res->file_offset, SEEK_SET); - compression = sci0_get_compression_method(fh); - close(fh); + compression = sci0_get_compression_method(file); + file.close(); if (compression == 3) return (mgr->sci_version = SCI_VERSION_01_VGA); @@ -424,51 +367,30 @@ sci_test_view_type(ResourceManager *mgr) { -int -scir_add_appropriate_sources(ResourceManager *mgr, - char *dir) { - const char *trailing_slash = ""; +int scir_add_appropriate_sources(ResourceManager *mgr) { //char path_separator; - sci_dir_t dirent; - char *name; ResourceSource *map; - int fd; - char fullname[MAXPATHLEN]; - if (dir[strlen(dir)-1] != G_DIR_SEPARATOR) { - trailing_slash = G_DIR_SEPARATOR_S; - } + if (!Common::File::exists("RESOURCE.MAP")) + return 0; + map = scir_add_external_map(mgr, "RESOURCE.MAP"); - name = (char *)malloc(strlen(dir) + 1 + - strlen("RESOURCE.MAP") + 1); - - sprintf(fullname, "%s%s%s", dir, trailing_slash, "RESOURCE.MAP"); - fd = sci_open("RESOURCE.MAP", O_RDONLY | O_BINARY); - if (!IS_VALID_FD(fd)) return 0; - close(fd); - map = scir_add_external_map(mgr, fullname); - free(name); - sci_init_dir(&dirent); - name = sci_find_first(&dirent, "RESOURCE.0??"); - while (name != NULL) { - char *dot = strrchr(name, '.'); + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, "RESOURCE.0??"); + + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { + const Common::String name = (*x)->getName(); + char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - sprintf(fullname, "%s%s%s", dir, G_DIR_SEPARATOR_S, name); - scir_add_volume(mgr, map, fullname, number, 0); - name = sci_find_next(&dirent); + scir_add_volume(mgr, map, name.c_str(), number, 0); } - sci_finish_find(&dirent); - - sci_finish_find(&dirent); - sprintf(fullname, "%s%s", dir, G_DIR_SEPARATOR_S); - scir_add_patch_dir(mgr, RESSOURCE_TYPE_DIRECTORY, fullname); + scir_add_patch_dir(mgr, ""); // FIXME: used to pass the 'current' instead of "" return 1; } -static int -_scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSource *source) { +static int _scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSource *source) { int preset_version = mgr->sci_version; int resource_error = 0; int dummy = mgr->sci_version; @@ -482,7 +404,7 @@ _scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSour _scir_scan_new_sources(mgr, detected_version, source->next); if (!source->scanned) { - source->scanned = 1; + source->scanned = true; switch (source->source_type) { case RESSOURCE_TYPE_DIRECTORY: if (mgr->sci_version <= SCI_VERSION_01) @@ -511,8 +433,6 @@ _scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSour if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) sciprintf("Running SCI games without a resource map is not supported ATM\n"); sci_free(mgr); - chdir(caller_cwd); - free(caller_cwd); return NULL; } if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) { @@ -522,7 +442,8 @@ _scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSour if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { /* Initialize empty resource manager */ - _scir_init_trivial(mgr); + mgr->_resourcesNr = 0; + mgr->_resources = 0; // FIXME: Was = (resource_t*)sci_malloc(1); resource_error = 0; } #endif @@ -547,7 +468,8 @@ _scir_scan_new_sources(ResourceManager *mgr, int *detected_version, ResourceSour if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { /* Initialize empty resource manager */ - _scir_init_trivial(mgr); + mgr->_resourcesNr = 0; + mgr->_resources = 0; // FIXME: Was = (resource_t*)sci_malloc(1); resource_error = 0; } } @@ -567,59 +489,46 @@ scir_scan_new_sources(ResourceManager *mgr, int *detected_version) { return 0; } -static void -_scir_free_resource_sources(ResourceSource *rss) { +static void _scir_free_resource_sources(ResourceSource *rss) { if (rss) { _scir_free_resource_sources(rss->next); - free(rss); + delete rss; } } -ResourceManager * -scir_new_resource_manager(char *dir, int version, int maxMemory) { +ResourceManager::ResourceManager(int version, int maxMemory) { int resource_error = 0; - ResourceManager *mgr = (ResourceManager*)sci_malloc(sizeof(ResourceManager)); - char *caller_cwd = sci_getcwd(); + ResourceManager *mgr = this; int resmap_version = version; - if (chdir(dir)) { - sciprintf("Resmgr: Directory '%s' is invalid!\n", dir); - free(caller_cwd); - return NULL; - } - - mgr->_maxMemory = maxMemory; + _maxMemory = maxMemory; mgr->memory_locked = 0; mgr->memory_lru = 0; - mgr->resource_path = dir; - - mgr->_resources = NULL; - mgr->_resourcesNr = 0; - mgr->_sources = NULL; + _resources = NULL; + _resourcesNr = 0; + _sources = NULL; mgr->sci_version = version; - scir_add_appropriate_sources(mgr, dir); + mgr->lru_first = NULL; + mgr->lru_last = NULL; + + scir_add_appropriate_sources(mgr); scir_scan_new_sources(mgr, &resmap_version); - if (!mgr->_resources || !mgr->_resourcesNr) { - if (mgr->_resources) { - free(mgr->_resources); - mgr->_resources = NULL; + if (!_resources || !_resourcesNr) { + if (_resources) { + free(_resources); + _resources = NULL; } sciprintf("Resmgr: Could not retrieve a resource list!\n"); _scir_free_resource_sources(mgr->_sources); - free(mgr); - chdir(caller_cwd); - free(caller_cwd); - return NULL; + error("FIXME: Move this code to an init() method so that we can perform error handling"); +// return NULL; } - mgr->lru_first = NULL; - mgr->lru_last = NULL; - - qsort(mgr->_resources, mgr->_resourcesNr, sizeof(resource_t), + qsort(_resources, _resourcesNr, sizeof(resource_t), resourcecmp); /* Sort resources */ if (version == SCI_VERSION_AUTODETECT) @@ -666,7 +575,7 @@ scir_new_resource_manager(char *dir, int version, int maxMemory) { resource_t *res = scir_test_resource(mgr, sci_script, 0); mgr->sci_version = version = SCI_VERSION_1_EARLY; - _scir_load_resource(mgr, res, 1); + _scir_load_resource(mgr, res, true); if (res->status == SCI_STATUS_NOMALLOC) mgr->sci_version = version = SCI_VERSION_1_LATE; @@ -682,27 +591,11 @@ scir_new_resource_manager(char *dir, int version, int maxMemory) { } if (!resource_error) { -#if 0 - if (version <= SCI_VERSION_01) - sci0_read_resource_patches(dir, - &mgr->_resources, - &mgr->_resourcesNr); - else - sci1_read_resource_patches(dir, - &mgr->_resources, - &mgr->_resourcesNr); -#endif - - qsort(mgr->_resources, mgr->_resourcesNr, sizeof(resource_t), + qsort(_resources, _resourcesNr, sizeof(resource_t), resourcecmp); /* Sort resources */ } mgr->sci_version = version; - - chdir(caller_cwd); - free(caller_cwd); - - return mgr; } static void @@ -730,13 +623,10 @@ _scir_free_resources(resource_t *resources, int _resourcesNr) { free(resources); } -void -scir_free_resource_manager(ResourceManager *mgr) { - _scir_free_resources(mgr->_resources, mgr->_resourcesNr); - _scir_free_resource_sources(mgr->_sources); - mgr->_resources = NULL; - - free(mgr); +ResourceManager::~ResourceManager() { + _scir_free_resources(_resources, _resourcesNr); + _scir_free_resource_sources(_sources); + _resources = NULL; } @@ -856,7 +746,7 @@ scir_find_resource(ResourceManager *mgr, int type, int number, int lock) { return NULL; if (!retval->status) - _scir_load_resource(mgr, retval, 0); + _scir_load_resource(mgr, retval, false); else if (retval->status == SCI_STATUS_ENQUEUED) _scir_remove_from_lru(mgr, retval); diff --git a/engines/sci/scicore/resource_map.cpp b/engines/sci/scicore/resource_map.cpp index 70ea8fa447..c79027d0a5 100644 --- a/engines/sci/scicore/resource_map.cpp +++ b/engines/sci/scicore/resource_map.cpp @@ -26,9 +26,9 @@ #include "sci/include/sci_memory.h" #include "sci/include/sciresource.h" #include "sci/include/resource.h" -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif + +#include "common/file.h" + #define RESOURCE_MAP_FILENAME "resource.map" @@ -86,39 +86,36 @@ | (((bytes)[3]) << 9) \ | (((bytes)[2]) << 1)) - -static int -detect_odd_sci01(int fh) { +static int detect_odd_sci01(Common::File &file) { byte buf[6]; int files_ok = 1; - int fsize, resources_nr, tempfh, read_ok; + int fsize, resource_nr, read_ok; char filename[14]; - fsize = sci_fd_size(fh); + fsize = file.size(); if (fsize < 0) { perror("Error occured while trying to get filesize of resource.map"); return SCI_ERROR_RESMAP_NOT_FOUND; } - resources_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; + resource_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; - while (resources_nr-- > 1) { - read_ok = read(fh, &buf, SCI0_RESMAP_ENTRIES_SIZE); + while (resource_nr-- > 1) { + read_ok = file.read(&buf, SCI0_RESMAP_ENTRIES_SIZE); if (read_ok) { sprintf(filename, "resource.%03i", SCI0_RESFILE_GET_FILE(buf + 2)); - tempfh = sci_open(filename, O_RDONLY | O_BINARY); - - if (tempfh == SCI_INVALID_FD) { + Common::File temp; + + // FIXME: Maybe better to use File::exists here? + if (!temp.open(filename)) { files_ok = 0; break; } - - close(tempfh); } } - lseek(fh, 0, SEEK_SET); + file.seek(0, SEEK_SET); return files_ok; } @@ -163,7 +160,7 @@ sci_res_read_entry(ResourceManager *mgr, ResourceSource *map, inline int sci1_res_type(int ofs, int *types, int lastrt) { int i, last = -1; - for (i = 0;i <= sci1_last_resource;i++) + for (i = 0; i <= sci1_last_resource;i++) if (types[i]) { if (types[i] > ofs) return last; @@ -173,16 +170,17 @@ inline int sci1_res_type(int ofs, int *types, int lastrt) { return lastrt; } -int sci1_parse_header(int fd, int *types, int *lastrt) { +int sci1_parse_header(Common::ReadStream &stream, int *types, int *lastrt) { unsigned char rtype; unsigned char offset[2]; int read_ok; int size = 0; do { - read_ok = read(fd, &rtype, 1); - if (!read_ok) break; - read_ok = read(fd, &offset, 2); + read_ok = stream.read(&rtype, 1); + if (!read_ok) + break; + read_ok = stream.read(&offset, 2); if (read_ok < 2) read_ok = 0; if (rtype != 0xff) { @@ -192,31 +190,30 @@ int sci1_parse_header(int fd, int *types, int *lastrt) { size += 3; } while (read_ok && (rtype != 0xFF)); - if (!read_ok) return 0; + if (!read_ok) + return 0; return size; } -int -sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **resource_p, int *resource_nr_p, int *sci_version) { +int sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **resource_p, int *resource_nr_p, int *sci_version) { int fsize; - int fd; + Common::File file; resource_t *resources; - int resources_nr; + int resource_nr; int resource_index = 0; int resources_total_read = 0; int next_entry; int max_resfile_nr = 0; byte buf[SCI0_RESMAP_ENTRIES_SIZE]; - fd = sci_open(map->location.file.name, O_RDONLY | O_BINARY); - if (!IS_VALID_FD(fd)) + if (!file.open(map->location_name)) return SCI_ERROR_RESMAP_NOT_FOUND; - read(fd, &buf, 4); + file.read(&buf, 4); /* Theory: An SCI1 map file begins with an index that allows us to seek quickly to a particular resource type. The entries are three bytes long; one byte @@ -237,13 +234,12 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r if ((buf[0] == 0x80) && (buf[1] % 3 == 0) && (buf[3] == 0x81)) { - close(fd); return SCI_ERROR_INVALID_RESMAP_ENTRY; } - lseek(fd, 0, SEEK_SET); + file.seek(0, SEEK_SET); - switch (detect_odd_sci01(fd)) { + switch (detect_odd_sci01(file)) { case 0 : /* Odd SCI01 */ if (*sci_version == SCI_VERSION_AUTODETECT) *sci_version = SCI_VERSION_01_VGA_ODD; @@ -256,22 +252,23 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r return SCI_ERROR_RESMAP_NOT_FOUND; } - if ((fsize = sci_fd_size(fd)) < 0) { + fsize = file.size(); + if (fsize < 0) { perror("Error occured while trying to get filesize of resource.map"); return SCI_ERROR_RESMAP_NOT_FOUND; } - resources_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; + resource_nr = fsize / SCI0_RESMAP_ENTRIES_SIZE; - resources = (resource_t*)sci_calloc(resources_nr, sizeof(resource_t)); + resources = (resource_t*)sci_calloc(resource_nr, sizeof(resource_t)); /* Sets valid default values for most entries */ do { - int read_ok = read(fd, &buf, SCI0_RESMAP_ENTRIES_SIZE); + int read_ok = file.read(&buf, SCI0_RESMAP_ENTRIES_SIZE); next_entry = 1; if (read_ok < 0) { - sciprintf("Error while reading %s: ", map->location.file.name); + sciprintf("Error while reading %s: ", map->location_name.c_str()); perror(""); next_entry = 0; } else if (read_ok != SCI0_RESMAP_ENTRIES_SIZE) { @@ -286,7 +283,6 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r if (sci_res_read_entry(mgr, map, buf, resources + resource_index, *sci_version)) { free(resources); - close(fd); return SCI_ERROR_RESMAP_NOT_FOUND; } @@ -304,7 +300,7 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r if (fresh) ++resource_index; - if (++resources_total_read >= resources_nr) { + if (++resources_total_read >= resource_nr) { sciprintf("Warning: After %d entries, resource.map" " is not terminated!\n", resource_index); next_entry = 0; @@ -314,16 +310,16 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r } while (next_entry); - close(fd); + file.close(); if (!resource_index) { sciprintf("resource.map was empty!\n"); - _scir_free_resources(resources, resources_nr); + _scir_free_resources(resources, resource_nr); return SCI_ERROR_RESMAP_NOT_FOUND; } if (max_resfile_nr > 999) { - _scir_free_resources(resources, resources_nr); + _scir_free_resources(resources, resource_nr); return SCI_ERROR_INVALID_RESMAP_ENTRY; } else { #if 0 @@ -331,18 +327,16 @@ sci0_read_resource_map(ResourceManager *mgr, ResourceSource *map, resource_t **r /* Check whether the highest resfile used exists */ char filename_buf[14]; sprintf(filename_buf, "resource.%03d", max_resfile_nr); - fd = sci_open(filename_buf, O_RDONLY); - if (!IS_VALID_FD(fd)) { - _scir_free_resources(resources, resources_nr); + if (!file.open(filename_buf) { + _scir_free_resources(resources, resource_nr); sciprintf("'%s' requested by resource.map, but not found\n", filename_buf); return SCI_ERROR_INVALID_RESMAP_ENTRY; - } else - close(fd); + } #endif } - if (resource_index < resources_nr) + if (resource_index < resource_nr) resources = (resource_t*)sci_realloc(resources, sizeof(resource_t) * resource_index); *resource_p = resources; @@ -388,9 +382,9 @@ int sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource *vol, resource_t **resource_p, int *resource_nr_p, int *sci_version) { int fsize; - int fd; + Common::File file; resource_t *resources, *resource_start; - int resources_nr; + int resource_nr; int resource_index = 0; int ofs, header_size; int *types = (int*)sci_malloc(sizeof(int) * (sci1_last_resource + 1)); @@ -400,15 +394,12 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource int entrysize; int entry_size_selector; - fd = sci_open(map->location.file.name, O_RDONLY | O_BINARY); - - if (!IS_VALID_FD(fd)) + if (!file.open(map->location_name)) return SCI_ERROR_RESMAP_NOT_FOUND; memset(types, 0, sizeof(int) * (sci1_last_resource + 1)); - if (!(sci1_parse_header(fd, types, &lastrt))) { - close(fd); + if (!(sci1_parse_header(file, types, &lastrt))) { return SCI_ERROR_INVALID_RESMAP_ENTRY; } @@ -418,7 +409,6 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource if (*sci_version == SCI_VERSION_AUTODETECT) { /* That didn't help */ sciprintf("Unable to detect resource map version\n"); - close(fd); return SCI_ERROR_NO_RESOURCE_FILES_FOUND; } @@ -426,24 +416,25 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource ? SCI11_RESMAP_ENTRIES_SIZE : SCI1_RESMAP_ENTRIES_SIZE; - if ((fsize = sci_fd_size(fd)) < 0) { + fsize = file.size(); + if (fsize < 0) { perror("Error occured while trying to get filesize of resource.map"); - close(fd); return SCI_ERROR_RESMAP_NOT_FOUND; } - resources_nr = (fsize - types[0]) / entrysize; - resource_start = resources = (resource_t*)sci_realloc(mgr->_resources, (mgr->_resourcesNr + resources_nr) * sizeof(resource_t)); + resource_nr = (fsize - types[0]) / entrysize; + resource_start = resources = (resource_t*)sci_realloc(mgr->_resources, (mgr->_resourcesNr + resource_nr) * sizeof(resource_t)); resources += mgr->_resourcesNr; i = 0; - while (types[i] == 0) i++; + while (types[i] == 0) + i++; header_size = ofs = types[i]; - lseek(fd, ofs, SEEK_SET); + file.seek(ofs, SEEK_SET); - for (i = 0; i < resources_nr; i++) { - int read_ok = read(fd, &buf, entrysize); + for (i = 0; i < resource_nr; i++) { + int read_ok = file.read(&buf, entrysize); int j; resource_t *res; int addto = resource_index; @@ -451,10 +442,11 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource if (read_ok < entrysize) { #if 0 - if (!eof(fd)) { - sciprintf("Error while reading %s: ", map->location.file.name); + if (!file.eof()) { + sciprintf("Error while reading %s: ", map->location_name.c_str()); perror(""); - } else read_ok = 1; + } else + read_ok = 1; break; #endif } @@ -498,7 +490,6 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource ofs += entrysize; } - close(fd); free(types); *resource_p = resource_start; @@ -510,9 +501,9 @@ sci1_read_resource_map(ResourceManager *mgr, ResourceSource *map, ResourceSource #ifdef TEST_RESOURCE_MAP int main(int argc, char **argv) { - int resources_nr; + int resource_nr; resource_t *resources; - int notok = sci0_read_resource_map(".", &resources, &resources_nr); + int notok = sci0_read_resource_map(".", &resources, &resource_nr); if (notok) { fprintf(stderr, "Failed: Error code %d\n", notok); @@ -522,9 +513,9 @@ main(int argc, char **argv) { if (resources) { int i; - printf("Found %d resources:\n", resources_nr); + printf("Found %d resources:\n", resource_nr); - for (i = 0; i < resources_nr; i++) { + for (i = 0; i < resource_nr; i++) { resource_t *res = resources + i; printf("#%04d:\tRESOURCE.%03d:%8d\t%s.%03d\n", diff --git a/engines/sci/scicore/resource_patch.cpp b/engines/sci/scicore/resource_patch.cpp index a9e472468f..154eb73984 100644 --- a/engines/sci/scicore/resource_patch.cpp +++ b/engines/sci/scicore/resource_patch.cpp @@ -23,131 +23,118 @@ * */ +#include "common/archive.h" +#include "common/file.h" #include "sci/include/sciresource.h" #include "sci/include/sci_memory.h" -void -sci0_sprintf_patch_file_name(char *string, resource_t *res) { +void sci0_sprintf_patch_file_name(char *string, resource_t *res) { sprintf(string, "%s.%03i", sci_resource_types[res->type], res->number); } -void -sci1_sprintf_patch_file_name(char *string, resource_t *res) { +void sci1_sprintf_patch_file_name(char *string, resource_t *res) { sprintf(string, "%d.%s", res->number, sci_resource_type_suffixes[res->type]); } /* version-agnostic patch application */ -static void -process_patch(ResourceSource *source, - char *entry, int restype, int resnumber, resource_t **resource_p, int *resource_nr_p) { - int fsize; - char filename[MAXPATHLEN]; +static void process_patch(ResourceSource *source, + Common::ArchiveMember &member, int restype, int resnumber, resource_t **resource_p, int *resource_nr_p) { + Common::File file; if (restype == sci_invalid_resource) return; - printf("Patching \"%s\": ", entry); - - sprintf(filename, "%s%s", source->location.dir.name, entry); - fsize = sci_file_size(filename); - if (fsize < 0) - perror("""__FILE__"": (""__LINE__""): sci_file_size()"); + printf("Patching \"%s\": ", member.getName().c_str()); + if (!file.open(member.createReadStream(), member.getName())) + perror("""__FILE__"": (""__LINE__""): failed to open"); else { - int file; guint8 filehdr[2]; resource_t *newrsc = _scir_find_resource_unsorted(*resource_p, *resource_nr_p, restype, resnumber); - + int fsize = file.size(); if (fsize < 3) { printf("File too small\n"); return; } - file = open(entry, O_RDONLY); - if (!IS_VALID_FD(file)) - perror("""__FILE__"": (""__LINE__""): open()"); - else { - int patch_data_offset; - - read(file, filehdr, 2); - - patch_data_offset = filehdr[1]; - - if ((filehdr[0] & 0x7f) != restype) { - printf("Failed; resource type mismatch\n"); - close(file); - } else if (patch_data_offset + 2 >= fsize) { - printf("Failed; patch starting at offset %d can't be in file of size %d\n", filehdr[1] + 2, fsize); - close(file); - } else { - /* Adjust for file offset */ - fsize -= patch_data_offset; - - /* Prepare destination, if neccessary */ - if (!newrsc) { - /* Completely new resource! */ - ++(*resource_nr_p); - *resource_p = (resource_t*)sci_realloc(*resource_p, - *resource_nr_p - * sizeof(resource_t)); - newrsc = (*resource_p - 1) + *resource_nr_p; - newrsc->alt_sources = NULL; - } - - /* Overwrite everything, because we're patching */ - newrsc->size = fsize - 2; - newrsc->id = restype << 11 | resnumber; - newrsc->number = resnumber; - newrsc->status = SCI_STATUS_NOMALLOC; - newrsc->type = restype; - newrsc->source = source; - newrsc->file_offset = 2 + patch_data_offset; + int patch_data_offset; + + file.read(filehdr, 2); + + patch_data_offset = filehdr[1]; + + if ((filehdr[0] & 0x7f) != restype) { + printf("Failed; resource type mismatch\n"); + } else if (patch_data_offset + 2 >= fsize) { + printf("Failed; patch starting at offset %d can't be in file of size %d\n", filehdr[1] + 2, fsize); + } else { + /* Adjust for file offset */ + fsize -= patch_data_offset; + + /* Prepare destination, if neccessary */ + if (!newrsc) { + /* Completely new resource! */ + ++(*resource_nr_p); + *resource_p = (resource_t*)sci_realloc(*resource_p, + *resource_nr_p + * sizeof(resource_t)); + newrsc = (*resource_p - 1) + *resource_nr_p; + newrsc->alt_sources = NULL; + } - _scir_add_altsource(newrsc, source, 2); + /* Overwrite everything, because we're patching */ + newrsc->size = fsize - 2; + newrsc->id = restype << 11 | resnumber; + newrsc->number = resnumber; + newrsc->status = SCI_STATUS_NOMALLOC; + newrsc->type = restype; + newrsc->source = source; + newrsc->file_offset = 2 + patch_data_offset; - close(file); + _scir_add_altsource(newrsc, source, 2); - printf("OK\n"); + printf("OK\n"); - } } } } -int -sci0_read_resource_patches(ResourceSource *source, resource_t **resource_p, int *resource_nr_p) { - sci_dir_t dir; - char *entry; - char *caller_cwd = sci_getcwd(); - - chdir(source->location.dir.name); - sci_init_dir(&dir); - entry = sci_find_first(&dir, "*.???"); - while (entry) { +int sci0_read_resource_patches(ResourceSource *source, resource_t **resource_p, int *resource_nr_p) { + // FIXME: Use only one specific dir, instead of SearchMan? + //chdir(source->location_dir_name.c_str()); + //sci_init_dir(&dir); + //entry = sci_find_first(&dir, "*.???"); + + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, "*.???"); + + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { + const Common::String name = (*x)->getName(); int restype = sci_invalid_resource; int resnumber = -1; int i; unsigned int resname_len; char *endptr; +printf("sci0_read_resource_patches: scanning '%s'\n", name.c_str()); for (i = sci_view; i < sci_invalid_resource; i++) - if (scumm_strnicmp(sci_resource_types[i], entry, + if (scumm_strnicmp(sci_resource_types[i], name.c_str(), strlen(sci_resource_types[i])) == 0) restype = i; if (restype != sci_invalid_resource) { resname_len = strlen(sci_resource_types[restype]); - if (entry[resname_len] != '.') + if (name[resname_len] != '.') restype = sci_invalid_resource; else { - resnumber = strtol(entry + 1 + resname_len, + resnumber = strtol(name.c_str() + 1 + resname_len, &endptr, 10); /* Get resource number */ - if ((*endptr != '\0') || (resname_len + 1 == strlen(entry))) + if ((*endptr != '\0') || (resname_len + 1 == name.size())) restype = sci_invalid_resource; if ((resnumber < 0) || (resnumber > 1000)) @@ -155,31 +142,29 @@ sci0_read_resource_patches(ResourceSource *source, resource_t **resource_p, int } } - process_patch(source, entry, restype, resnumber, resource_p, resource_nr_p); - - entry = sci_find_next(&dir); + process_patch(source, **x, restype, resnumber, resource_p, resource_nr_p); } - chdir(caller_cwd); - free(caller_cwd); return 0; } int sci1_read_resource_patches(ResourceSource *source, resource_t **resource_p, int *resource_nr_p) { - sci_dir_t dir; - char *entry; - char *caller_cwd = sci_getcwd(); - - chdir(source->location.dir.name); - sci_init_dir(&dir); - entry = sci_find_first(&dir, "*.*"); - while (entry) { + // FIXME: Use only one specific dir, instead of SearchMan? + //chdir(source->location_dir_name.c_str()); + //sci_init_dir(&dir); + //entry = sci_find_first(&dir, "*.*"); + + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, "*.*"); + + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { + const Common::String name = (*x)->getName(); int restype = sci_invalid_resource; int resnumber = -1; int i; char *endptr; - char *dot = strchr(entry, '.'); + char *dot = strchr(name.c_str(), '.'); for (i = sci_view; i < sci_invalid_resource; i++) { if (dot != NULL) { @@ -191,7 +176,7 @@ sci1_read_resource_patches(ResourceSource *source, resource_t **resource_p, int if (restype != sci_invalid_resource) { - resnumber = strtol(entry, + resnumber = strtol(name.c_str(), &endptr, 10); /* Get resource number */ if (endptr != dot) @@ -204,13 +189,9 @@ sci1_read_resource_patches(ResourceSource *source, resource_t **resource_p, int restype = sci_invalid_resource; } - process_patch(source, entry, restype, resnumber, resource_p, resource_nr_p); - - entry = sci_find_next(&dir); + process_patch(source, **x, restype, resnumber, resource_p, resource_nr_p); } - chdir(caller_cwd); - free(caller_cwd); return 0; } diff --git a/engines/sci/scicore/tools.cpp b/engines/sci/scicore/tools.cpp index 9b192cbf24..417165af99 100644 --- a/engines/sci/scicore/tools.cpp +++ b/engines/sci/scicore/tools.cpp @@ -24,6 +24,11 @@ */ +#include "common/archive.h" +#include "common/file.h" +#include "common/util.h" + + #ifdef _MSC_VER # include <sys/timeb.h> # include <windows.h> @@ -439,90 +444,45 @@ sci_sched_yield() { ** (sci_dir_t *) dir: Directory to find file within. ** Returns : (char *) Case-sensitive filename of the file. */ -char *_fcaseseek(const char *fname, sci_dir_t *dir) { +Common::String _fcaseseek(const char *fname) { /* Expects *dir to be uninitialized and the caller to ** free it afterwards */ - Common::String buf; - char *retval = NULL, *name; - -#ifdef _MSC_VER - return (char *)fname; -#endif - if (strchr(fname, G_DIR_SEPARATOR)) { fprintf(stderr, "_fcaseseek() does not support subdirs\n"); BREAKPOINT(); } - sci_init_dir(dir); - - /* Replace all letters with '?' chars */ - buf = fname; - - for (Common::String::iterator iterator = buf.begin(); iterator != buf.end(); ++iterator) { - if (isalpha(*iterator)) - *iterator = '?'; - } - - name = sci_find_first(dir, buf.c_str()); + // Look up the file, ignoring case + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, fname); - while (name && !retval) { - if (!scumm_stricmp(fname, name)) - retval = name; - else - name = sci_find_next(dir); + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { + const Common::String name = (*x)->getName(); + if (name.equalsIgnoreCase(fname)) + return name; } - - return retval; + return Common::String(); } -FILE * -sci_fopen(const char *fname, const char *mode) { - sci_dir_t dir; - char *name = _fcaseseek(fname, &dir); +FILE *sci_fopen(const char *fname, const char *mode) { + Common::String name = _fcaseseek(fname); FILE *file = NULL; - if (name) - file = fopen(name, mode); + if (!name.empty()) + file = fopen(name.c_str(), mode); else if (strchr(mode, 'w')) file = fopen(fname, mode); - sci_finish_find(&dir); /* Free memory */ - return file; } -int -sci_open(const char *fname, int flags) { - sci_dir_t dir; - char *name; +int sci_open(const char *fname, int flags) { int file = SCI_INVALID_FD; - char *separator_position; - char *path; - char *caller_cwd; - - sci_init_dir(&dir); - - separator_position = (char *)strrchr(fname, G_DIR_SEPARATOR); - if (separator_position) { - path = (char *) malloc(separator_position - fname + 1); - path[separator_position-fname] = 0; - strncpy(path, fname, separator_position - fname); - chdir(path); - free(path); - } - - name = _fcaseseek(separator_position ? separator_position + 1 : fname, &dir); - if (name) - file = open(name, flags); - - sci_finish_find(&dir); /* Free memory */ - - caller_cwd = sci_getcwd(); - chdir(caller_cwd); - free(caller_cwd); + Common::String name = _fcaseseek(fname); + if (!name.empty()) + file = open(name.c_str(), flags); return file; } |