diff --git a/espReader/ESPReader.h b/espReader/ESPReader.h index 690ae4b..90d8216 100644 --- a/espReader/ESPReader.h +++ b/espReader/ESPReader.h @@ -31,8 +31,10 @@ extern "C" { #endif +// Flag fields are 32 bits, so there are 32 flags #define RFS_INNER_SIZE 32 +// There are 127 record types + a NONE type used for sanity checks #define RT_SIZE 128 /* RT hash seed was externally calculated s.t. the fourcc codes perfectly hash @@ -48,9 +50,12 @@ extern "C" { #define RT_HASH_BITS 9 #define RT_HASH_SEED 131261257 +// Used for identifying records that are compressed #define COMPRESSED_FLAG (((uint32_t)1) << 18) +// Top level group order, there are 118 top level groups #define GO_SIZE 118 +// There are 10 Group Types #define GTS_SIZE 10 @@ -68,15 +73,17 @@ extern "C" { // === SIMPLE TYPES === // + // 3 byte ID, upper byte is determined at run time and is used to reference + // across esp/esm files typedef uint32_t formid; - // char[4] with uint32_t access + // char[4] with uint32_t access, used to access fourcc values union type4 { char bytes[4]; uint32_t uint; }; - // indexed by flag bit + // Inner type for Record Flag String LUT. Indexed by flag bit. typedef const char *const rfs_inner[RFS_INNER_SIZE]; // @@ -84,7 +91,7 @@ extern "C" { // // Tag for generic node tagged union - enum node_type { // NT_ prefix + enum node_type { NT_GROUP, NT_RECORD, }; @@ -116,8 +123,8 @@ extern "C" { WTHR, }; - // GRUP type values - enum group_type { // GT_ prefix + // Group type enum + enum group_type { GT_TOP = 0, GT_WORLD_CHILDREN = 1, GT_INTERIOR_CELL_BLOCK = 2, @@ -134,7 +141,7 @@ extern "C" { // === COMPOSITE TYPES === // - // Generic node + // Generic node in the esp/esm tree typedef struct node Node; struct node { union { @@ -146,13 +153,24 @@ extern "C" { uint32_t _pad; }; - // calculated timestamp + // Used for passing around parsed timestamps struct timestamp { uint16_t year; uint8_t month; uint8_t day; }; + /* Given to espr_walk. + * + * pre is called before the children of the current node have been walked + * post is called after the children of the current node have been walked + * + * carry_out and carry_in is a pointer to a void * on the stack that can be + * used for passing data between pre and post for a node. + * + * data is a pointer that the user can supply when calling espr_walk that + * will be passed to pre and post when they are called. + */ struct walker_callbacks { void (*pre)(Node n, void *data, void **carry_out); void (*post)(Node n, void *data, void **carry_in); @@ -215,9 +233,8 @@ extern "C" { // 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[RT_SIZE]; + extern rfs_inner *const rfs_refr[RT_SIZE]; // Expected (probably) order of top level groups in an esp/esm extern const enum record_type group_order[GO_SIZE]; @@ -229,9 +246,9 @@ extern "C" { // === FUNCTIONS === // - // hashes type value into RT_ hash value + // hashes type value into a record type enum value inline uint32_t rt_hash(uint32_t type) { - return uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED); + return rth2rt[uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED)]; } /* `espr_walk` walks through the tree structure of the esp/esm binary data diff --git a/espReader/ESPTree.h b/espReader/ESPTree.h index cf58a1e..6db349c 100644 --- a/espReader/ESPTree.h +++ b/espReader/ESPTree.h @@ -10,11 +10,32 @@ typedef struct meta_node MetaNode; /* Meta Nodes are used for constructing a more flexible tree structure - * on top of + * on top of the natural structure of ESP/ESM files. + * + * Meta Nodes do not create a pure tree structure, rather they have pointers to + * their parent and first child, and children have pointers backwards and + * forward through a linked list of all of the children of the parent node. + * + * There is no root node as such, rather there is a root linked list for which + * all of the Meta Nodes have no parents. + * + * While the ESP/ESM buffer can be modified in-place, any modification that + * changes the size of the stored data cannot be directly written to the buffer + * without first shifting all of the data after the point of modification. + * + * Modifications that change data size are: + * - Adding or deleting a group or record + * - Adding or deleting a field in a record + * - Changing a variable length field with data of different length + * + * With a Meta Node you can instead allocate new, arbitrarily sized memory for + * the node data. The Meta Node tree can then be walked to reconstruct a + * contiguous view of discontiguous memory. */ struct meta_node { Node n; MetaNode *parent; + MetaNode *child; MetaNode *prev; MetaNode *next; }; diff --git a/espReader/LUT.c b/espReader/LUT.c index e2b13bf..29107aa 100644 --- a/espReader/LUT.c +++ b/espReader/LUT.c @@ -476,50 +476,50 @@ rfs_inner wrld = { [19] = "Can't Wait", }; -rfs_inner *const rfs[RT_HASH_SIZE] = { - [RT_AACT] = CP(NULL),[RT_ACHR] = CP(achr),[RT_ACTI] = CP(acti), - [RT_ADDN] = CP(NULL),[RT_ALCH] = CP(alch),[RT_AMMO] = CP(ammo), - [RT_ANIO] = CP(anio),[RT_APPA] = CP(NULL),[RT_ARMA] = CP(NULL), - [RT_ARMO] = CP(armo),[RT_ARTO] = CP(NULL),[RT_ASPC] = CP(NULL), - [RT_ASTP] = CP(NULL),[RT_AVIF] = CP(NULL),[RT_BOOK] = CP(NULL), - [RT_BPTD] = CP(NULL),[RT_CAMS] = CP(NULL),[RT_CELL] = CP(cell), - [RT_CLAS] = CP(NULL),[RT_CLDC] = CP(NULL),[RT_CLFM] = CP(clfm), - [RT_CLMT] = CP(NULL),[RT_COBJ] = CP(NULL),[RT_COLL] = CP(NULL), - [RT_CONT] = CP(cont),[RT_CPTH] = CP(NULL),[RT_CSTY] = CP(csty), - [RT_DEBR] = CP(NULL),[RT_DIAL] = CP(NULL),[RT_DLBR] = CP(NULL), - [RT_DLVW] = CP(NULL),[RT_DOBJ] = CP(NULL),[RT_DOOR] = CP(door), - [RT_DUAL] = CP(NULL),[RT_ECZN] = CP(NULL),[RT_EFSH] = CP(NULL), - [RT_ENCH] = CP(NULL),[RT_EQUP] = CP(NULL),[RT_EXPL] = CP(NULL), - [RT_EYES] = CP(eyes),[RT_FACT] = CP(NULL),[RT_FLOR] = CP(NULL), - [RT_FLST] = CP(NULL),[RT_FSTP] = CP(NULL),[RT_FSTS] = CP(NULL), - [RT_FURN] = CP(furn),[RT_GLOB] = CP(glob),[RT_GMST] = CP(NULL), - [RT_GRAS] = CP(NULL),[RT_GRUP] = CP(NULL),[RT_HAIR] = CP(NULL), - [RT_HAZD] = CP(NULL),[RT_HDPT] = CP(hdpt),[RT_IDLE] = CP(NULL), - [RT_IDLM] = CP(idlm),[RT_IMAD] = CP(NULL),[RT_IMGS] = CP(NULL), - [RT_INFO] = CP(info),[RT_INGR] = CP(NULL),[RT_IPCT] = CP(NULL), - [RT_IPDS] = CP(NULL),[RT_KEYM] = CP(keym),[RT_KYWD] = CP(NULL), - [RT_LAND] = CP(land),[RT_LCRT] = CP(NULL),[RT_LCTN] = CP(NULL), - [RT_LGTM] = CP(NULL),[RT_LIGH] = CP(ligh),[RT_LSCR] = CP(lscr), - [RT_LTEX] = CP(NULL),[RT_LVLI] = CP(NULL),[RT_LVLN] = CP(NULL), - [RT_LVSP] = CP(NULL),[RT_MATO] = CP(NULL),[RT_MATT] = CP(NULL), - [RT_MESG] = CP(NULL),[RT_MGEF] = CP(NULL),[RT_MISC] = CP(misc), - [RT_MOVT] = CP(NULL),[RT_MSTT] = CP(mstt),[RT_MUSC] = CP(NULL), - [RT_MUST] = CP(NULL),[RT_NAVI] = CP(NULL),[RT_NAVM] = CP(navm), - [RT_NOTE] = CP(NULL),[RT_NPC_] = CP(npc_),[RT_OTFT] = CP(NULL), - [RT_PACK] = CP(NULL),[RT_PERK] = CP(perk),[RT_PGRE] = CP(pgre), - [RT_PHZD] = CP(phzd),[RT_PROJ] = CP(NULL),[RT_PWAT] = CP(NULL), - [RT_QUST] = CP(NULL),[RT_RACE] = CP(race),[RT_REFR] = CP(refr), - [RT_REGN] = CP(regn),[RT_RELA] = CP(rela),[RT_REVB] = CP(NULL), - [RT_RFCT] = CP(NULL),[RT_RGDL] = CP(NULL),[RT_SCEN] = CP(NULL), - [RT_SCOL] = CP(NULL),[RT_SCPT] = CP(NULL),[RT_SCRL] = CP(NULL), - [RT_SHOU] = CP(shou),[RT_SLGM] = CP(slgm),[RT_SMBN] = CP(NULL), - [RT_SMEN] = CP(NULL),[RT_SMQN] = CP(NULL),[RT_SNCT] = CP(NULL), - [RT_SNDR] = CP(NULL),[RT_SOPM] = CP(NULL),[RT_SOUN] = CP(NULL), - [RT_SPEL] = CP(NULL),[RT_SPGD] = CP(NULL),[RT_STAT] = CP(stat), - [RT_TACT] = CP(tact),[RT_TES4] = CP(tes4),[RT_TREE] = CP(tree), - [RT_TXST] = CP(NULL),[RT_VTYP] = CP(NULL),[RT_WATR] = CP(NULL), - [RT_WEAP] = CP(weap),[RT_WOOP] = CP(NULL),[RT_WRLD] = CP(wrld), - [RT_WTHR] = CP(NULL), +rfs_inner *const rfs[RT_SIZE] = { + [AACT] = CP(NULL),[ACHR] = CP(achr),[ACTI] = CP(acti), + [ADDN] = CP(NULL),[ALCH] = CP(alch),[AMMO] = CP(ammo), + [ANIO] = CP(anio),[APPA] = CP(NULL),[ARMA] = CP(NULL), + [ARMO] = CP(armo),[ARTO] = CP(NULL),[ASPC] = CP(NULL), + [ASTP] = CP(NULL),[AVIF] = CP(NULL),[BOOK] = CP(NULL), + [BPTD] = CP(NULL),[CAMS] = CP(NULL),[CELL] = CP(cell), + [CLAS] = CP(NULL),[CLDC] = CP(NULL),[CLFM] = CP(clfm), + [CLMT] = CP(NULL),[COBJ] = CP(NULL),[COLL] = CP(NULL), + [CONT] = CP(cont),[CPTH] = CP(NULL),[CSTY] = CP(csty), + [DEBR] = CP(NULL),[DIAL] = CP(NULL),[DLBR] = CP(NULL), + [DLVW] = CP(NULL),[DOBJ] = CP(NULL),[DOOR] = CP(door), + [DUAL] = CP(NULL),[ECZN] = CP(NULL),[EFSH] = CP(NULL), + [ENCH] = CP(NULL),[EQUP] = CP(NULL),[EXPL] = CP(NULL), + [EYES] = CP(eyes),[FACT] = CP(NULL),[FLOR] = CP(NULL), + [FLST] = CP(NULL),[FSTP] = CP(NULL),[FSTS] = CP(NULL), + [FURN] = CP(furn),[GLOB] = CP(glob),[GMST] = CP(NULL), + [GRAS] = CP(NULL),[GRUP] = CP(NULL),[HAIR] = CP(NULL), + [HAZD] = CP(NULL),[HDPT] = CP(hdpt),[IDLE] = CP(NULL), + [IDLM] = CP(idlm),[IMAD] = CP(NULL),[IMGS] = CP(NULL), + [INFO] = CP(info),[INGR] = CP(NULL),[IPCT] = CP(NULL), + [IPDS] = CP(NULL),[KEYM] = CP(keym),[KYWD] = CP(NULL), + [LAND] = CP(land),[LCRT] = CP(NULL),[LCTN] = CP(NULL), + [LGTM] = CP(NULL),[LIGH] = CP(ligh),[LSCR] = CP(lscr), + [LTEX] = CP(NULL),[LVLI] = CP(NULL),[LVLN] = CP(NULL), + [LVSP] = CP(NULL),[MATO] = CP(NULL),[MATT] = CP(NULL), + [MESG] = CP(NULL),[MGEF] = CP(NULL),[MISC] = CP(misc), + [MOVT] = CP(NULL),[MSTT] = CP(mstt),[MUSC] = CP(NULL), + [MUST] = CP(NULL),[NAVI] = CP(NULL),[NAVM] = CP(navm), + [NOTE] = CP(NULL),[NPC_] = CP(npc_),[OTFT] = CP(NULL), + [PACK] = CP(NULL),[PERK] = CP(perk),[PGRE] = CP(pgre), + [PHZD] = CP(phzd),[PROJ] = CP(NULL),[PWAT] = CP(NULL), + [QUST] = CP(NULL),[RACE] = CP(race),[REFR] = CP(refr), + [REGN] = CP(regn),[RELA] = CP(rela),[REVB] = CP(NULL), + [RFCT] = CP(NULL),[RGDL] = CP(NULL),[SCEN] = CP(NULL), + [SCOL] = CP(NULL),[SCPT] = CP(NULL),[SCRL] = CP(NULL), + [SHOU] = CP(shou),[SLGM] = CP(slgm),[SMBN] = CP(NULL), + [SMEN] = CP(NULL),[SMQN] = CP(NULL),[SNCT] = CP(NULL), + [SNDR] = CP(NULL),[SOPM] = CP(NULL),[SOUN] = CP(NULL), + [SPEL] = CP(NULL),[SPGD] = CP(NULL),[STAT] = CP(stat), + [TACT] = CP(tact),[TES4] = CP(tes4),[TREE] = CP(tree), + [TXST] = CP(NULL),[VTYP] = CP(NULL),[WATR] = CP(NULL), + [WEAP] = CP(weap),[WOOP] = CP(NULL),[WRLD] = CP(wrld), + [WTHR] = CP(NULL), }; // REFR flags depend on what its NAME field references @@ -630,49 +630,49 @@ rfs_inner r_misc = REFR_GROUP2; rfs_inner r_slgm = REFR_GROUP2; rfs_inner r_weap = REFR_GROUP2; -rfs_inner *const rfs_r[RT_HASH_SIZE] = { - [RT_AACT] = CP(NULL ),[RT_ACHR] = CP(NULL ),[RT_ACTI] = CP(r_acti), - [RT_ADDN] = CP(r_addn),[RT_ALCH] = CP(r_alch),[RT_AMMO] = CP(r_ammo), - [RT_ANIO] = CP(NULL ),[RT_APPA] = CP(NULL ),[RT_ARMA] = CP(NULL ), - [RT_ARMO] = CP(r_armo),[RT_ARTO] = CP(NULL ),[RT_ASPC] = CP(NULL ), - [RT_ASTP] = CP(NULL ),[RT_AVIF] = CP(NULL ),[RT_BOOK] = CP(NULL ), - [RT_BPTD] = CP(NULL ),[RT_CAMS] = CP(NULL ),[RT_CELL] = CP(NULL ), - [RT_CLAS] = CP(NULL ),[RT_CLDC] = CP(NULL ),[RT_CLFM] = CP(NULL ), - [RT_CLMT] = CP(NULL ),[RT_COBJ] = CP(NULL ),[RT_COLL] = CP(NULL ), - [RT_CONT] = CP(r_cont),[RT_CPTH] = CP(NULL ),[RT_CSTY] = CP(NULL ), - [RT_DEBR] = CP(NULL ),[RT_DIAL] = CP(NULL ),[RT_DLBR] = CP(NULL ), - [RT_DLVW] = CP(NULL ),[RT_DOBJ] = CP(NULL ),[RT_DOOR] = CP(r_door), - [RT_DUAL] = CP(NULL ),[RT_ECZN] = CP(NULL ),[RT_EFSH] = CP(NULL ), - [RT_ENCH] = CP(NULL ),[RT_EQUP] = CP(NULL ),[RT_EXPL] = CP(NULL ), - [RT_EYES] = CP(NULL ),[RT_FACT] = CP(NULL ),[RT_FLOR] = CP(r_flor), - [RT_FLST] = CP(NULL ),[RT_FSTP] = CP(NULL ),[RT_FSTS] = CP(NULL ), - [RT_FURN] = CP(NULL ),[RT_GLOB] = CP(NULL ),[RT_GMST] = CP(NULL ), - [RT_GRAS] = CP(NULL ),[RT_GRUP] = CP(NULL ),[RT_HAIR] = CP(NULL ), - [RT_HAZD] = CP(NULL ),[RT_HDPT] = CP(NULL ),[RT_IDLE] = CP(NULL ), - [RT_IDLM] = CP(NULL ),[RT_IMAD] = CP(NULL ),[RT_IMGS] = CP(NULL ), - [RT_INFO] = CP(NULL ),[RT_INGR] = CP(r_ingr),[RT_IPCT] = CP(NULL ), - [RT_IPDS] = CP(NULL ),[RT_KEYM] = CP(r_keym),[RT_KYWD] = CP(NULL ), - [RT_LAND] = CP(NULL ),[RT_LCRT] = CP(NULL ),[RT_LCTN] = CP(NULL ), - [RT_LGTM] = CP(NULL ),[RT_LIGH] = CP(r_ligh),[RT_LSCR] = CP(NULL ), - [RT_LTEX] = CP(NULL ),[RT_LVLI] = CP(NULL ),[RT_LVLN] = CP(NULL ), - [RT_LVSP] = CP(NULL ),[RT_MATO] = CP(NULL ),[RT_MATT] = CP(NULL ), - [RT_MESG] = CP(NULL ),[RT_MGEF] = CP(NULL ),[RT_MISC] = CP(r_misc), - [RT_MOVT] = CP(NULL ),[RT_MSTT] = CP(r_mstt),[RT_MUSC] = CP(NULL ), - [RT_MUST] = CP(NULL ),[RT_NAVI] = CP(NULL ),[RT_NAVM] = CP(NULL ), - [RT_NOTE] = CP(NULL ),[RT_NPC_] = CP(NULL ),[RT_OTFT] = CP(NULL ), - [RT_PACK] = CP(NULL ),[RT_PERK] = CP(NULL ),[RT_PGRE] = CP(NULL ), - [RT_PHZD] = CP(NULL ),[RT_PROJ] = CP(NULL ),[RT_PWAT] = CP(NULL ), - [RT_QUST] = CP(NULL ),[RT_RACE] = CP(NULL ),[RT_REFR] = CP(NULL ), - [RT_REGN] = CP(NULL ),[RT_RELA] = CP(NULL ),[RT_REVB] = CP(NULL ), - [RT_RFCT] = CP(NULL ),[RT_RGDL] = CP(NULL ),[RT_SCEN] = CP(NULL ), - [RT_SCOL] = CP(NULL ),[RT_SCPT] = CP(NULL ),[RT_SCRL] = CP(r_scrl), - [RT_SHOU] = CP(NULL ),[RT_SLGM] = CP(r_slgm),[RT_SMBN] = CP(NULL ), - [RT_SMEN] = CP(NULL ),[RT_SMQN] = CP(NULL ),[RT_SNCT] = CP(NULL ), - [RT_SNDR] = CP(NULL ),[RT_SOPM] = CP(NULL ),[RT_SOUN] = CP(NULL ), - [RT_SPEL] = CP(NULL ),[RT_SPGD] = CP(NULL ),[RT_STAT] = CP(r_stat), - [RT_TACT] = CP(NULL ),[RT_TES4] = CP(NULL ),[RT_TREE] = CP(r_tree), - [RT_TXST] = CP(NULL ),[RT_VTYP] = CP(NULL ),[RT_WATR] = CP(NULL ), - [RT_WEAP] = CP(r_weap),[RT_WOOP] = CP(NULL ),[RT_WRLD] = CP(NULL ), - [RT_WTHR] = CP(NULL ), +rfs_inner *const rfs_r[RT_SIZE] = { + [AACT] = CP(NULL ),[ACHR] = CP(NULL ),[ACTI] = CP(r_acti), + [ADDN] = CP(r_addn),[ALCH] = CP(r_alch),[AMMO] = CP(r_ammo), + [ANIO] = CP(NULL ),[APPA] = CP(NULL ),[ARMA] = CP(NULL ), + [ARMO] = CP(r_armo),[ARTO] = CP(NULL ),[ASPC] = CP(NULL ), + [ASTP] = CP(NULL ),[AVIF] = CP(NULL ),[BOOK] = CP(NULL ), + [BPTD] = CP(NULL ),[CAMS] = CP(NULL ),[CELL] = CP(NULL ), + [CLAS] = CP(NULL ),[CLDC] = CP(NULL ),[CLFM] = CP(NULL ), + [CLMT] = CP(NULL ),[COBJ] = CP(NULL ),[COLL] = CP(NULL ), + [CONT] = CP(r_cont),[CPTH] = CP(NULL ),[CSTY] = CP(NULL ), + [DEBR] = CP(NULL ),[DIAL] = CP(NULL ),[DLBR] = CP(NULL ), + [DLVW] = CP(NULL ),[DOBJ] = CP(NULL ),[DOOR] = CP(r_door), + [DUAL] = CP(NULL ),[ECZN] = CP(NULL ),[EFSH] = CP(NULL ), + [ENCH] = CP(NULL ),[EQUP] = CP(NULL ),[EXPL] = CP(NULL ), + [EYES] = CP(NULL ),[FACT] = CP(NULL ),[FLOR] = CP(r_flor), + [FLST] = CP(NULL ),[FSTP] = CP(NULL ),[FSTS] = CP(NULL ), + [FURN] = CP(NULL ),[GLOB] = CP(NULL ),[GMST] = CP(NULL ), + [GRAS] = CP(NULL ),[GRUP] = CP(NULL ),[HAIR] = CP(NULL ), + [HAZD] = CP(NULL ),[HDPT] = CP(NULL ),[IDLE] = CP(NULL ), + [IDLM] = CP(NULL ),[IMAD] = CP(NULL ),[IMGS] = CP(NULL ), + [INFO] = CP(NULL ),[INGR] = CP(r_ingr),[IPCT] = CP(NULL ), + [IPDS] = CP(NULL ),[KEYM] = CP(r_keym),[KYWD] = CP(NULL ), + [LAND] = CP(NULL ),[LCRT] = CP(NULL ),[LCTN] = CP(NULL ), + [LGTM] = CP(NULL ),[LIGH] = CP(r_ligh),[LSCR] = CP(NULL ), + [LTEX] = CP(NULL ),[LVLI] = CP(NULL ),[LVLN] = CP(NULL ), + [LVSP] = CP(NULL ),[MATO] = CP(NULL ),[MATT] = CP(NULL ), + [MESG] = CP(NULL ),[MGEF] = CP(NULL ),[MISC] = CP(r_misc), + [MOVT] = CP(NULL ),[MSTT] = CP(r_mstt),[MUSC] = CP(NULL ), + [MUST] = CP(NULL ),[NAVI] = CP(NULL ),[NAVM] = CP(NULL ), + [NOTE] = CP(NULL ),[NPC_] = CP(NULL ),[OTFT] = CP(NULL ), + [PACK] = CP(NULL ),[PERK] = CP(NULL ),[PGRE] = CP(NULL ), + [PHZD] = CP(NULL ),[PROJ] = CP(NULL ),[PWAT] = CP(NULL ), + [QUST] = CP(NULL ),[RACE] = CP(NULL ),[REFR] = CP(NULL ), + [REGN] = CP(NULL ),[RELA] = CP(NULL ),[REVB] = CP(NULL ), + [RFCT] = CP(NULL ),[RGDL] = CP(NULL ),[SCEN] = CP(NULL ), + [SCOL] = CP(NULL ),[SCPT] = CP(NULL ),[SCRL] = CP(r_scrl), + [SHOU] = CP(NULL ),[SLGM] = CP(r_slgm),[SMBN] = CP(NULL ), + [SMEN] = CP(NULL ),[SMQN] = CP(NULL ),[SNCT] = CP(NULL ), + [SNDR] = CP(NULL ),[SOPM] = CP(NULL ),[SOUN] = CP(NULL ), + [SPEL] = CP(NULL ),[SPGD] = CP(NULL ),[STAT] = CP(r_stat), + [TACT] = CP(NULL ),[TES4] = CP(NULL ),[TREE] = CP(r_tree), + [TXST] = CP(NULL ),[VTYP] = CP(NULL ),[WATR] = CP(NULL ), + [WEAP] = CP(r_weap),[WOOP] = CP(NULL ),[WRLD] = CP(NULL ), + [WTHR] = CP(NULL ), }; diff --git a/espReader/Reader.c b/espReader/Reader.c index 430e1ea..2c83d1c 100644 --- a/espReader/Reader.c +++ b/espReader/Reader.c @@ -261,7 +261,7 @@ char *walk_concat(char *data, size_t size, struct walker_callbacks cb) { const Type4 *type = (Type4 *)data; // check valid type - assert(rt[rth2rt[rt_hash(type->uint)]] == type->uint); + assert(rt[rt_hash(type->uint)] == type->uint); // only need to distinguish between groups and records if (type->uint == rt[GRUP])