g/jak1: Extract ambient data to json (#3945)
I added extraction of ambients to json files when extracting the levels. All of the ambient json files are written to the same folder as actors are. Ambients aren't used in jak2 and 3 so it only is used on jak1.  --------- Co-authored-by: Tyler Wilding <xtvaser@gmail.com>
This commit is contained in:
parent
012ff7bb16
commit
7320bfc068
|
|
@ -527,6 +527,13 @@ std::string DrawableActor::print(const PrintSettings& /*settings*/, int indent)
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string DrawableAmbient::print(const PrintSettings& /*settings*/, int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
result += fmt::format("{}bsphere: {}", is, bsphere.print_meters());
|
||||
return result;
|
||||
}
|
||||
|
||||
void InstanceTie::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion /*version*/) {
|
||||
|
|
@ -1952,6 +1959,110 @@ void DrawableInlineArrayActor::read_from_file(TypedRef ref,
|
|||
}
|
||||
}
|
||||
|
||||
void EntityAmbient::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion /*version*/) {
|
||||
trans.read_from_file(get_field_ref(ref, "trans", dts));
|
||||
aid = read_plain_data_field<u32>(ref, "aid", dts);
|
||||
// ambientData = read_plain_data_field<u128>(ref, "extra", dts); // to-do: get ambient-data, not
|
||||
// sure if nessecary tho
|
||||
|
||||
int res_length = read_plain_data_field<int32_t>(ref, "length", dts);
|
||||
// int res_allocated_length = read_plain_data_field<int32_t>(ref, "allocated-length", dts);
|
||||
|
||||
auto tags = deref_label(get_field_ref(ref, "tag", dts));
|
||||
auto data_base = deref_label(get_field_ref(ref, "data-base", dts));
|
||||
|
||||
for (int i = 0; i < res_length; i++) {
|
||||
auto& res = res_list.emplace_back();
|
||||
res.name = read_symbol(tags);
|
||||
tags.byte_offset += 4;
|
||||
res.key_frame = deref_float(tags, 0);
|
||||
tags.byte_offset += 4;
|
||||
res.elt_type = read_type(tags);
|
||||
tags.byte_offset += 4;
|
||||
const u32 vals = deref_u32(tags, 0);
|
||||
const u32 offset = vals & 0xffff; // 16 bits
|
||||
res.count = (vals >> 16) & 0x7fff; // 15 bits
|
||||
res.inlined = vals & 0x8000'0000;
|
||||
|
||||
Ref data = data_base;
|
||||
data.byte_offset += offset;
|
||||
|
||||
if (res.elt_type == "string") {
|
||||
ASSERT(!res.inlined);
|
||||
for (int j = 0; j < res.count; j++) {
|
||||
res.strings.push_back(read_string_ref(data));
|
||||
data.byte_offset += 4;
|
||||
}
|
||||
} else if (res.elt_type == "symbol") {
|
||||
ASSERT(!res.inlined);
|
||||
for (int j = 0; j < res.count; j++) {
|
||||
res.strings.push_back(read_symbol(data));
|
||||
data.byte_offset += 4;
|
||||
}
|
||||
} else if (res.elt_type == "type") {
|
||||
ASSERT(!res.inlined);
|
||||
for (int j = 0; j < res.count; j++) {
|
||||
res.strings.push_back(read_type(data));
|
||||
data.byte_offset += 4;
|
||||
}
|
||||
} else if (res.elt_type == "vector") {
|
||||
ASSERT(res.inlined);
|
||||
res.inlined_storage = bytes_from_plain_data(data, 16 * res.count);
|
||||
} else if (res.elt_type == "float") {
|
||||
fill_res_with_value_types<float>(res, data);
|
||||
} else if (res.elt_type == "int32") {
|
||||
fill_res_with_value_types<int32_t>(res, data);
|
||||
} else if (res.elt_type == "int16") {
|
||||
fill_res_with_value_types<int16_t>(res, data);
|
||||
} else if (res.elt_type == "int8") {
|
||||
fill_res_with_value_types<int8_t>(res, data);
|
||||
} else if (res.elt_type == "uint32") {
|
||||
fill_res_with_value_types<uint32_t>(res, data);
|
||||
} else if (res.elt_type == "uint8") {
|
||||
fill_res_with_value_types<uint8_t>(res, data);
|
||||
} else if (res.elt_type == "actor-group") {
|
||||
// TODO: unsupported.
|
||||
} else if (res.elt_type == "pair") {
|
||||
ASSERT(res.count == 1);
|
||||
ASSERT(!res.inlined);
|
||||
data = deref_label(data);
|
||||
res.script = data.data->to_form_script(data.seg, (data.byte_offset) / 4, nullptr);
|
||||
} else {
|
||||
fmt::print("unhandled elt_type: {}\n", res.elt_type);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
tags.byte_offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableAmbient::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion version) {
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
ambient.read_from_file(get_and_check_ref_to_basic(ref, "ambient", "entity-ambient", dts), dts,
|
||||
version);
|
||||
}
|
||||
|
||||
void DrawableInlineArrayAmbient::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion version) {
|
||||
int numAmbients = read_plain_data_field<int16_t>(ref, "length", dts);
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
for (int i = 0; i < numAmbients; i++) {
|
||||
Ref obj_ref = data_ref;
|
||||
obj_ref.byte_offset += 32 * i; // todo not a constant here
|
||||
auto type = get_type_of_basic(obj_ref);
|
||||
if (type != "drawable-ambient") {
|
||||
throw Error("bad drawable-ambient type: {}", type);
|
||||
}
|
||||
drawable_ambients.emplace_back();
|
||||
drawable_ambients.back().read_from_file(typed_ref_from_basic(obj_ref, dts), dts, version);
|
||||
}
|
||||
}
|
||||
|
||||
void CollideHash::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion /*version*/) {
|
||||
|
|
@ -2065,6 +2176,11 @@ void BspHeader::read_from_file(const decompiler::LinkedObjectFile& file,
|
|||
actors.read_from_file(
|
||||
get_and_check_ref_to_basic(ref, "actors", "drawable-inline-array-actor", dts), dts,
|
||||
version);
|
||||
if (get_word_kind_for_field(ref, "ambients", dts) == decompiler::LinkedWord::PTR) {
|
||||
ambients.read_from_file(
|
||||
get_and_check_ref_to_basic(ref, "ambients", "drawable-inline-array-ambient", dts), dts,
|
||||
version);
|
||||
}
|
||||
}
|
||||
|
||||
if (version > GameVersion::Jak1 &&
|
||||
|
|
|
|||
|
|
@ -189,6 +189,31 @@ struct DrawableActor : public Drawable {
|
|||
std::string my_type() const override { return "drawable-actor"; }
|
||||
};
|
||||
|
||||
struct EntityAmbient {
|
||||
Vector trans;
|
||||
u32 aid = 0;
|
||||
|
||||
u128 ambientData;
|
||||
|
||||
std::vector<Res> res_list;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion version);
|
||||
};
|
||||
|
||||
struct DrawableAmbient : public Drawable {
|
||||
Vector bsphere;
|
||||
|
||||
EntityAmbient ambient;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion version) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "drawable-ambient"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeActor : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
|
|
@ -765,6 +790,13 @@ struct DrawableInlineArrayActor {
|
|||
GameVersion version);
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayAmbient {
|
||||
std::vector<DrawableAmbient> drawable_ambients;
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
GameVersion version);
|
||||
};
|
||||
|
||||
struct CollideHash {
|
||||
Ref item_array;
|
||||
int num_items = 0;
|
||||
|
|
@ -912,6 +944,7 @@ struct BspHeader {
|
|||
// (boxes box8s-array :offset-assert 148)
|
||||
// (current-bsp-back-flags uint32 :offset-assert 152)
|
||||
// (ambients drawable-inline-array-ambient :offset-assert 156)
|
||||
DrawableInlineArrayAmbient ambients;
|
||||
// (unk-data-4 float :offset-assert 160)
|
||||
// (unk-data-5 float :offset-assert 164)
|
||||
// (adgifs adgif-shader-array :offset-assert 168)
|
||||
|
|
|
|||
|
|
@ -146,4 +146,95 @@ std::string extract_actors_to_json(const level_tools::DrawableInlineArrayActor&
|
|||
return json.dump(2);
|
||||
}
|
||||
|
||||
std::string extract_ambients_to_json(const level_tools::DrawableInlineArrayAmbient& actors) {
|
||||
nlohmann::json json;
|
||||
|
||||
for (const auto& damb : actors.drawable_ambients) {
|
||||
const auto& ambient = damb.ambient;
|
||||
auto& json_ambient = json.emplace_back();
|
||||
json_ambient["bsphere"] = vectorm_json(damb.bsphere);
|
||||
// drawable ID?
|
||||
|
||||
json_ambient["trans"] = vectorm_json(ambient.trans);
|
||||
json_ambient["aid"] = ambient.aid; // aid
|
||||
|
||||
auto& json_lump = json_ambient["lump"];
|
||||
|
||||
nlohmann::json effects;
|
||||
int effectCount = 0,
|
||||
effectParamCount =
|
||||
0; // just to keep track since names cound all be together and then params
|
||||
|
||||
for (const auto& res : ambient.res_list) {
|
||||
if (res.elt_type == "string") {
|
||||
if (res.name == "name")
|
||||
json_lump[res.name] = strings_json(res.strings, false);
|
||||
else
|
||||
json_lump[res.name] = strings_json(res.strings, true);
|
||||
} else if (res.elt_type == "symbol") {
|
||||
if (res.name == "effect-name") {
|
||||
if (++effectCount > effectParamCount) {
|
||||
nlohmann::json effect;
|
||||
effect["name"] = strings_json(res.strings, false);
|
||||
effects.push_back(effect);
|
||||
} else {
|
||||
auto& effect = effects[effectCount - 1];
|
||||
effect["name"] = strings_json(res.strings, false);
|
||||
}
|
||||
} else {
|
||||
json_lump[res.name] = strings_json(res.strings, false);
|
||||
}
|
||||
} else if (res.elt_type == "type") {
|
||||
// TODO: confusion with symbols
|
||||
json_lump[res.name] = strings_json(res.strings, true);
|
||||
} else if (res.elt_type == "vector") {
|
||||
const float* data = (const float*)res.inlined_storage.data();
|
||||
if (res.count == 1) {
|
||||
json_lump[res.name] = vector_json(data);
|
||||
} else {
|
||||
for (int i = 0; i < res.count; i++) {
|
||||
json_lump[res.name].push_back(vector_json(data + 4 * i));
|
||||
}
|
||||
}
|
||||
} else if (res.elt_type == "pair") {
|
||||
json_lump[res.name] = pretty_print::to_string(res.script);
|
||||
} else if (res.elt_type == "float") {
|
||||
if (res.name == "effect-param") {
|
||||
if (++effectParamCount > effectCount) {
|
||||
nlohmann::json effect;
|
||||
effect["params"] = value_json<float>(res.inlined_storage, res.count);
|
||||
effects.push_back(effect);
|
||||
} else {
|
||||
auto& effect = effects[effectParamCount - 1];
|
||||
effect["params"] = value_json<float>(res.inlined_storage, res.count);
|
||||
}
|
||||
} else {
|
||||
json_lump[res.name] = value_json<float>(res.inlined_storage, res.count);
|
||||
}
|
||||
} else if (res.elt_type == "int32") {
|
||||
json_lump[res.name] = value_json<int32_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "int16") {
|
||||
json_lump[res.name] = value_json<int16_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "int8") {
|
||||
json_lump[res.name] = value_json<int8_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "uint32") {
|
||||
json_lump[res.name] = value_json<uint32_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "uint16") {
|
||||
json_lump[res.name] = value_json<uint16_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "uint8") {
|
||||
json_lump[res.name] = value_json<uint8_t>(res.inlined_storage, res.count);
|
||||
} else if (res.elt_type == "actor-group") {
|
||||
// not supported.
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
if (effectCount || effectParamCount)
|
||||
json_lump["effects"] = effects;
|
||||
}
|
||||
|
||||
return json.dump(2);
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@
|
|||
namespace decompiler {
|
||||
|
||||
std::string extract_actors_to_json(const level_tools::DrawableInlineArrayActor& actors);
|
||||
std::string extract_ambients_to_json(const level_tools::DrawableInlineArrayAmbient& actors);
|
||||
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
|
|
|||
|
|
@ -389,6 +389,10 @@ void extract_from_level(const ObjectFileDB& db,
|
|||
}
|
||||
file_util::write_text_file(entities_folder / fmt::format("{}-actors.json", level_data.level_name),
|
||||
extract_actors_to_json(bsp_header.actors));
|
||||
if (config.game_version == GameVersion::Jak1)
|
||||
file_util::write_text_file(
|
||||
entities_folder / fmt::format("{}-ambients.json", level_data.level_name),
|
||||
extract_ambients_to_json(bsp_header.ambients));
|
||||
}
|
||||
|
||||
void extract_all_levels(const ObjectFileDB& db,
|
||||
|
|
|
|||
Loading…
Reference in New Issue