Reformatting.
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
#include <stdint.h>
|
||||
#include "msh.h"
|
||||
|
||||
// Guards for C++ usage
|
||||
// Guards for C++ usage
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -38,7 +38,7 @@ extern "C" {
|
||||
/* RT hash seed was externally calculated s.t. the fourcc codes perfectly hash into
|
||||
* indices between 0 and 511. That is, there are no hashing collisions. This allows
|
||||
* for hard coded lookup tables for the fourcc codes in a relatively small space.
|
||||
*
|
||||
*
|
||||
* A minimal perfect hash is also possible with an intermediate seed table, though
|
||||
* I'm not sure which is faster, if it's worth trying to speed this up, etc.
|
||||
*/
|
||||
@@ -52,219 +52,216 @@ extern "C" {
|
||||
#define GTS_SIZE 10
|
||||
|
||||
|
||||
//
|
||||
// === FORWARD DEFS ===
|
||||
//
|
||||
//
|
||||
// === FORWARD DEFS ===
|
||||
//
|
||||
|
||||
typedef union type4 Type4;
|
||||
typedef struct timestamp Timestamp;
|
||||
typedef struct group Group;
|
||||
typedef struct record Record;
|
||||
typedef struct field Field;
|
||||
typedef union type4 Type4;
|
||||
typedef struct timestamp Timestamp;
|
||||
typedef struct group Group;
|
||||
typedef struct record Record;
|
||||
typedef struct field Field;
|
||||
|
||||
//
|
||||
// === SIMPLE TYPES ===
|
||||
//
|
||||
//
|
||||
// === SIMPLE TYPES ===
|
||||
//
|
||||
|
||||
// Basic types
|
||||
typedef uint32_t formid;
|
||||
typedef uint32_t formid;
|
||||
|
||||
// char[4] with uint32_t access
|
||||
union type4 {
|
||||
char bytes[4];
|
||||
uint32_t uint;
|
||||
};
|
||||
// char[4] with uint32_t access
|
||||
union type4 {
|
||||
char bytes[4];
|
||||
uint32_t uint;
|
||||
};
|
||||
|
||||
// indexed by flag bit
|
||||
typedef const char *const rfs_inner[RFS_INNER_SIZE];
|
||||
// indexed by flag bit
|
||||
typedef const char *const rfs_inner[RFS_INNER_SIZE];
|
||||
|
||||
//
|
||||
// === ENUMS ===
|
||||
//
|
||||
//
|
||||
// === ENUMS ===
|
||||
//
|
||||
|
||||
// Tag for generic node tagged union
|
||||
enum node_type { // NT_ prefix
|
||||
NT_GROUP,
|
||||
NT_RECORD,
|
||||
};
|
||||
// Tag for generic node tagged union
|
||||
enum node_type { // NT_ prefix
|
||||
NT_GROUP,
|
||||
NT_RECORD,
|
||||
};
|
||||
|
||||
// Record type enum
|
||||
enum record_type {
|
||||
_NONE,
|
||||
AACT, ACHR, ACTI, ADDN, ALCH, AMMO,
|
||||
ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
|
||||
ASTP, AVIF, BOOK, BPTD, CAMS, CELL,
|
||||
CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
|
||||
CONT, CPTH, CSTY, DEBR, DIAL, DLBR,
|
||||
DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
|
||||
ENCH, EQUP, EXPL, EYES, FACT, FLOR,
|
||||
FLST, FSTP, FSTS, FURN, GLOB, GMST,
|
||||
GRAS, GRUP, HAIR, HAZD, HDPT, IDLE,
|
||||
IDLM, IMAD, IMGS, INFO, INGR, IPCT,
|
||||
IPDS, KEYM, KYWD, LAND, LCRT, LCTN,
|
||||
LGTM, LIGH, LSCR, LTEX, LVLI, LVLN,
|
||||
LVSP, MATO, MATT, MESG, MGEF, MISC,
|
||||
MOVT, MSTT, MUSC, MUST, NAVI, NAVM,
|
||||
NOTE, NPC_, OTFT, PACK, PERK, PGRE,
|
||||
PHZD, PROJ, PWAT, QUST, RACE, REFR,
|
||||
REGN, RELA, REVB, RFCT, RGDL, SCEN,
|
||||
SCOL, SCPT, SCRL, SHOU, SLGM, SMBN,
|
||||
SMEN, SMQN, SNCT, SNDR, SOPM, SOUN,
|
||||
SPEL, SPGD, STAT, TACT, TES4, TREE,
|
||||
TXST, VTYP, WATR, WEAP, WOOP, WRLD,
|
||||
WTHR,
|
||||
};
|
||||
// Record type enum
|
||||
enum record_type {
|
||||
AACT, ACHR, ACTI, ADDN, ALCH, AMMO,
|
||||
ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
|
||||
ASTP, AVIF, BOOK, BPTD, CAMS, CELL,
|
||||
CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
|
||||
CONT, CPTH, CSTY, DEBR, DIAL, DLBR,
|
||||
DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
|
||||
ENCH, EQUP, EXPL, EYES, FACT, FLOR,
|
||||
FLST, FSTP, FSTS, FURN, GLOB, GMST,
|
||||
GRAS, GRUP, HAIR, HAZD, HDPT, IDLE,
|
||||
IDLM, IMAD, IMGS, INFO, INGR, IPCT,
|
||||
IPDS, KEYM, KYWD, LAND, LCRT, LCTN,
|
||||
LGTM, LIGH, LSCR, LTEX, LVLI, LVLN,
|
||||
LVSP, MATO, MATT, MESG, MGEF, MISC,
|
||||
MOVT, MSTT, MUSC, MUST, NAVI, NAVM,
|
||||
NOTE, NPC_, OTFT, PACK, PERK, PGRE,
|
||||
PHZD, PROJ, PWAT, QUST, RACE, REFR,
|
||||
REGN, RELA, REVB, RFCT, RGDL, SCEN,
|
||||
SCOL, SCPT, SCRL, SHOU, SLGM, SMBN,
|
||||
SMEN, SMQN, SNCT, SNDR, SOPM, SOUN,
|
||||
SPEL, SPGD, STAT, TACT, TES4, TREE,
|
||||
TXST, VTYP, WATR, WEAP, WOOP, WRLD,
|
||||
WTHR,
|
||||
};
|
||||
|
||||
// GRUP type values
|
||||
enum group_type { // GT_ prefix
|
||||
GT_TOP = 0,
|
||||
GT_WORLD_CHILDREN = 1,
|
||||
GT_INTERIOR_CELL_BLOCK = 2,
|
||||
GT_INTERIOR_CELL_SUBBLOCK = 3,
|
||||
GT_EXTERIOR_CELL_BLOCK = 4,
|
||||
GT_EXTERIOR_CELL_SUBBLOCK = 5,
|
||||
GT_CELL_CHILDREN = 6,
|
||||
GT_TOPIC_CHILDREN = 7,
|
||||
GT_CELL_PERSISTENT_CHILDREN = 8,
|
||||
GT_CELL_TEMPORARY_CHILDREN = 9,
|
||||
};
|
||||
// GRUP type values
|
||||
enum group_type { // GT_ prefix
|
||||
GT_TOP = 0,
|
||||
GT_WORLD_CHILDREN = 1,
|
||||
GT_INTERIOR_CELL_BLOCK = 2,
|
||||
GT_INTERIOR_CELL_SUBBLOCK = 3,
|
||||
GT_EXTERIOR_CELL_BLOCK = 4,
|
||||
GT_EXTERIOR_CELL_SUBBLOCK = 5,
|
||||
GT_CELL_CHILDREN = 6,
|
||||
GT_TOPIC_CHILDREN = 7,
|
||||
GT_CELL_PERSISTENT_CHILDREN = 8,
|
||||
GT_CELL_TEMPORARY_CHILDREN = 9,
|
||||
};
|
||||
|
||||
//
|
||||
// === COMPOSITE TYPES ===
|
||||
//
|
||||
//
|
||||
// === COMPOSITE TYPES ===
|
||||
//
|
||||
|
||||
// Generic node
|
||||
typedef struct node Node;
|
||||
struct node {
|
||||
union {
|
||||
Group *group;
|
||||
Record *record;
|
||||
} header;
|
||||
char *const data;
|
||||
enum node_type type;
|
||||
uint32_t _pad;
|
||||
};
|
||||
// Generic node
|
||||
typedef struct node Node;
|
||||
struct node {
|
||||
union {
|
||||
Group *group;
|
||||
Record *record;
|
||||
} header;
|
||||
char *const data;
|
||||
enum node_type type;
|
||||
uint32_t _pad;
|
||||
};
|
||||
|
||||
// calculated timestamp
|
||||
struct timestamp {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
};
|
||||
// calculated timestamp
|
||||
struct timestamp {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
};
|
||||
|
||||
struct walker_callbacks {
|
||||
void (*pre)(Node n, void *data, void **carry_out);
|
||||
void (*post)(Node n, void *data, void **carry_in);
|
||||
void *data;
|
||||
};
|
||||
struct walker_callbacks {
|
||||
void (*pre)(Node n, void *data, void **carry_out);
|
||||
void (*post)(Node n, void *data, void **carry_in);
|
||||
void *data;
|
||||
};
|
||||
|
||||
//
|
||||
// === BINARY DATA OVERLAYS ===
|
||||
//
|
||||
//
|
||||
// === BINARY DATA OVERLAYS ===
|
||||
//
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// Group header overlay
|
||||
struct group {
|
||||
Type4 grup; // always RT_GRUP
|
||||
uint32_t size; // uncludes the 24 byte group header
|
||||
union {
|
||||
Type4 type; // this may be mangled and should not be relied on
|
||||
formid formid;
|
||||
int32_t number;
|
||||
int16_t coord[2];
|
||||
} label; // access determined by the `type` below
|
||||
int32_t type; // group_type enum
|
||||
uint16_t timestamp;
|
||||
uint16_t vcinfo;
|
||||
uint32_t unknown;
|
||||
};
|
||||
// Group header overlay
|
||||
struct group {
|
||||
Type4 grup; // always RT_GRUP
|
||||
uint32_t size; // uncludes the 24 byte group header
|
||||
union {
|
||||
Type4 type; // this may be mangled and should not be relied on
|
||||
formid formid;
|
||||
int32_t number;
|
||||
int16_t coord[2];
|
||||
} label; // access determined by the `type` below
|
||||
int32_t type; // group_type enum
|
||||
uint16_t timestamp;
|
||||
uint16_t vcinfo;
|
||||
uint32_t unknown;
|
||||
};
|
||||
|
||||
// Record header overlay
|
||||
struct record {
|
||||
Type4 type;
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t formid;
|
||||
uint16_t timestamp;
|
||||
uint16_t vcinfo;
|
||||
uint16_t version;
|
||||
uint16_t unknown;
|
||||
};
|
||||
// Record header overlay
|
||||
struct record {
|
||||
Type4 type;
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t formid;
|
||||
uint16_t timestamp;
|
||||
uint16_t vcinfo;
|
||||
uint16_t version;
|
||||
uint16_t unknown;
|
||||
};
|
||||
|
||||
// Field header overlay
|
||||
struct field {
|
||||
Type4 type;
|
||||
uint16_t size;
|
||||
};
|
||||
// Field header overlay
|
||||
struct field {
|
||||
Type4 type;
|
||||
uint16_t size;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
//
|
||||
// === LUTs ===
|
||||
//
|
||||
//
|
||||
// === LUTs ===
|
||||
//
|
||||
|
||||
// record type enum to fourcc value
|
||||
extern const uint32_t rt[RT_SIZE];
|
||||
// record type enum to fourcc value
|
||||
extern const uint32_t rt[RT_SIZE];
|
||||
|
||||
// for converting between record_type and record_type_hash enums
|
||||
extern const uint16_t rt2rth[RT_SIZE];
|
||||
extern const uint8_t rth2rt[RT_HASH_SIZE];
|
||||
// for converting between record_type and record_type_hash enums
|
||||
extern const uint16_t rt2rth[RT_SIZE];
|
||||
extern const uint8_t rth2rt[RT_HASH_SIZE];
|
||||
|
||||
// type -> flag mappings
|
||||
// NULL table pointers indicate no flags
|
||||
// NULL string pointers indicate invalid flag
|
||||
extern rfs_inner *const rfs[RT_HASH_SIZE];
|
||||
// type -> flag mappings
|
||||
// NULL table pointers indicate no flags
|
||||
// NULL string pointers indicate invalid flag
|
||||
extern rfs_inner *const rfs[RT_HASH_SIZE];
|
||||
|
||||
extern rfs_inner *const rfs_refr[RT_HASH_SIZE];
|
||||
extern rfs_inner *const rfs_refr[RT_HASH_SIZE];
|
||||
|
||||
// Expected (probably) order of top level groups in an esp/esm
|
||||
extern const enum record_type group_order[GO_SIZE];
|
||||
// Expected (probably) order of top level groups in an esp/esm
|
||||
extern const enum record_type group_order[GO_SIZE];
|
||||
|
||||
// Printable strings for group types
|
||||
extern const char *const group_type_strings[GTS_SIZE];
|
||||
// Printable strings for group types
|
||||
extern const char *const group_type_strings[GTS_SIZE];
|
||||
|
||||
//
|
||||
// === FUNCTIONS ===
|
||||
//
|
||||
|
||||
//
|
||||
// === FUNCTIONS ===
|
||||
//
|
||||
// hashes type value into RT_ hash value
|
||||
inline uint32_t rt_hash(uint32_t type) {
|
||||
return uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED);
|
||||
}
|
||||
|
||||
// hashes type value into RT_ hash value
|
||||
inline uint32_t rt_hash(uint32_t type) {
|
||||
return uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED);
|
||||
}
|
||||
/* `espr_walk` walks through the tree structure of the esp/esm binary data
|
||||
* starting at `data` of `size` bytes.
|
||||
*
|
||||
* `cb` is a callback that takes a `Node` to process. `pt` is a pointer to
|
||||
* arbitrary data that is passed on to `cb` whenever it is called.
|
||||
*
|
||||
* Data is walked sequentially. Nodes passed to `cb` will be strictly increasing
|
||||
* in terms of memory location within the buffer.
|
||||
*/
|
||||
void espr_walk(char *data, size_t size, struct walker_callbacks cb);
|
||||
|
||||
/* `espr_walk` walks through the tree structure of the esp/esm binary data
|
||||
* starting at `data` of `size` bytes.
|
||||
*
|
||||
* `cb` is a callback that takes a `Node` to process. `pt` is a pointer to
|
||||
* arbitrary data that is passed on to `cb` whenever it is called.
|
||||
*
|
||||
* Data is walked sequentially. Nodes passed to `cb` will be strictly increasing
|
||||
* in terms of memory location within the buffer.
|
||||
*/
|
||||
void espr_walk(char *data, size_t size, struct walker_callbacks cb);
|
||||
/* `espr_print` prints the header of every group and record in the given
|
||||
* esp/esm binary data.
|
||||
*/
|
||||
void espr_print(char *data, size_t size);
|
||||
|
||||
/* `espr_print` prints the header of every group and record in the given
|
||||
* esp/esm binary data.
|
||||
*/
|
||||
void espr_print(char *data, size_t size);
|
||||
/* Calculates the size of the esp data if all of the compressed records are
|
||||
* decompressed.
|
||||
*/
|
||||
size_t espr_decompressed_size(char *data, size_t size);
|
||||
|
||||
/* Calculates the size of the esp data if all of the compressed records are
|
||||
* decompressed.
|
||||
*/
|
||||
size_t espr_decompressed_size(char *data, size_t size);
|
||||
/* Counts the number of formids present in the esp/esm data. This should be
|
||||
* equal to the number of records.
|
||||
*/
|
||||
size_t espr_formid_count(char *data, size_t size);
|
||||
|
||||
/* Counts the number of formids present in the esp/esm data. This should be
|
||||
* equal to the number of records.
|
||||
*/
|
||||
size_t espr_formid_count(char *data, size_t size);
|
||||
|
||||
/* Copies the data from `data` to `buf` decompressing compressed fields as
|
||||
* it does so. buf_size should be the value returned from `espr_decompressed_size`,
|
||||
* and `buf` should be at least of that size.
|
||||
*/
|
||||
void espr_decompress(char *data, size_t size, char *buf, size_t buf_size);
|
||||
/* Copies the data from `data` to `buf` decompressing compressed fields as
|
||||
* it does so. buf_size should be the value returned from `espr_decompressed_size`,
|
||||
* and `buf` should be at least of that size.
|
||||
*/
|
||||
void espr_decompress(char *data, size_t size, char *buf, size_t buf_size);
|
||||
|
||||
// End C++ guard
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user