int parse_od_resource(struct H3MLIB_CTX *ctx, struct H3M_OD_ENTRY *od_entry, struct META_OD_ENTRY *meta_od_entry) { struct H3M *p = &ctx->h3m; struct H3MLIB_PARSING *parsing = &ctx->parsing; const uint32_t fm = p->format; struct H3M_OD_BODY_DYNAMIC_RESOURCE *body = NULL; size_t n = 0; int ret = 0; if (0 == ((struct H3M_OD_BODY_STATIC_RESOURCE *) &parsing->raw[parsing->offset])->has_guardians) { meta_od_entry->binary_compatible = 1; meta_od_entry->body_size = sizeof(struct H3M_OD_BODY_STATIC_RESOURCE); return 0; } od_entry->body = calloc(1, sizeof(*body)); body = (struct H3M_OD_BODY_DYNAMIC_RESOURCE *)od_entry->body; meta_od_entry->binary_compatible = 0; meta_od_entry->body_size = sizeof(*body); SAFE_READ_SIZEOF(&body->has_guardians, parsing) if (0 != body->has_guardians) { if (0 != (ret = parse_od_ext_guardians(ctx, &body->guardians, meta_od_entry))) { return ret; } } n = sizeof(body->quantity) + sizeof(body->unknown1); SAFE_READ_N(&body->quantity, n, parsing); return 0; }
static int _parse_player_ab(int idx, struct H3MLIB_CTX *ctx) { struct H3M *p = &ctx->h3m; struct H3MLIB_META *meta = &ctx->meta; struct H3MLIB_PARSING *parsing = &ctx->parsing; int orig_off = ctx->parsing.offset; int ret = 0; size_t size = 0; const char *member = NULL; struct H3M_PLAYER_AB *ab = NULL; // TODO: Roll strnlen replacement for all language that may require it // Simply alloc enough space for all of the unions - no one cares about a few // bytes needlessly used up for the smaller unions ab = calloc(1, sizeof(*ab) + H3M_MAX_HERO_NAME + 1); // + 1 for NULL terminator // TODO: safety check here SAFE_READ_N(ab, sizeof(*ab) + H3M_MAX_HERO_NAME, parsing); //// HACK FOR PLACEHOLDER HERO //if (0 == ab->has_main_town && 0xFF == ab->u.e0.starting_hero_type && 0 != ab->town_types) //{ // size = 10; // member = "player (e4)"; // meta->player_has_ai[idx] = 1; // meta->player_ext_types[idx] = 0; //} //// H3M_PLAYER_EXT_ABSOD //else if (0 == ab->has_main_town && 0xFF == ab->u.e0.starting_hero_type) { size = sizeof(*ab) - sizeof(ab->u) + sizeof(ab->u.e0); member = "player (e0)"; meta->player_ext_types[idx] = 0; } // H3M_PLAYER_EXT_WITH_TOWN_ABSOD else if (0 != ab->has_main_town && 0xFF == ab->u.e1.starting_hero_type) { size = sizeof(*ab) - sizeof(ab->u) + sizeof(ab->u.e1); member = "player (e1)"; meta->player_ext_types[idx] = 1; } // H3M_PLAYER_EXT_WITH_HERO_ABSOD else if (0 == ab->has_main_town && (0 == ab->u.e2.starting_hero_name_size || (ab->u.e2.starting_hero_name_size <= H3M_MAX_HERO_NAME && ab->u.e2.starting_hero_name_size == strnlen((char *)ab->u.e2.starting_hero_name, H3M_MAX_HERO_NAME + 1)))) { size = sizeof(*ab) - sizeof(ab->u) + sizeof(ab->u.e2) + ab->u.e2.starting_hero_name_size; member = "player (e2)"; meta->player_has_ai[idx] = 1; meta->player_ext_types[idx] = 2; } // H3M_PLAYER_EXT_WITH_TOWN_AND_HERO_ABSOD else if (0 != ab->has_main_town && (0 == ab->u.e3.starting_hero_name_size || (ab->u.e3.starting_hero_name_size <= H3M_MAX_HERO_NAME && ab->u.e3.starting_hero_name_size == strnlen((char *)ab->u.e3.starting_hero_name, H3M_MAX_HERO_NAME + 1)))) { size = sizeof(*ab) - sizeof(ab->u) + sizeof(ab->u.e3) + ab->u.e3.starting_hero_name_size; member = "player (e3)"; meta->player_has_ai[idx] = 1; meta->player_ext_types[idx] = 3; } else { #ifdef _WIN32 OutputDebugStringA("unknown player"); #endif SAFE_CHECK_NOT_PASSED() } p->players[idx] = (union H3M_PLAYER *)ab; meta->player_sizes[idx] = size; if (NULL != ctx->callbacks.cb_parse) { ret = ctx->callbacks.cb_parse(orig_off, member, &parsing->raw[orig_off], size, ctx->callbacks.cb_data); } ctx->parsing.offset = orig_off + size; return ret; }