/* * ============================================================================ * RES_FILE: Resource File Manipulation Routines * * Author: J. Zbiciak * Last Modified: 8/23/98 * ============================================================================ * * This file defines the interface into the RES_FILE set of library routines. * The library was designed to be resonably flexible and fairly elegant. * While some effort has been made to make the implementation resonably * efficient at a low level, many aspects of the architecture are geared * towards conceptual clarity rather than raw performance. For instance, * the "pack"/"unpack" architecture is fairly elegant, but reeks of overhead. * * This library strives to be fully re-entrant. * * ============================================================================ * * Library functions: * * RES_ENCODE -- Converts a record to external storage format * RES_DECODE -- Decodes a record into internal storage format * RES_TYPE_NAME -- returns a human-readable name for a type number * RES_CLEAR_ERR -- clears any errors that are in a res_state_t structure. * RES_FIND_REC -- find named record in an archive (not hierarchially) * * Enumerated types: * * RES_RECST_T -- Enumerated set of resource record states. * RES_TYPE_T -- Enumerated resource record types. * RES_ERR_T -- Enumerated list of defined error codes. * * Structure types: * * RES_REC_T -- Resource Record structure * RES_STATE_T -- General state management structure. * RES_ARCH_T -- Resource Archive structure * RES_IMG_T -- Resource Image/Font structure * * Provided macros: * * RES_MAXERR -- Maximum number of queued error messages to store. * RES_ERRMSGLEN -- Maximum length of an error message. * * Note: RES_MAXERR and RES_ERRMSGLEN may be defined externally. However, * if this is done, make certain that all files that #include this file * receive these same modified definitions. * * ============================================================================ */ #ifndef _RES_FILE_H #define _RES_FILE_H /* * ============================================================================ * TYPE DECLARATIONS * ============================================================================ */ /* * ---------------------------------------------------------------------------- * RES_STATE_T -- General state management structure. * RES_ERR_T -- Enumerated list of defined error codes. * * The res_state_t structure provides a means for passing library state * information between a calling application and the res_file library. * All persistent library state that a thread of execution might want * is kept in this structure. This allows the res_file library to * theoretically be re-entrant. * * The top-level res_arch_t structure in a hierarchial structure contains * a pointer to a res_state_t. This pointer defines the behavior of the * res_file library with respect to this res_arch_t. Nested archive * structures inherit this pointer from their enclosing parent archives. * NOTE: IT IS EXTREMELY IMPORTANT THAT THESE POINTERS REMAIN CONSISTENT. * That said, if you rely on library routines for merging resources * together, you should be ok. If some things are mismatched, such as * the "malloc", "realloc" and "free" functions, then the "losing" archive * will have its contents re-malloc'd with the "winning" archive's malloc, * and freed with the "losing" archive's free during the merge. * * The library function res_init_arch() will set up a new archive structure, * along with the state structure that it points to. The calling software * must perform this initialization for all other library functionality to * work. * * The res_file routines pass error status information back to callers * via these structures. In the structure are fields for error messages * as well as error codes. Up to RES_MAXERR errors may be reported at a * time -- this is provided because multiple errors might occur during an * operation. The function res_clear_err resets a res_state_t structure * to the state "RES_e_ok". Note that the error messages provided in the * err_msg[] array are statically allocated within the res_state_t * structure. * * The enumerated type "res_err_t" defines the currently defined error types. * * Note: The resource file functions still return a sentinel value denoting * whether an error occured (eg. -1, NULL, whatever). The state structure * just provides the details. :-) * ---------------------------------------------------------------------------- */ #ifndef RES_MAXERR #define RES_MAXERR ((int)4) #endif #ifndef RES_ERRMSGLEN #define RES_ERRMSGLEN ((int)80) #endif typedef void *(*res_malloc_t) (size_t); /* malloc-type function ptr */ typedef void *(*res_realloc_t)(void*, size_t); /* realloc-type function ptr */ typedef void (*res_free_t) (void*); /* free-type function ptr */ typedef enum res_err_t { RES_e_ok = 0, /* No error has occurred. */ RES_e_no_mem = 1, /* Out of memory. */ RES_e_underflow = 2, /* Input buffer underflowed. */ RES_e_overflow = 3, /* Output buffer overflowed. */ RES_e_format = 4, /* Invalid file format. */ RES_e_inconsistent = 5, /* Data structures are inconsistent. */ RES_e_rle_decode = 6, /* RLE decoder error. */ RES_e_invalid_type = 7, /* Invalid resource type. */ RES_e_not_impl = 8, /* Not yet implemented. */ RES_e_special_enc = 9, /* Error calling special encoder. */ RES_e_special_dec = 9, /* Error calling special decoder. */ RES_e_err_overflow = -1, /* Too many errors! */ RES_e_unknown = -2 /* Unknown (invalid?) error */ } res_err_t; typedef struct res_state_t { int num_err; res_err_t err_list[RES_MAXERR]; char err_msg [RES_MAXERR][RES_ERRMSGLEN]; res_malloc_t malloc; res_realloc_t realloc; res_free_t free; } res_state_t; /* * ---------------------------------------------------------------------------- * RES_ARCH_T -- Resource Archive structure * * A resource archive contains a linked list of resource records. A given * resource record may contain another resource archive, thus providing a * hierarchial means for storing data within a top-level resource archive. * ---------------------------------------------------------------------------- */ typedef struct res_arch_t { char ident[13]; /* ASCIIZ identifier string */ unsigned short state; /* Resource file state */ unsigned short count; /* Number of resource records */ struct res_rec_t *res_rec; /* Linked-list of res records */ } res_arch_t; /* * ---------------------------------------------------------------------------- * RES_IMG_T -- Resource Image structure * * Images in a resource archive are in an RLE-encoded image format. * This structure contains a pointer to the image, as well as the * image dimensions. The image itself is an 8-bit pseudocolor image * whose palette is stored elsewhere as a palette resource. * * Currently, it appears all fonts are mostly stored in the same format as * the image files, so no special structure is defined for fonts. One anomaly * is that TINYFONT.RES stores a '0' in each font's length field. The * library corrects this by determining the correct value that goes there. * I don't know if that will break the existing PC Intellivision simulator. * ---------------------------------------------------------------------------- */ typedef struct res_img_t { unsigned short x_dim; /* Width of image */ unsigned short y_dim; /* Height of image */ unsigned short len; /* Actual length of compressed data. */ unsigned char *img; /* Image data */ } res_img_t; /* * ---------------------------------------------------------------------------- * RES_TYPE_T -- Enumerated resource record types. * * These resource types denote resource types found in the Intellivision * simulator's resource archives. * ---------------------------------------------------------------------------- */ typedef enum res_type_t { RES_t_raw = 0x0000, /* Raw binary data */ RES_t_archive = 0x0001, /* Nested resource archive */ RES_t_image = 0x0002, /* Compressed image data */ RES_t_font = 0x0003, /* Compressed font data */ RES_t_palette = 0x0004, /* Palette record */ RES_t_audio = 0x0005, /* Sound data */ RES_t_pcx = 0x0006, /* PCX image data */ RES_t_html = 0x0007, /* HTML data */ RES_t_unknown /* "unknown" sentinel value */ } res_type_t; #define RES_RECURSE (31) #define RES_ALL (~RES_RECURSE) /* * ---------------------------------------------------------------------------- * RES_REC_T -- Resource Record structure * RES_RECST_T -- Enumerated set of resource record states. * * A resource record contains information about an encapsulated resource. * It is the basic type that all res_file routines work with. Resources * can be of many formats, including resource archive format. For that * reason, even the top-level archive is encapsulated in a resource record, * primarily for convenience. This meta-record corresponds to the physical * file that the resource archive resides in. * * The resource record structure includes a type flag which denotes the * type of data stored in this structure, and a state flag which denote the * state of the data stored. Types include "archive", "image", "font", etc, * as enumerated by res_type_t. States include "decoded", and "encoded", * as enumerated by res_recst_t. * * The res_recst_t enumeration allows denoting what state a resource * record is in. Currently, only "decoded", and "encoded" are implemented. * The "not-present" state may possibly allow the implementation of a * zone-memory-based caching scheme, similar to what idSoftware used in DOOM. * That is a very low priority right now, since it is fairly complicated to * implement correctly, and by-and-large not necessary at the moment. * * When a resource object is in "encoded" form, it exists merely as a raw * memory image that mirrors how it would be stored to disk. When a resource * is in "decoded" form, it is converted into a structure containing type- * specific data. The res_rec_t merely stores a pointer to whatever data * is stored in the record, and it uses a union to provide dynamic casting * between types. * ---------------------------------------------------------------------------- */ typedef enum res_recst_t { RES_s_notpresent = 0x0000, /* Resource is cached out */ RES_s_encoded = 0x0001, /* Resource is in encoded form */ RES_s_decoded = 0x0002 /* Resource is in decoded form */ } res_recst_t; typedef struct res_rec_t { res_state_t *lib_state; /* Library state information */ res_recst_t rec_state; /* Status of this record */ char ident[13]; /* ASCIIZ identifier string */ res_type_t type; /* Resource record type */ unsigned len; /* Length of resource (bytes) */ unsigned dist; /* Distance until next resource */ unsigned ofs; /* Offset into archive */ union { res_arch_t *arch; /* Nested archive (if type=1) */ res_img_t *img; /* Decompressed image data */ void *data; /* Raw binary data */ } res; /* Specialized encode/decode functions for this resource */ int (*enc) (struct res_rec_t*); int (*dec) (struct res_rec_t*); struct res_rec_t *next; /* Pointer to next res_rec_t */ } res_rec_t; /* * ============================================================================ * FUNCTION PROTOTYPES * ============================================================================ */ int /* Return code: 0 or -1 */ res_encode ( res_rec_t *record /* Record containing resource to encode */ ); int /* Return code: 0 or -1 */ res_decode ( res_rec_t *record, /* Record containing resource to decode */ unsigned decode_mask, /* Bitmask of what types to decode */ int (*enc)(res_rec_t*), /* Special encode function (if any) */ int (*dec)(res_rec_t*) /* Special decode function (if any) */ ); const char * /* Pointer to resource name */ res_type_name ( res_type_t type /* Resource type name */ ); res_rec_t * /* Resource record (if found) */ res_find_rec ( res_rec_t *archive, /* Archive to search in */ const char *name /* Resource name to look for */ ); int res_clear_err ( res_rec_t *archive /* Archive to reset */ ); int /* Return code: 0 or -1 */ res_init_arch ( res_rec_t *archive, /* Archive to initialize */ res_malloc_t malloc_func, /* malloc function to use for archive */ res_realloc_t realloc_func, /* realloc function to use for archive */ res_free_t free_func /* free function to use for archive */ ); void res_report_err ( res_rec_t *record, /* Record to record error in. */ res_err_t error /* Error number to report. */ ); int /* Return code: 0 or -1 */ res_init_rec ( res_rec_t *record, /* Record to initialize */ res_malloc_t malloc_func, /* malloc function to use for archive */ res_realloc_t realloc_func, /* realloc function to use for archive */ res_free_t free_func /* free function to use for archive */ ); #endif /* _RES_FILE_H */ /* * ============================================================================ * Copyright (c) 1998, Joseph Zbiciak. * ============================================================================ */