Files
korenkonder_ReDIVA/src/CRE/Glitter/file_writer.cpp
T
2022-10-03 15:54:28 +03:00

1309 lines
51 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "glitter.hpp"
#include "../../KKdLib/io/file_stream.hpp"
#include "../../KKdLib/io/path.hpp"
#include "../../KKdLib/interpolation.hpp"
#include "../../KKdLib/farc.hpp"
#include "../../KKdLib/str_utils.hpp"
#include "../data.hpp"
namespace Glitter {
FileWriter::FileWriter() : type() {
}
void FileWriter::PackCurve(f2_struct* st, Curve* c, bool big_endian) {
if (!c->keys.size()) {
st->header.signature = reverse_endianness_uint32_t('KEYS');
st->header.length = 0x20;
st->header.use_big_endian = false;
st->header.use_section_size = true;
st->header.version = c->keys_version;
return;
}
size_t l = 0;
uint32_t o;
enrs e;
enrs_entry ee;
size_t count;
if (c->flags & CURVE_KEY_RANDOM_RANGE) {
KeyType key_type = c->keys.front().type;
if (key_type == KEY_HERMITE) {
ee = { 0, 2, 20, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 4, ENRS_DWORD);
l = 20;
}
else {
ee = { 0, 2, 12, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 2, ENRS_DWORD);
l = 12;
}
count = 1;
Curve::Key* i_begin = c->keys.data() + 1;
Curve::Key* i_end = c->keys.data() + c->keys.size();
for (Curve::Key* i = i_begin; i != i_end;
i++, count++, l += key_type == KEY_HERMITE ? 20 : 12) {
if (i->type == key_type)
continue;
if (count > 0) {
ee.repeat_count = (uint32_t)count;
e.vec.push_back(ee);
}
count = 1;
o = (uint32_t)((key_type == KEY_HERMITE ? 20 : 12) * count);
if (i->type == KEY_HERMITE) {
ee = { o, 2, 20, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 4, ENRS_DWORD);
}
else {
ee = { o, 2, 12, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 2, ENRS_DWORD);
}
key_type = i->type;
}
}
else {
KeyType key_type = c->keys.front().type;
if (key_type == KEY_HERMITE) {
ee = { 0, 2, 16, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 3, ENRS_DWORD);
l = 16;
}
else {
ee = { 0, 2, 8, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 1, ENRS_DWORD);
l = 8;
}
count = 1;
Curve::Key* i_begin = c->keys.data() + 1;
Curve::Key* i_end = c->keys.data() + c->keys.size();
for (Curve::Key* i = i_begin; i != i_end;
i++, count++, l += key_type == KEY_HERMITE ? 16 : 8) {
if (i->type == key_type)
continue;
if (count > 0) {
ee.repeat_count = (uint32_t)count;
e.vec.push_back(ee);
}
count = 1;
o = (uint32_t)((key_type == KEY_HERMITE ? 16 : 8) * count);
if (i->type == KEY_HERMITE) {
ee = { o, 2, 16, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 3, ENRS_DWORD);
}
else {
ee = { o, 2, 8, 1 };
ee.append(0, 2, ENRS_WORD);
ee.append(0, 1, ENRS_DWORD);
}
key_type = i->type;
}
}
if (count > 0) {
ee.repeat_count = (uint32_t)count;
e.vec.push_back(ee);
}
float_t scale = 1.0f;
if (c->keys_version == 0)
switch (c->type) {
case CURVE_ROTATION_X:
case CURVE_ROTATION_Y:
case CURVE_ROTATION_Z:
scale = RAD_TO_DEG_FLOAT;
break;
case CURVE_COLOR_R:
case CURVE_COLOR_G:
case CURVE_COLOR_B:
case CURVE_COLOR_A:
scale = 255.0f;
break;
}
l = align_val(l, 0x10);
st->data.resize(l);
size_t d = (size_t)st->data.data();
if (scale == 1.0f) {
if (big_endian)
if (c->flags & CURVE_KEY_RANDOM_RANGE)
for (Curve::Key& i : c->keys) {
store_reverse_endianness_int16_t((int16_t*)d, (int16_t)i.type);
store_reverse_endianness_int16_t((int16_t*)(d + 2), (int16_t)i.frame);
if (i.type == KEY_HERMITE) {
store_reverse_endianness_float_t((float_t*)(d + 4), i.tangent1);
store_reverse_endianness_float_t((float_t*)(d + 8), i.tangent2);
store_reverse_endianness_float_t((float_t*)(d + 12), i.random_range);
store_reverse_endianness_float_t((float_t*)(d + 16), i.value);
d += 20;
}
else {
store_reverse_endianness_float_t((float_t*)(d + 4), i.random_range);
store_reverse_endianness_float_t((float_t*)(d + 8), i.value);
d += 12;
}
}
else
for (Curve::Key& i : c->keys) {
store_reverse_endianness_int16_t((int16_t*)d, (int16_t)i.type);
store_reverse_endianness_int16_t((int16_t*)(d + 2), (int16_t)i.frame);
if (i.type == KEY_HERMITE) {
store_reverse_endianness_float_t((float_t*)(d + 4), i.tangent1);
store_reverse_endianness_float_t((float_t*)(d + 8), i.tangent2);
store_reverse_endianness_float_t((float_t*)(d + 12), i.value);
d += 16;
}
else {
store_reverse_endianness_float_t((float_t*)(d + 4), i.value);
d += 8;
}
}
else
if (c->flags & CURVE_KEY_RANDOM_RANGE)
for (Curve::Key& i : c->keys) {
*(int16_t*)d = (int16_t)i.type;
*(int16_t*)(d + 2) = (int16_t)i.frame;
if (i.type == KEY_HERMITE) {
*(float_t*)(d + 4) = i.tangent1;
*(float_t*)(d + 8) = i.tangent2;
*(float_t*)(d + 12) = i.random_range;
*(float_t*)(d + 16) = i.value;
d += 20;
}
else {
*(float_t*)(d + 4) = i.random_range;
*(float_t*)(d + 8) = i.value;
d += 12;
}
}
else
for (Curve::Key& i : c->keys) {
*(int16_t*)d = (int16_t)i.type;
*(int16_t*)(d + 2) = (int16_t)i.frame;
if (i.type == KEY_HERMITE) {
*(float_t*)(d + 4) = i.tangent1;
*(float_t*)(d + 8) = i.tangent2;
*(float_t*)(d + 12) = i.value;
d += 16;
}
else {
*(float_t*)(d + 4) = i.value;
d += 8;
}
}
}
else {
if (big_endian)
if (c->flags & CURVE_KEY_RANDOM_RANGE)
for (Curve::Key& i : c->keys) {
store_reverse_endianness_int16_t((int16_t*)d, (int16_t)i.type);
store_reverse_endianness_int16_t((int16_t*)(d + 2), (int16_t)i.frame);
if (i.type == KEY_HERMITE) {
store_reverse_endianness_float_t((float_t*)(d + 4), i.tangent1 * scale);
store_reverse_endianness_float_t((float_t*)(d + 8), i.tangent2 * scale);
store_reverse_endianness_float_t((float_t*)(d + 12), i.random_range * scale);
store_reverse_endianness_float_t((float_t*)(d + 16), i.value * scale);
d += 20;
}
else {
store_reverse_endianness_float_t((float_t*)(d + 4), i.random_range * scale);
store_reverse_endianness_float_t((float_t*)(d + 8), i.value * scale);
d += 12;
}
}
else
for (Curve::Key& i : c->keys) {
store_reverse_endianness_int16_t((int16_t*)d, (int16_t)i.type);
store_reverse_endianness_int16_t((int16_t*)(d + 2), (int16_t)i.frame);
if (i.type == KEY_HERMITE) {
store_reverse_endianness_float_t((float_t*)(d + 4), i.tangent1 * scale);
store_reverse_endianness_float_t((float_t*)(d + 8), i.tangent2 * scale);
store_reverse_endianness_float_t((float_t*)(d + 12), i.value * scale);
d += 16;
}
else {
store_reverse_endianness_float_t((float_t*)(d + 4), i.value * scale);
d += 8;
}
}
else
if (c->flags & CURVE_KEY_RANDOM_RANGE)
for (Curve::Key& i : c->keys) {
*(int16_t*)d = (int16_t)i.type;
*(int16_t*)(d + 2) = (int16_t)i.frame;
if (i.type == KEY_HERMITE) {
*(float_t*)(d + 4) = i.tangent1 * scale;
*(float_t*)(d + 8) = i.tangent2 * scale;
*(float_t*)(d + 12) = i.random_range * scale;
*(float_t*)(d + 16) = i.value * scale;
d += 20;
}
else {
*(float_t*)(d + 4) = i.random_range * scale;
*(float_t*)(d + 8) = i.value * scale;
d += 12;
}
}
else
for (Curve::Key& i : c->keys) {
*(int16_t*)d = (int16_t)i.type;
*(int16_t*)(d + 2) = (int16_t)i.frame;
if (i.type == KEY_HERMITE) {
*(float_t*)(d + 4) = i.tangent1 * scale;
*(float_t*)(d + 8) = i.tangent2 * scale;
*(float_t*)(d + 12) = i.value * scale;
d += 16;
}
else {
*(float_t*)(d + 4) = i.value * scale;
d += 8;
}
}
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('KEYS');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
st->header.version = c->keys_version;
}
bool FileWriter::PackDivaList(EffectGroup* eff_group, f2_struct* st, bool big_endian) {
if (!eff_group->effects.size())
return false;
enrs e;
enrs_entry ee;
ee = { 0, 1, 4, 1 };
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
size_t length = 0;
for (Effect*& i : eff_group->effects)
if (i)
length++;
st->data.resize(0x10 + 0x80 * length);
size_t d = (size_t)st->data.data();
if (big_endian)
store_reverse_endianness_uint32_t((uint32_t*)d, (uint32_t)length);
else
*(uint32_t*)d = (uint32_t)length;
d += 4;
for (Effect*& i : eff_group->effects)
if (i) {
size_t size = min_def(i->name.size(), 0x7F);
memcpy((void*)d, i->name.c_str(), size);
memset((void*)(d + size), 0, 0x80 - size);
d += 0x80;
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('GEFF');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
return true;
}
bool FileWriter::PackDivaResource(EffectGroup* eff_group, f2_struct* st) {
if (eff_group->resources_tex.textures.size() < 1)
return false;
if (!eff_group->resources_tex.produce_enrs(&st->enrs))
return false;
eff_group->resources_tex.pack_file(st->data, false);
st->header.signature = reverse_endianness_uint32_t('TXPC');
st->header.length = 0x20;
st->header.use_big_endian = false;
st->header.use_section_size = true;
return true;
}
bool FileWriter::PackDivaResourceHashes(EffectGroup* eff_group, f2_struct* st, bool big_endian) {
if (eff_group->effects.size() < 1 || !eff_group->resources_count
|| eff_group->resource_hashes.size() < 1)
return false;
size_t count = eff_group->resources_count;
size_t l = 0;
enrs e;
enrs_entry ee;
ee = { 0, 2, (uint32_t)(8 + count * 8), 1 };
ee.append(0, 1, ENRS_DWORD);
ee.append(4, (uint32_t)count, ENRS_QWORD);
e.vec.push_back(ee);
l += 8 + count * 8;
l = align_val(l, 0x10);
st->data.resize(l);
size_t d = (size_t)st->data.data();
if (big_endian)
store_reverse_endianness_int32_t((int32_t*)d, (int32_t)count);
else
*(int32_t*)d = (int32_t)count;
*(int32_t*)(d + 4) = 0;
d += 8;
if (big_endian) {
uint64_t* hashes_src = eff_group->resource_hashes.data();
uint64_t* hashes_dst = (uint64_t*)(void*)d;
for (size_t i = 0; i < count; i++)
store_reverse_endianness_uint64_t(hashes_dst++, *hashes_src++);
}
else
memcpy((void*)d, eff_group->resource_hashes.data(), sizeof(uint64_t) * count);
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('DVRS');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
return true;
}
bool FileWriter::PackEffect(f2_struct* st, Effect* eff, bool big_endian) {
if (eff->version != 6 && eff->version != 7)
return false;
Effect::ExtAnim* ext_anim = eff->data.ext_anim;
size_t l = 0;
uint32_t o;
enrs e;
enrs_entry ee;
ee = { 0, 2, 56, 1 };
ee.append(0, 1, ENRS_QWORD);
ee.append(0, 12, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 56;
if (eff->version == 7) {
ee = { 0, 1, 4, 1 };
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 4;
}
ee = { 0, 1, 4, 1 };
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 4;
if (~eff->data.flags & EFFECT_LOCAL && ext_anim)
if (ext_anim->flags & EFFECT_EXT_ANIM_CHARA_ANIM) {
ee = { 0, 1, 12, 1 };
ee.append(0, 3, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 12;
}
else {
ee = { 0, 2, 140, 1 };
ee.append(0, 1, ENRS_QWORD);
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 140;
}
l = align_val(l, 0x10);
st->data.resize(l);
size_t d = (size_t)st->data.data();
EffectFileFlag flags = (EffectFileFlag)0;
if (eff->data.flags & EFFECT_ALPHA)
enum_or(flags, EFFECT_FILE_ALPHA);
if (eff->data.flags & EFFECT_FOG)
enum_or(flags, EFFECT_FILE_FOG);
else if (eff->data.flags & EFFECT_FOG_HEIGHT)
enum_or(flags, EFFECT_FILE_FOG_HEIGHT);
if (eff->data.flags & EFFECT_EMISSION)
enum_or(flags, EFFECT_FILE_EMISSION);
if (big_endian) {
store_reverse_endianness_uint64_t((uint64_t*)d, type != Glitter::FT
? hash_string_murmurhash(eff->name) : hash_string_fnv1a64m(eff->name));
store_reverse_endianness_int32_t((int32_t*)(d + 8), eff->data.appear_time);
store_reverse_endianness_int32_t((int32_t*)(d + 12), eff->data.life_time);
store_reverse_endianness_int32_t((int32_t*)(d + 16), eff->data.start_time);
store_reverse_endianness_int32_t((int32_t*)(d + 20), 0xFFFFFFFF);
store_reverse_endianness_int32_t((int32_t*)(d + 24), eff->data.flags & EFFECT_LOOP ? 1 : 0);
store_reverse_endianness_float_t((float_t*)(d + 28), eff->translation.x);
store_reverse_endianness_float_t((float_t*)(d + 32), eff->translation.y);
store_reverse_endianness_float_t((float_t*)(d + 36), eff->translation.z);
store_reverse_endianness_float_t((float_t*)(d + 40), eff->rotation.x);
store_reverse_endianness_float_t((float_t*)(d + 40), eff->rotation.y);
store_reverse_endianness_float_t((float_t*)(d + 40), eff->rotation.z);
store_reverse_endianness_int32_t((int32_t*)(d + 52), flags);
}
else {
*(uint64_t*)d = type != Glitter::FT
? hash_string_murmurhash(eff->name) : hash_string_fnv1a64m(eff->name);
*(int32_t*)(d + 8) = eff->data.appear_time;
*(int32_t*)(d + 12) = eff->data.life_time;
*(int32_t*)(d + 16) = eff->data.start_time;
*(int32_t*)(d + 20) = 0xFFFFFFFF;
*(int32_t*)(d + 24) = eff->data.flags & EFFECT_LOOP ? 1 : 0;
*(vec3*)(d + 28) = eff->translation;
*(vec3*)(d + 40) = eff->rotation;
*(int32_t*)(d + 52) = flags;
}
d += 56;
if (eff->version == 7) {
if (big_endian)
store_reverse_endianness_float_t((float_t*)d, eff->data.emission);
else
*(float_t*)d = eff->data.emission;
d += 4;
}
if (eff->data.flags & EFFECT_LOCAL) {
if (big_endian)
store_reverse_endianness_int32_t((int32_t*)d, 1);
else
*(int32_t*)d = 1;
d += 4;
}
else if (ext_anim) {
if (ext_anim->flags & EFFECT_EXT_ANIM_CHARA_ANIM) {
if (big_endian)
store_reverse_endianness_int32_t((int32_t*)d, 2);
else
*(int32_t*)d = 2;
d += 4;
EffectExtAnimFlag ext_anim_flag = ext_anim->flags;
enum_and(ext_anim_flag, ~EFFECT_EXT_ANIM_CHARA_ANIM);
if (big_endian) {
store_reverse_endianness_int32_t((int32_t*)d, ext_anim->chara_index);
store_reverse_endianness_int32_t((int32_t*)(d + 4), ext_anim_flag);
store_reverse_endianness_int32_t((int32_t*)(d + 8), ext_anim->node_index);
}
else {
*(int32_t*)d = ext_anim->chara_index;
*(int32_t*)(d + 4) = ext_anim_flag;
*(int32_t*)(d + 8) = ext_anim->node_index;
}
}
else {
if (big_endian)
store_reverse_endianness_int32_t((int32_t*)d, 3);
else
*(int32_t*)d = 3;
d += 4;
if (big_endian) {
store_reverse_endianness_uint64_t((uint64_t*)d, ext_anim->object_hash);
store_reverse_endianness_int32_t((int32_t*)(d + 8), ext_anim->flags);
}
else {
*(uint64_t*)d = ext_anim->object_hash;
*(int32_t*)(d + 8) = ext_anim->flags;
}
strncpy_s((char*)(d + 12), 0x80, ext_anim->mesh_name, 0x80);
((char*)(d + 12))[0x7F] = '\0';
}
}
else {
*(int32_t*)d = 0;
d += 4;
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('EFCT');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
st->header.version = eff->version;
return true;
}
bool FileWriter::PackEmitter(f2_struct* st, Emitter* emit, bool big_endian) {
if (emit->version != 1 && emit->version != 2)
return false;
switch (emit->data.type) {
case EMITTER_BOX:
case EMITTER_CYLINDER:
case EMITTER_SPHERE:
case EMITTER_POLYGON:
break;
default:
return false;
}
size_t l = 0;
uint32_t o;
enrs e;
enrs_entry ee;
ee = { 0, 5, 96, 1 };
ee.append(0, 5, ENRS_DWORD);
ee.append(0, 2, ENRS_WORD);
ee.append(0, 2, ENRS_DWORD);
ee.append(0, 2, ENRS_WORD);
ee.append(0, 15, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 96;
switch (emit->data.type) {
case EMITTER_BOX:
ee = { o, 1, 12, 1 };
ee.append(0, 3, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 12;
break;
case EMITTER_CYLINDER:
ee = { o, 1, 20, 1 };
ee.append(0, 5, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 20;
break;
case EMITTER_SPHERE:
ee = { o, 1, 16, 1 };
ee.append(0, 4, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 16;
break;
case EMITTER_POLYGON:
ee = { o, 1, 8, 1 };
ee.append(0, 2, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 8;
break;
}
l = align_val(l, 0x10);
st->data.resize(l);
size_t d = (size_t)st->data.data();
if (big_endian) {
store_reverse_endianness_int32_t((int32_t*)d, emit->data.start_time);
store_reverse_endianness_int32_t((int32_t*)(d + 4), emit->data.life_time);
store_reverse_endianness_int32_t((int32_t*)(d + 8), emit->data.loop_start_time);
store_reverse_endianness_int32_t((int32_t*)(d + 12), emit->data.loop_end_time);
store_reverse_endianness_int32_t((int32_t*)(d + 16), emit->data.flags);
store_reverse_endianness_int32_t((int16_t*)(d + 20), (int16_t)emit->data.type);
store_reverse_endianness_int32_t((int16_t*)(d + 22), (int16_t)emit->data.direction);
store_reverse_endianness_float_t((float_t*)(d + 24), emit->data.emission_interval);
store_reverse_endianness_float_t((float_t*)(d + 28), emit->data.particles_per_emission);
store_reverse_endianness_int16_t((int16_t*)(d + 32), (uint16_t)0);
store_reverse_endianness_int16_t((int16_t*)(d + 34), (uint16_t)0);
store_reverse_endianness_float_t((float_t*)(d + 36), emit->translation.x);
store_reverse_endianness_float_t((float_t*)(d + 40), emit->translation.y);
store_reverse_endianness_float_t((float_t*)(d + 44), emit->translation.z);
store_reverse_endianness_float_t((float_t*)(d + 48), emit->rotation.x);
store_reverse_endianness_float_t((float_t*)(d + 52), emit->rotation.y);
store_reverse_endianness_float_t((float_t*)(d + 56), emit->rotation.z);
store_reverse_endianness_float_t((float_t*)(d + 60), emit->scale.x);
store_reverse_endianness_float_t((float_t*)(d + 64), emit->scale.y);
store_reverse_endianness_float_t((float_t*)(d + 68), emit->scale.z);
store_reverse_endianness_float_t((float_t*)(d + 72), emit->data.rotation_add.x);
store_reverse_endianness_float_t((float_t*)(d + 76), emit->data.rotation_add.y);
store_reverse_endianness_float_t((float_t*)(d + 80), emit->data.rotation_add.z);
store_reverse_endianness_float_t((float_t*)(d + 84), emit->data.rotation_add_random.x);
store_reverse_endianness_float_t((float_t*)(d + 88), emit->data.rotation_add_random.y);
store_reverse_endianness_float_t((float_t*)(d + 92), emit->data.rotation_add_random.z);
}
else {
*(int32_t*)d = emit->data.start_time;
*(int32_t*)(d + 4) = emit->data.life_time;
*(int32_t*)(d + 8) = emit->data.loop_start_time;
*(int32_t*)(d + 12) = emit->data.loop_end_time;
*(int32_t*)(d + 16) = emit->data.flags;
*(int16_t*)(d + 20) = (int16_t)emit->data.type;
*(int16_t*)(d + 22) = (int16_t)emit->data.direction;
*(float_t*)(d + 24) = emit->data.emission_interval;
*(float_t*)(d + 28) = emit->data.particles_per_emission;
*(int16_t*)(d + 32) = 0;
*(int16_t*)(d + 34) = 0;
*(vec3*)(d + 36) = emit->translation;
*(vec3*)(d + 48) = emit->rotation;
*(vec3*)(d + 60) = emit->scale;
*(vec3*)(d + 72) = emit->data.rotation_add;
*(vec3*)(d + 84) = emit->data.rotation_add_random;
}
d += 96;
switch (emit->data.type) {
case EMITTER_BOX:
if (big_endian) {
store_reverse_endianness_float_t((float_t*)d, emit->data.box.size.x);
store_reverse_endianness_float_t((float_t*)(d + 4), emit->data.box.size.y);
store_reverse_endianness_float_t((float_t*)(d + 8), emit->data.box.size.z);
}
else
*(vec3*)d = emit->data.box.size;
break;
case EMITTER_CYLINDER:
if (big_endian) {
store_reverse_endianness_float_t((float_t*)d, emit->data.cylinder.radius);
store_reverse_endianness_float_t((float_t*)(d + 4), emit->data.cylinder.height);
store_reverse_endianness_float_t((float_t*)(d + 8), emit->data.cylinder.start_angle);
store_reverse_endianness_float_t((float_t*)(d + 12), emit->data.cylinder.end_angle);
store_reverse_endianness_int32_t((int32_t*)(d + 16), ((int32_t)emit->data.cylinder.direction << 1)
| (emit->data.cylinder.on_edge ? 1 : 0));
}
else {
*(float_t*)d = emit->data.cylinder.radius;
*(float_t*)(d + 4) = emit->data.cylinder.height;
*(float_t*)(d + 8) = emit->data.cylinder.start_angle;
*(float_t*)(d + 12) = emit->data.cylinder.end_angle;
*(int32_t*)(d + 16) = ((int32_t)emit->data.cylinder.direction << 1)
| (emit->data.cylinder.on_edge ? 1 : 0);
}
break;
case EMITTER_SPHERE:
if (big_endian) {
store_reverse_endianness_float_t((float_t*)d, emit->data.sphere.radius);
store_reverse_endianness_float_t((float_t*)(d + 4), emit->data.sphere.latitude);
store_reverse_endianness_float_t((float_t*)(d + 8), emit->data.sphere.longitude);
store_reverse_endianness_int32_t((int32_t*)(d + 12), ((int32_t)emit->data.sphere.direction << 1)
| (emit->data.sphere.on_edge ? 1 : 0));
}
else {
*(float_t*)d = emit->data.sphere.radius;
*(float_t*)(d + 4) = emit->data.sphere.latitude;
*(float_t*)(d + 8) = emit->data.sphere.longitude;
*(int32_t*)(d + 12) = ((int32_t)emit->data.sphere.direction << 1)
| (emit->data.sphere.on_edge ? 1 : 0);
}
break;
case EMITTER_POLYGON:
if (big_endian) {
store_reverse_endianness_float_t((float_t*)d, emit->data.polygon.size);
store_reverse_endianness_int32_t((int32_t*)(d + 4), emit->data.polygon.count);
}
else {
*(float_t*)d = emit->data.polygon.size;
*(int32_t*)(d + 4) = emit->data.polygon.count;
}
break;
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('EMIT');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
st->header.version = emit->version;
return true;
}
bool FileWriter::PackParticle(EffectGroup* eff_group,
f2_struct* st, Particle* ptcl, Effect* eff, bool big_endian) {
if (ptcl->version < 2)
return false;
size_t l = 0;
uint32_t o;
enrs e;
enrs_entry ee;
ee = { 0, 1, 204, 1 };
ee.append(0, 51, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 204;
if (ptcl->version == 3) {
ee = { o, 1, 8, 1 };
ee.append(0, 2, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 8;
}
if (ptcl->data.type == PARTICLE_LOCUS || ptcl->data.type == PARTICLE_MESH) {
ee = { o, 1, 4, 1 };
ee.append(0, 2, ENRS_WORD);
e.vec.push_back(ee);
l += o = 4;
}
ee = { o, 4, 44, 1 };
ee.append(0, 1, ENRS_QWORD);
ee.append(4, 5, ENRS_DWORD);
ee.append(0, 2, ENRS_WORD);
ee.append(0, 2, ENRS_DWORD);
if (eff_group->version >= 7) {
ee.count++;
ee.size += 4;
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 48;
}
else {
e.vec.push_back(ee);
l += o = 44;
}
ee = { o, 2, 12, 1 };
ee.append(0, 1, ENRS_QWORD);
ee.append(0, 1, ENRS_DWORD);
e.vec.push_back(ee);
l += o = 12;
l = align_val(l, 0x10);
st->data.resize(l);
size_t d = (size_t)st->data.data();
ParticleFlag flags = ptcl->data.flags;
if (eff->data.flags & EFFECT_LOCAL)
enum_and(flags, ~PARTICLE_LOCAL);
if (eff->data.flags & EFFECT_EMISSION)
enum_and(flags, ~PARTICLE_EMISSION);
ParticleType type;
if (ptcl->data.type == PARTICLE_LINE)
type = PARTICLE_MESH;
else if (ptcl->data.type == PARTICLE_MESH)
type = PARTICLE_LINE;
else
type = ptcl->data.type;
if (big_endian) {
store_reverse_endianness_int32_t((int32_t*)d, ptcl->data.life_time);
store_reverse_endianness_int32_t((int32_t*)(d + 4), type);
store_reverse_endianness_int32_t((int32_t*)(d + 8), ptcl->data.draw_type);
store_reverse_endianness_float_t((float_t*)(d + 12), ptcl->data.rotation.x);
store_reverse_endianness_float_t((float_t*)(d + 16), ptcl->data.rotation.y);
store_reverse_endianness_float_t((float_t*)(d + 20), ptcl->data.rotation.z);
store_reverse_endianness_float_t((float_t*)(d + 24), ptcl->data.rotation_random.x);
store_reverse_endianness_float_t((float_t*)(d + 28), ptcl->data.rotation_random.y);
store_reverse_endianness_float_t((float_t*)(d + 32), ptcl->data.rotation_random.z);
store_reverse_endianness_float_t((float_t*)(d + 36), ptcl->data.rotation_add.x);
store_reverse_endianness_float_t((float_t*)(d + 40), ptcl->data.rotation_add.y);
store_reverse_endianness_float_t((float_t*)(d + 44), ptcl->data.rotation_add.z);
store_reverse_endianness_float_t((float_t*)(d + 48), ptcl->data.rotation_add_random.x);
store_reverse_endianness_float_t((float_t*)(d + 52), ptcl->data.rotation_add_random.y);
store_reverse_endianness_float_t((float_t*)(d + 56), ptcl->data.rotation_add_random.z);
store_reverse_endianness_float_t((float_t*)(d + 60), ptcl->data.scale.x);
store_reverse_endianness_float_t((float_t*)(d + 64), ptcl->data.scale.y);
store_reverse_endianness_float_t((float_t*)(d + 68), ptcl->data.scale.z);
store_reverse_endianness_float_t((float_t*)(d + 72), ptcl->data.scale_random.x);
store_reverse_endianness_float_t((float_t*)(d + 76), ptcl->data.scale_random.y);
store_reverse_endianness_float_t((float_t*)(d + 80), ptcl->data.scale_random.z);
store_reverse_endianness_float_t((float_t*)(d + 84), ptcl->data.z_offset);
store_reverse_endianness_int32_t((int32_t*)(d + 88), ptcl->data.pivot);
store_reverse_endianness_int32_t((int32_t*)(d + 92), flags);
store_reverse_endianness_float_t((float_t*)(d + 96), ptcl->data.speed);
store_reverse_endianness_float_t((float_t*)(d + 100), ptcl->data.speed_random);
store_reverse_endianness_float_t((float_t*)(d + 104), ptcl->data.deceleration);
store_reverse_endianness_float_t((float_t*)(d + 108), ptcl->data.deceleration_random);
store_reverse_endianness_float_t((float_t*)(d + 112), ptcl->data.direction.x);
store_reverse_endianness_float_t((float_t*)(d + 116), ptcl->data.direction.y);
store_reverse_endianness_float_t((float_t*)(d + 120), ptcl->data.direction.z);
store_reverse_endianness_float_t((float_t*)(d + 124), ptcl->data.direction_random.x);
store_reverse_endianness_float_t((float_t*)(d + 128), ptcl->data.direction_random.y);
store_reverse_endianness_float_t((float_t*)(d + 132), ptcl->data.direction_random.z);
store_reverse_endianness_float_t((float_t*)(d + 136), ptcl->data.gravity.x);
store_reverse_endianness_float_t((float_t*)(d + 140), ptcl->data.gravity.y);
store_reverse_endianness_float_t((float_t*)(d + 144), ptcl->data.gravity.z);
store_reverse_endianness_float_t((float_t*)(d + 148), ptcl->data.acceleration.x);
store_reverse_endianness_float_t((float_t*)(d + 152), ptcl->data.acceleration.y);
store_reverse_endianness_float_t((float_t*)(d + 156), ptcl->data.acceleration.z);
store_reverse_endianness_float_t((float_t*)(d + 160), ptcl->data.acceleration_random.x);
store_reverse_endianness_float_t((float_t*)(d + 164), ptcl->data.acceleration_random.y);
store_reverse_endianness_float_t((float_t*)(d + 168), ptcl->data.acceleration_random.z);
store_reverse_endianness_float_t((float_t*)(d + 172), ptcl->data.reflection_coeff);
store_reverse_endianness_float_t((float_t*)(d + 176), ptcl->data.reflection_coeff_random);
store_reverse_endianness_float_t((float_t*)(d + 180), ptcl->data.rebound_plane_y);
store_reverse_endianness_float_t((float_t*)(d + 184), ptcl->data.uv_scroll_add.x);
store_reverse_endianness_float_t((float_t*)(d + 188), ptcl->data.uv_scroll_add.y);
store_reverse_endianness_float_t((float_t*)(d + 192), ptcl->data.uv_scroll_add_scale);
store_reverse_endianness_int32_t((int32_t*)(d + 196), ptcl->data.sub_flags);
store_reverse_endianness_int32_t((int32_t*)(d + 200), ptcl->data.count);
}
else {
*(int32_t*)d = ptcl->data.life_time;
*(int32_t*)(d + 4) = type;
*(int32_t*)(d + 8) = ptcl->data.draw_type;
*(vec3*)(d + 12) = ptcl->data.rotation;
*(vec3*)(d + 24) = ptcl->data.rotation_random;
*(vec3*)(d + 36) = ptcl->data.rotation_add;
*(vec3*)(d + 48) = ptcl->data.rotation_add_random;
*(vec3*)(d + 60) = ptcl->data.scale;
*(vec3*)(d + 72) = ptcl->data.scale_random;
*(float_t*)(d + 84) = ptcl->data.z_offset;
*(int32_t*)(d + 88) = ptcl->data.pivot;
*(int32_t*)(d + 92) = flags;
*(float_t*)(d + 96) = ptcl->data.speed;
*(float_t*)(d + 100) = ptcl->data.speed_random;
*(float_t*)(d + 104) = ptcl->data.deceleration;
*(float_t*)(d + 108) = ptcl->data.deceleration_random;
*(vec3*)(d + 112) = ptcl->data.direction;
*(vec3*)(d + 124) = ptcl->data.direction_random;
*(vec3*)(d + 136) = ptcl->data.gravity;
*(vec3*)(d + 148) = ptcl->data.acceleration;
*(vec3*)(d + 160) = ptcl->data.acceleration_random;
*(float_t*)(d + 172) = ptcl->data.reflection_coeff;
*(float_t*)(d + 176) = ptcl->data.reflection_coeff_random;
*(float_t*)(d + 180) = ptcl->data.rebound_plane_y;
*(vec2*)(d + 184) = ptcl->data.uv_scroll_add;
*(float_t*)(d + 192) = ptcl->data.uv_scroll_add_scale;
*(int32_t*)(d + 196) = ptcl->data.sub_flags;
*(int32_t*)(d + 200) = ptcl->data.count;
}
d += 204;
if (ptcl->version == 3) {
*(int32_t*)d = 0;
if (big_endian)
store_reverse_endianness_float_t((float_t*)(d + 4), ptcl->data.emission);
else
*(float_t*)(d + 4) = ptcl->data.emission;
d += 8;
}
if (ptcl->data.type == PARTICLE_LOCUS || ptcl->data.type == PARTICLE_MESH) {
if (big_endian) {
store_reverse_endianness_uint16_t((uint16_t*)d, (uint16_t)ptcl->data.locus_history_size);
store_reverse_endianness_uint16_t((uint16_t*)(d + 2), (uint16_t)ptcl->data.locus_history_size_random);
}
else {
*(uint16_t*)d = (uint16_t)ptcl->data.locus_history_size;
*(uint16_t*)(d + 2) = (uint16_t)ptcl->data.locus_history_size_random;
}
d += 4;
}
if (big_endian) {
store_reverse_endianness_uint64_t((uint64_t*)d, ptcl->data.tex_hash);
*(uint8_t*)(d + 8) = (uint8_t)roundf(clamp_def(ptcl->data.color.x, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 9) = (uint8_t)roundf(clamp_def(ptcl->data.color.y, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 10) = (uint8_t)roundf(clamp_def(ptcl->data.color.z, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 11) = (uint8_t)roundf(clamp_def(ptcl->data.color.w, 0.0f, 1.0f) * 255.0f);
store_reverse_endianness_int32_t((int32_t*)(d + 12), ptcl->data.blend_mode);
store_reverse_endianness_int32_t((int32_t*)(d + 16), ptcl->data.unk0);
store_reverse_endianness_int32_t((int32_t*)(d + 20), ptcl->data.split_u);
store_reverse_endianness_int32_t((int32_t*)(d + 24), ptcl->data.split_v);
store_reverse_endianness_int32_t((int32_t*)(d + 28), ptcl->data.uv_index_type);
store_reverse_endianness_int16_t((int16_t*)(d + 32), (int16_t)ptcl->data.uv_index);
store_reverse_endianness_int16_t((int16_t*)(d + 34), (int16_t)ptcl->data.frame_step_uv);
store_reverse_endianness_int32_t((int32_t*)(d + 36), ptcl->data.uv_index_start);
store_reverse_endianness_int32_t((int32_t*)(d + 40), ptcl->data.uv_index_end);
}
else {
*(uint64_t*)d = ptcl->data.tex_hash;
*(uint8_t*)(d + 8) = (uint8_t)roundf(clamp_def(ptcl->data.color.x, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 9) = (uint8_t)roundf(clamp_def(ptcl->data.color.y, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 10) = (uint8_t)roundf(clamp_def(ptcl->data.color.z, 0.0f, 1.0f) * 255.0f);
*(uint8_t*)(d + 11) = (uint8_t)roundf(clamp_def(ptcl->data.color.w, 0.0f, 1.0f) * 255.0f);
*(int32_t*)(d + 12) = ptcl->data.blend_mode;
*(int32_t*)(d + 16) = ptcl->data.unk0;
*(int32_t*)(d + 20) = ptcl->data.split_u;
*(int32_t*)(d + 24) = ptcl->data.split_v;
*(int32_t*)(d + 28) = ptcl->data.uv_index_type;
*(int16_t*)(d + 32) = (int16_t)ptcl->data.uv_index;
*(int16_t*)(d + 34) = (int16_t)ptcl->data.frame_step_uv;
*(int32_t*)(d + 36) = ptcl->data.uv_index_start;
*(int32_t*)(d + 40) = ptcl->data.uv_index_end;
}
d += 44;
if (eff_group->version >= 7) {
if (big_endian)
store_reverse_endianness_int32_t((int32_t*)d, ptcl->data.unk1);
else
*(int32_t*)d = ptcl->data.unk1;
d += 4;
}
else
if (ptcl->data.flags & PARTICLE_TEXTURE_MASK) {
if (big_endian) {
store_reverse_endianness_uint64_t((uint64_t*)d, ptcl->data.mask_tex_hash);
store_reverse_endianness_int32_t((int32_t*)(d + 8), ptcl->data.mask_blend_mode);
}
else {
*(uint64_t*)d = ptcl->data.mask_tex_hash;
*(int32_t*)(d + 8) = ptcl->data.mask_blend_mode;
}
d += 12;
}
else {
*(uint64_t*)d = 0;
*(int32_t*)(d + 8) = 0;
d += 12;
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('PTCL');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
st->header.version = ptcl->version;
return true;
}
bool FileWriter::UnparseAnimation(f2_struct* st, Animation* anim, CurveTypeFlags flags, bool big_endian) {
if (anim->curves.size() < 1)
return false;
static const CurveType order[] = {
CURVE_COLOR_A,
CURVE_COLOR_R,
CURVE_COLOR_G,
CURVE_COLOR_B,
CURVE_COLOR_RGB_SCALE,
CURVE_COLOR_A_2ND,
CURVE_COLOR_R_2ND,
CURVE_COLOR_G_2ND,
CURVE_COLOR_B_2ND,
CURVE_COLOR_RGB_SCALE_2ND,
CURVE_TRANSLATION_X,
CURVE_TRANSLATION_Y,
CURVE_TRANSLATION_Z,
CURVE_ROTATION_X,
CURVE_ROTATION_Y,
CURVE_ROTATION_Z,
CURVE_SCALE_X,
CURVE_SCALE_Y,
CURVE_SCALE_Z,
CURVE_SCALE_ALL,
CURVE_EMISSION_INTERVAL,
CURVE_PARTICLES_PER_EMISSION,
CURVE_U_SCROLL,
CURVE_V_SCROLL,
CURVE_U_SCROLL_ALPHA,
CURVE_V_SCROLL_ALPHA,
CURVE_U_SCROLL_2ND,
CURVE_V_SCROLL_2ND,
CURVE_U_SCROLL_ALPHA_2ND,
CURVE_V_SCROLL_ALPHA_2ND,
};
for (int32_t i = CURVE_TRANSLATION_X; i <= CURVE_V_SCROLL_ALPHA_2ND; i++) {
if (~flags & (1 << (size_t)order[i]))
continue;
for (Curve*& j : anim->curves) {
Curve* c = j;
if (!c || c->type != order[i])
continue;
f2_struct s;
if (UnparseCurve(&s, c, big_endian)) {
st->sub_structs.push_back(s);
break;
}
}
}
if (st->sub_structs.size() < 1)
return false;
st->header.signature = reverse_endianness_uint32_t('ANIM');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
return true;
}
bool FileWriter::UnparseCurve(f2_struct* st, Curve* c, bool big_endian) {
#if !defined(CRE_DEV)
if (c->keys.size() < 1)
return false;
#else
std::vector<Curve::Key> keys = c->keys;
if (c->keys_rev.size() < 1)
return false;
c->Recalculate(type);
if (!c->keys.size()) {
c->keys = keys;
return false;
}
#endif
size_t l;
size_t d;
l = 0;
uint32_t o;
enrs e;
enrs_entry ee;
ee = { 0, 2, 32, 1 };
ee.append(0, 4, ENRS_DWORD);
ee.append(0, 3, ENRS_WORD);
e.vec.push_back(ee);
l += o = 32;
st->data.resize(l);
d = (size_t)st->data.data();
float_t random_range = c->random_range;
if (c->version == 0)
switch (c->type) {
case CURVE_ROTATION_X:
case CURVE_ROTATION_Y:
case CURVE_ROTATION_Z:
random_range = 0.0f;
break;
}
if (big_endian) {
store_reverse_endianness_uint32_t((uint32_t*)d, c->type);
store_reverse_endianness_uint32_t((uint32_t*)(d + 4), c->repeat ? 1 : 0);
store_reverse_endianness_uint32_t((uint32_t*)(d + 8), c->flags);
store_reverse_endianness_float_t((float_t*)(d + 12), random_range);
store_reverse_endianness_int16_t((int16_t*)(d + 16), (int16_t)c->keys.size());
store_reverse_endianness_int16_t((int16_t*)(d + 18), (int16_t)c->start_time);
store_reverse_endianness_int16_t((int16_t*)(d + 20), (int16_t)c->end_time);
}
else {
*(uint32_t*)d = c->type;
*(uint32_t*)(d + 4) = c->repeat ? 1 : 0;
*(uint32_t*)(d + 8) = c->flags;
*(float_t*)(d + 12) = random_range;
*(int16_t*)(d + 16) = (int16_t)c->keys.size();
*(int16_t*)(d + 18) = (int16_t)c->start_time;
*(int16_t*)(d + 20) = (int16_t)c->end_time;
}
st->enrs = e;
st->header.signature = reverse_endianness_uint32_t('CURV');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
st->header.version = c->version;
f2_struct s;
PackCurve(&s, c, big_endian);
st->sub_structs.push_back(s);
#if defined(CRE_DEV)
c->keys = keys;
#endif
return true;
}
bool FileWriter::UnparseDivaEffect(EffectGroup* eff_group, f2_struct* st, bool big_endian) {
UnparseEffectGroup(eff_group, st, big_endian);
st->header.signature = reverse_endianness_uint32_t('DVEF');
st->header.length = 0x20;
st->header.use_big_endian = false;
st->header.use_section_size = true;
st->header.version = eff_group->version;
return true;
}
bool FileWriter::UnparseDivaList(EffectGroup* eff_group, f2_struct* st, bool big_endian) {
f2_struct s;
if (!PackDivaList(eff_group, &s, big_endian))
return false;
st->sub_structs.push_back(s);
st->header.signature = reverse_endianness_uint32_t('LIST');
st->header.length = 0x20;
st->header.use_big_endian = big_endian;
st->header.use_section_size = true;
return true;
}
bool FileWriter::UnparseDivaResource(EffectGroup* eff_group, f2_struct* st) {
f2_struct s;
if (!PackDivaResource(eff_group, &s))
return false;
st->sub_structs.push_back(s);
st->header.signature = reverse_endianness_uint32_t('DVRS');
st->header.length = 0x20;
st->header.use_big_endian = false;
st->header.use_section_size = true;
st->header.version = 1;
return true;
}
bool FileWriter::UnparseEffect(EffectGroup* eff_group, f2_struct* st, Effect* eff, bool big_endian) {
if (!PackEffect(st, eff, big_endian))
return false;
f2_struct s;
if (UnparseAnimation(&s, &eff->animation, effect_curve_flags, big_endian))
st->sub_structs.push_back(s);
for (Emitter*& i : eff->emitters) {
if (!i)
continue;
f2_struct s;
if (UnparseEmitter(eff_group, &s, i, eff, big_endian))
st->sub_structs.push_back(s);
}
return true;
}
void FileWriter::UnparseEffectGroup(EffectGroup* eff_group, f2_struct* st, bool big_endian) {
for (Effect*& i : eff_group->effects) {
if (!i)
continue;
f2_struct s;
if (UnparseEffect(eff_group, &s, i, big_endian))
st->sub_structs.push_back(s);
}
f2_struct s;
if (PackDivaResourceHashes(eff_group, &s, big_endian))
st->sub_structs.push_back(s);
}
bool FileWriter::UnparseEmitter(EffectGroup* eff_group,
f2_struct* st, Emitter* emit, Effect* eff, bool big_endian) {
if (!PackEmitter(st, emit, big_endian))
return false;
f2_struct s;
if (UnparseAnimation(&s, &emit->animation, emitter_curve_flags, big_endian))
st->sub_structs.push_back(s);
for (Particle*& i : emit->particles) {
if (!i)
continue;
f2_struct s;
if (UnparseParticle(eff_group, &s, i, eff, big_endian))
st->sub_structs.push_back(s);
}
return true;
}
bool FileWriter::UnparseParticle(EffectGroup* eff_group,
f2_struct* st, Particle* ptcl, Effect* eff, bool big_endian) {
if (!PackParticle(eff_group, st, ptcl, eff, big_endian))
return false;
CurveTypeFlags flags;
if (type == Glitter::X)
flags = particle_x_curve_flags;
else
flags = particle_curve_flags;
if (ptcl->data.type != PARTICLE_MESH) {
enum_and(flags, ~CURVE_TYPE_UV_SCROLL_2ND);
if (ptcl->data.draw_type != DIRECTION_PARTICLE_ROTATION)
enum_and(flags, ~(CURVE_TYPE_ROTATION_X | CURVE_TYPE_ROTATION_Y));
}
f2_struct s;
if (UnparseAnimation(&s, &ptcl->animation, flags, big_endian))
st->sub_structs.push_back(s);
return true;
}
void FileWriter::Write(GLT, EffectGroup* eff_group,
const char* path, const char* file, bool compress, bool big_endian) {
FileWriter fr;
fr.type = GLT_VAL;
farc f;
{
f2_struct st;
if (fr.UnparseDivaEffect(eff_group, &st, big_endian)) {
f.add_file();
farc_file& ff_drs = f.files.back();
st.write(&ff_drs.data, &ff_drs.size);
ff_drs.name = std::string(file) + ".dve";
}
}
{
f2_struct st;
if (fr.UnparseDivaResource(eff_group, &st)) {
f.add_file();
farc_file& ff_dve = f.files.back();
st.write(&ff_dve.data, &ff_dve.size);
ff_dve.name = std::string(file) + ".drs";
}
else
return;
}
if (fr.type == Glitter::FT) {
f2_struct st;
if (fr.UnparseDivaList(eff_group, &st, big_endian)) {
f.add_file();
farc_file& ff_lst = f.files.back();
st.write(&ff_lst.data, &ff_lst.size);
ff_lst.name = std::string(file) + ".lst";
}
else
return;
}
farc_compress_mode mode;
if (compress)
mode = glt_type != Glitter::FT ? FARC_COMPRESS_FARC_GZIP_AES : FARC_COMPRESS_FArC;
else
mode = FARC_COMPRESS_FArc;
char* temp = str_utils_add(path, file);
if (glt_type != Glitter::FT) {
char* list_temp = str_utils_add(temp, ".glitter.txt");
file_stream s;
s.open(list_temp, "wb");
if (s.check_not_null()) {
for (Glitter::Effect*& i : eff_group->effects)
if (i) {
s.write_string(i->name);
s.write_char('\n');
}
}
free_def(list_temp);
}
f.write(temp, mode, false);
free_def(temp);
}
}