mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-08 06:38:27 +03:00
FT FARC reading fixes and writing support
This commit is contained in:
@@ -2137,6 +2137,7 @@ namespace Glitter {
|
||||
bool encrypt = !!(writer_flags & FILE_WRITER_ENCRYPT);
|
||||
bool save_lst = !(writer_flags & FILE_WRITER_NO_LIST);
|
||||
bool big_endian = !!(writer_flags & FILE_WRITER_BIG_ENDIAN);
|
||||
bool ft = !!(writer_flags & FILE_WRITER_FT);
|
||||
farc f;
|
||||
{
|
||||
size_t file_len = utf8_length(file);
|
||||
@@ -2198,6 +2199,7 @@ namespace Glitter {
|
||||
if (encrypt) {
|
||||
signature = FARC_FARC;
|
||||
flags = FARC_AES;
|
||||
f.ft = ft;
|
||||
|
||||
if (compress)
|
||||
enum_or(flags, FARC_GZIP);
|
||||
|
||||
@@ -275,6 +275,7 @@ namespace Glitter {
|
||||
FILE_WRITER_ENCRYPT = 0x02,
|
||||
FILE_WRITER_NO_LIST = 0x04,
|
||||
FILE_WRITER_BIG_ENDIAN = 0x08,
|
||||
FILE_WRITER_FT = 0x10,
|
||||
};
|
||||
|
||||
enum FogType {
|
||||
|
||||
+233
-96
@@ -11,6 +11,7 @@
|
||||
#include "deflate.hpp"
|
||||
#include "hash.hpp"
|
||||
#include "str_utils.hpp"
|
||||
#include <time.h>
|
||||
|
||||
static const uint8_t key[] = {
|
||||
0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x5F,
|
||||
@@ -31,10 +32,14 @@ static void farc_unpack_file(farc* f, stream& s, farc_file* ff,
|
||||
bool save = false, char* temp_path = 0, size_t dir_len = 0);
|
||||
static void farc_write_padding(farc* f, stream& s, size_t size, bool x = false);
|
||||
|
||||
farc::farc() : flags(), ft() {
|
||||
signature = FARC_FArC;
|
||||
farc::farc(farc_signature signature, farc_flags flags, bool ft)
|
||||
: signature(signature), flags(flags), ft(ft), entry_padding(), header_padding() {
|
||||
compression_level = 12;
|
||||
alignment = 0x10;
|
||||
if (ft) {
|
||||
entry_size = 0x10;
|
||||
header_size = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
farc::~farc() {
|
||||
@@ -426,53 +431,75 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
}
|
||||
|
||||
if (plain)
|
||||
signature = FARC_FArc;
|
||||
if (signature == FARC_FARC)
|
||||
flags = (farc_flags)0;
|
||||
else
|
||||
signature = FARC_FArc;
|
||||
|
||||
f->ft &= signature == FARC_FARC;
|
||||
|
||||
bool compressed = false;
|
||||
bool encrypted = false;
|
||||
switch (signature) {
|
||||
case FARC_FARC:
|
||||
f->flags = flags;
|
||||
compressed = !!(flags & FARC_GZIP);
|
||||
encrypted = !!(flags & FARC_AES);
|
||||
case FARC_FArc:
|
||||
default:
|
||||
f->flags = (farc_flags)0;
|
||||
break;
|
||||
case FARC_FArC:
|
||||
f->flags = (farc_flags)0;
|
||||
compressed = true;
|
||||
break;
|
||||
default:
|
||||
f->flags = (farc_flags)0;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t header_length = 0;
|
||||
switch (signature) {
|
||||
case FARC_FARC:
|
||||
header_length += sizeof(int32_t) * 5;
|
||||
break;
|
||||
default:
|
||||
header_length += sizeof(int32_t);
|
||||
f->flags = flags;
|
||||
compressed = !!(flags & FARC_GZIP);
|
||||
encrypted = !!(flags & FARC_AES);
|
||||
break;
|
||||
}
|
||||
|
||||
if (signature == FARC_FArc)
|
||||
for (farc_file& i : f->files) {
|
||||
header_length += i.name.size() + 1;
|
||||
header_length += sizeof(int32_t) * 2;
|
||||
}
|
||||
else
|
||||
for (farc_file& i : f->files) {
|
||||
header_length += i.name.size() + 1;
|
||||
header_length += sizeof(int32_t) * 3;
|
||||
}
|
||||
size_t header_length = sizeof(int32_t);
|
||||
for (farc_file& i : f->files)
|
||||
header_length += i.name.size() + 1;
|
||||
|
||||
size_t align = header_length + 8;
|
||||
s.set_position(align_val(align, f->alignment), SEEK_SET);
|
||||
switch (signature) {
|
||||
case FARC_FArc:
|
||||
header_length += sizeof(int32_t) * 2 * f->files.size();
|
||||
break;
|
||||
case FARC_FArC:
|
||||
default:
|
||||
header_length += sizeof(int32_t) * 3 * f->files.size();
|
||||
break;
|
||||
case FARC_FARC:
|
||||
if (f->ft) {
|
||||
f->header_size = max_def(f->header_size, 0x10u);
|
||||
f->entry_size = max_def(f->entry_size, 0x10u);
|
||||
|
||||
header_length += sizeof(int32_t) + f->header_size;
|
||||
header_length += f->entry_size * f->files.size();
|
||||
|
||||
if (encrypted) {
|
||||
size_t head_data_len = header_length - sizeof(int32_t) * 2;
|
||||
head_data_len = align_val(head_data_len, 0x10);
|
||||
if (head_data_len == header_length - sizeof(int32_t) * 2)
|
||||
head_data_len += 0x10;
|
||||
header_length = head_data_len + sizeof(int32_t) * 2;
|
||||
|
||||
header_length += 0x10;
|
||||
}
|
||||
}
|
||||
else {
|
||||
header_length += sizeof(int32_t) * 4 + f->header_padding;
|
||||
header_length += (sizeof(int32_t) * 3 + f->entry_padding) * f->files.size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
size_t align = align_val(header_length + 8, max_def(f->alignment, encrypted ? 0x10u : 0x01u));
|
||||
s.set_position(align, SEEK_SET);
|
||||
size_t dir_len = f->directory_path.size();
|
||||
|
||||
aes128_ctx ctx;
|
||||
if (signature == FARC_FARC)
|
||||
aes128_init_ctx(&ctx, key);
|
||||
aes128_init_ctx(&ctx, f->ft ? key_ft : key);
|
||||
|
||||
f->compression_level = clamp_def(f->compression_level, 0, 12);
|
||||
|
||||
@@ -511,9 +538,17 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
free_def(temp);
|
||||
}
|
||||
|
||||
std::vector<size_t> size_compressed_enc;
|
||||
if (f->ft) {
|
||||
time_t t;
|
||||
srand((uint32_t)_time64(&t));
|
||||
}
|
||||
|
||||
if (encrypted)
|
||||
size_compressed_enc.resize(f->files.size());
|
||||
|
||||
for (farc_file& i : f->files) {
|
||||
i.offset = s.get_position();
|
||||
size_t file_len = i.size;
|
||||
|
||||
if (i.encrypted && encrypted) {
|
||||
void* t1;
|
||||
@@ -521,7 +556,7 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
if (i.compressed && compressed) {
|
||||
if (!i.data_compressed || i.data_changed) {
|
||||
free_def(i.data_compressed);
|
||||
deflate::compress_gzip(i.data, file_len, i.data_compressed,
|
||||
deflate::compress_gzip(i.data, i.size, i.data_compressed,
|
||||
i.size_compressed, f->compression_level, i.name.c_str());
|
||||
}
|
||||
t1 = i.data_compressed;
|
||||
@@ -534,21 +569,45 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
t1_len = i.size;
|
||||
}
|
||||
|
||||
size_t t2_len = align_val(t1_len, f->alignment);
|
||||
uint8_t* t2 = (uint8_t*)force_malloc(t2_len);
|
||||
memcpy(t2, t1, t1_len);
|
||||
memset(t2 + t1_len, 0x78, t2_len - t1_len);
|
||||
if (f->ft) {
|
||||
size_t t2_len = align_val(t1_len, 0x10);
|
||||
if (t2_len == t1_len)
|
||||
t2_len += 0x10;
|
||||
t2_len += 0x10;
|
||||
size_compressed_enc.data()[&i - f->files.data()] = t2_len;
|
||||
|
||||
aes128_ecb_encrypt_buffer(&ctx, t2, t2_len);
|
||||
uint8_t* t2 = (uint8_t*)force_malloc(t2_len);
|
||||
for (int32_t j = 0; j < 0x10; j++)
|
||||
t2[j] = (uint8_t)rand();
|
||||
memcpy(t2 + 0x10, t1, t1_len);
|
||||
const int32_t pkcs7_pad_len = (int32_t)(t2_len - t1_len - 0x10);
|
||||
memset(t2 + 0x10 + t1_len, pkcs7_pad_len, pkcs7_pad_len); // PKCS7 Padding
|
||||
|
||||
s.write(t2, t2_len);
|
||||
free_def(t2);
|
||||
aes128_ctx_set_iv(&ctx, t2);
|
||||
aes128_cbc_encrypt_buffer(&ctx, t2 + 0x10, t2_len - 0x10);
|
||||
|
||||
s.write(t2, t2_len);
|
||||
free_def(t2);
|
||||
}
|
||||
else {
|
||||
size_t t2_len = align_val(align_val(t1_len, 0x10), f->alignment);
|
||||
size_compressed_enc.data()[&i - f->files.data()] = t2_len;
|
||||
|
||||
uint8_t* t2 = (uint8_t*)force_malloc(t2_len);
|
||||
memcpy(t2, t1, t1_len);
|
||||
memset(t2 + t1_len, 0x78, t2_len - t1_len);
|
||||
|
||||
aes128_ecb_encrypt_buffer(&ctx, t2, t2_len);
|
||||
|
||||
s.write(t2, t2_len);
|
||||
free_def(t2);
|
||||
}
|
||||
}
|
||||
else if (i.compressed && compressed) {
|
||||
i.encrypted = false;
|
||||
if (!i.data_compressed || i.data_changed) {
|
||||
free_def(i.data_compressed);
|
||||
deflate::compress_gzip(i.data, file_len, i.data_compressed,
|
||||
deflate::compress_gzip(i.data, i.size, i.data_compressed,
|
||||
i.size_compressed, f->compression_level, i.name.c_str());
|
||||
}
|
||||
s.write(i.data_compressed, i.size_compressed);
|
||||
@@ -558,12 +617,72 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
i.compressed = false;
|
||||
i.encrypted = false;
|
||||
free_def(i.data_compressed);
|
||||
s.write(i.data, file_len);
|
||||
s.write(i.data, i.size);
|
||||
farc_write_padding(f, s, i.size);
|
||||
}
|
||||
i.data_changed = false;
|
||||
}
|
||||
|
||||
if (f->ft) {
|
||||
s.set_position(0, SEEK_SET);
|
||||
s.write_uint32_t_reverse_endianness(FARC_FARC, true);
|
||||
s.write_uint32_t_reverse_endianness((int32_t)header_length, true);
|
||||
s.write_uint32_t_reverse_endianness(f->flags, true);
|
||||
s.write_uint32_t_reverse_endianness(0x00, true);
|
||||
|
||||
size_t head_data_len = header_length - sizeof(int32_t) * 2;
|
||||
uint8_t* head_data = (uint8_t*)force_malloc(head_data_len);
|
||||
if (encrypted)
|
||||
for (int32_t i = 0; i < 0x10; i++)
|
||||
head_data[i] = (uint8_t)rand();
|
||||
|
||||
uint8_t* dt = head_data;
|
||||
if (encrypted)
|
||||
dt += 0x10;
|
||||
|
||||
store_reverse_endianness_uint32_t((void*)dt, f->header_size);
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 4), f->alignment);
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 8), (uint32_t)f->files.size());
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 12), f->entry_size);
|
||||
dt += f->header_size;
|
||||
|
||||
for (farc_file& i : f->files) {
|
||||
memcpy(dt, i.name.c_str(), i.name.size());
|
||||
dt[i.name.size()] = 0;
|
||||
dt += i.name.size() + 1;
|
||||
|
||||
farc_flags flags = (farc_flags)0;
|
||||
if (i.compressed && compressed)
|
||||
enum_or(flags, FARC_GZIP);
|
||||
if (i.encrypted && encrypted)
|
||||
enum_or(flags, FARC_AES);
|
||||
|
||||
store_reverse_endianness_uint32_t((void*)dt, (uint32_t)i.offset);
|
||||
if (i.encrypted && encrypted)
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 4),
|
||||
(uint32_t)size_compressed_enc.data()[&i - f->files.data()]);
|
||||
else if (i.compressed && compressed)
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 4), (uint32_t)i.size_compressed);
|
||||
else
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 4), (uint32_t)i.size);
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 8), (uint32_t)i.size);
|
||||
store_reverse_endianness_uint32_t((void*)(dt + 12), (uint32_t)flags);
|
||||
dt += f->entry_size;
|
||||
}
|
||||
|
||||
if (encrypted) {
|
||||
const int32_t pkcs7_pad_len = (int32_t)(head_data_len - (dt - head_data));
|
||||
memset(dt, pkcs7_pad_len, pkcs7_pad_len); // PKCS7 Padding
|
||||
|
||||
aes128_ctx_set_iv(&ctx, head_data);
|
||||
aes128_cbc_encrypt_buffer(&ctx, head_data + 0x10, head_data_len - 0x10);
|
||||
}
|
||||
|
||||
s.write(head_data, head_data_len);
|
||||
free_def(head_data);
|
||||
return;
|
||||
}
|
||||
|
||||
s.set_position(0, SEEK_SET);
|
||||
switch (signature) {
|
||||
case FARC_FArc:
|
||||
@@ -583,8 +702,10 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
s.write_uint32_t_reverse_endianness(f->flags, true);
|
||||
s.write_uint32_t_reverse_endianness(0x00, true);
|
||||
s.write_uint32_t_reverse_endianness(f->alignment, true);
|
||||
s.write_uint32_t_reverse_endianness(0x00, true);
|
||||
s.write_uint32_t_reverse_endianness(0x00, true);
|
||||
s.write_uint32_t_reverse_endianness(f->entry_padding, true);
|
||||
s.write_uint32_t_reverse_endianness(f->header_padding, true);
|
||||
if (f->header_padding)
|
||||
s.write(f->header_padding);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -614,14 +735,16 @@ static void farc_pack_files(farc* f, stream& s, farc_signature signature, farc_f
|
||||
for (farc_file& i : f->files) {
|
||||
s.write_string_null_terminated(i.name);
|
||||
s.write_int32_t_reverse_endianness((int32_t)i.offset, true);
|
||||
if (i.compressed) {
|
||||
s.write_int32_t_reverse_endianness((int32_t)i.size_compressed, true);
|
||||
if (i.encrypted && encrypted)
|
||||
s.write_int32_t_reverse_endianness(
|
||||
(uint32_t)size_compressed_enc.data()[&i - f->files.data()], true);
|
||||
else if (i.compressed && compressed)
|
||||
s.write_int32_t_reverse_endianness((uint32_t)i.size_compressed, true);
|
||||
else
|
||||
s.write_int32_t_reverse_endianness((int32_t)i.size, true);
|
||||
}
|
||||
else {
|
||||
s.write_int32_t_reverse_endianness((int32_t)i.size, true);
|
||||
s.write_int32_t_reverse_endianness(0x00, true);
|
||||
}
|
||||
s.write_int32_t_reverse_endianness((int32_t)i.size, true);
|
||||
if (f->entry_padding)
|
||||
s.write(f->entry_padding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -679,10 +802,17 @@ static errno_t farc_read_header(farc* f, stream& s) {
|
||||
}
|
||||
|
||||
if (f->ft) {
|
||||
f->alignment = load_reverse_endianness_uint32_t((void*)dt);
|
||||
f->header_size = load_reverse_endianness_uint32_t((void*)dt);
|
||||
if (header_length < f->header_size || f->header_size < 0x10)
|
||||
return -3;
|
||||
|
||||
f->alignment = load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
uint32_t files_count = load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
uint32_t entry_size = load_reverse_endianness_uint32_t((void*)(dt + 12));
|
||||
dt += sizeof(uint32_t) * 4;
|
||||
f->entry_size = load_reverse_endianness_uint32_t((void*)(dt + 12));
|
||||
if (f->entry_size < 0x10)
|
||||
return -4;
|
||||
|
||||
dt += sizeof(uint32_t) * 4 + (f->header_size - 0x10);
|
||||
|
||||
f->files.clear();
|
||||
f->files.reserve(files_count);
|
||||
@@ -691,7 +821,8 @@ static errno_t farc_read_header(farc* f, stream& s) {
|
||||
while (dt[length])
|
||||
length++;
|
||||
|
||||
farc_file ff;
|
||||
f->files.push_back({});
|
||||
farc_file& ff = f->files.back();
|
||||
ff.name.assign((const char*)dt, length);
|
||||
dt += length + 1;
|
||||
ff.offset = (size_t)load_reverse_endianness_uint32_t((void*)dt);
|
||||
@@ -699,17 +830,9 @@ static errno_t farc_read_header(farc* f, stream& s) {
|
||||
ff.size = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
farc_flags flags = (farc_flags)load_reverse_endianness_uint32_t((void*)(dt + 12));
|
||||
|
||||
if (ff.size)
|
||||
ff.compressed = true;
|
||||
else {
|
||||
ff.size = ff.size_compressed;
|
||||
ff.size_compressed = 0;
|
||||
ff.compressed = false;
|
||||
}
|
||||
|
||||
ff.encrypted = ((f->flags | flags) & FARC_AES) != 0;
|
||||
f->files.push_back(ff);
|
||||
dt += entry_size;
|
||||
ff.compressed = !!(flags & FARC_GZIP);
|
||||
ff.encrypted = !!(flags & FARC_AES);
|
||||
dt += f->entry_size;
|
||||
files_count--;
|
||||
}
|
||||
|
||||
@@ -720,11 +843,17 @@ static errno_t farc_read_header(farc* f, stream& s) {
|
||||
size_t entry_size;
|
||||
if (f->signature == FARC_FARC) {
|
||||
f->alignment = load_reverse_endianness_uint32_t((void*)dt);
|
||||
uint32_t entry_offset = load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
uint32_t header_offset = load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
dt += sizeof(uint32_t) * 3;
|
||||
if ((f->flags & FARC_AES) && f->alignment < 0x10)
|
||||
return -5;
|
||||
|
||||
entry_size = sizeof(uint32_t) * 3 + entry_offset;
|
||||
f->entry_padding = load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
f->header_padding = load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
dt += sizeof(uint32_t) * 3 + f->header_padding;
|
||||
|
||||
if (dt - d_t >= header_length)
|
||||
return -6;
|
||||
|
||||
entry_size = sizeof(uint32_t) * 3 + f->entry_padding;
|
||||
}
|
||||
else if (f->signature != FARC_FArc) {
|
||||
f->alignment = load_reverse_endianness_uint32_t((void*)dt);
|
||||
@@ -739,56 +868,64 @@ static errno_t farc_read_header(farc* f, stream& s) {
|
||||
entry_size = sizeof(uint32_t) * 2;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
size_t files_count = 0;
|
||||
uint8_t* position = dt;
|
||||
|
||||
while (dt - d_t < header_length) {
|
||||
while (*dt++);
|
||||
dt += entry_size;
|
||||
count++;
|
||||
files_count++;
|
||||
}
|
||||
dt = position;
|
||||
|
||||
bool encrypted = !!(f->flags & FARC_AES);
|
||||
const bool encrypted = !!(f->flags & FARC_AES);
|
||||
|
||||
f->files.clear();
|
||||
f->files.resize(count);
|
||||
f->files.reserve(files_count);
|
||||
if (f->signature != FARC_FArc)
|
||||
for (farc_file& i : f->files) {
|
||||
while (dt - d_t < header_length && files_count) {
|
||||
size_t length = 0;
|
||||
while (dt[length])
|
||||
length++;
|
||||
i.name.assign((const char*)dt, length);
|
||||
dt += length + 1;
|
||||
i.offset = (size_t)load_reverse_endianness_uint32_t((void*)dt);
|
||||
i.size_compressed = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
i.size = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
|
||||
if (i.size)
|
||||
i.compressed = true;
|
||||
f->files.push_back({});
|
||||
farc_file& ff = f->files.back();
|
||||
ff.name.assign((const char*)dt, length);
|
||||
dt += length + 1;
|
||||
ff.offset = (size_t)load_reverse_endianness_uint32_t((void*)dt);
|
||||
ff.size_compressed = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
ff.size = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 8));
|
||||
|
||||
if (ff.size)
|
||||
ff.compressed = true;
|
||||
else {
|
||||
i.size = i.size_compressed;
|
||||
i.size_compressed = 0;
|
||||
i.compressed = false;
|
||||
ff.size = ff.size_compressed;
|
||||
ff.size_compressed = 0;
|
||||
ff.compressed = false;
|
||||
}
|
||||
|
||||
i.encrypted = encrypted;
|
||||
ff.encrypted = encrypted;
|
||||
dt += entry_size;
|
||||
files_count--;
|
||||
}
|
||||
else
|
||||
for (farc_file& i : f->files) {
|
||||
while (dt - d_t < header_length && files_count) {
|
||||
size_t length = 0;
|
||||
while (dt[length])
|
||||
length++;
|
||||
i.name.assign((const char*)dt, length);
|
||||
dt += length + 1;
|
||||
i.offset = (size_t)load_reverse_endianness_uint32_t((void*)dt);
|
||||
i.size = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
|
||||
i.size_compressed = 0;
|
||||
i.compressed = false;
|
||||
i.encrypted = false;
|
||||
f->files.push_back({});
|
||||
farc_file& ff = f->files.back();
|
||||
ff.name.assign((const char*)dt, length);
|
||||
dt += length + 1;
|
||||
ff.offset = (size_t)load_reverse_endianness_uint32_t((void*)dt);
|
||||
ff.size = (size_t)load_reverse_endianness_uint32_t((void*)(dt + 4));
|
||||
|
||||
ff.size_compressed = 0;
|
||||
ff.compressed = false;
|
||||
ff.encrypted = false;
|
||||
dt += sizeof(int32_t) * 2;
|
||||
files_count--;
|
||||
}
|
||||
|
||||
free_def(d_t);
|
||||
@@ -865,8 +1002,8 @@ static void farc_unpack_file(farc* f, stream& s, farc_file* ff, bool save, char*
|
||||
}
|
||||
}
|
||||
else if (ff->compressed || ff->encrypted) {
|
||||
size_t temp_s = ff->compressed ? ff->size_compressed : ff->size;
|
||||
temp_s = ff->encrypted ? align_val(temp_s, f->alignment) : temp_s;
|
||||
size_t temp_s = ff->compressed || ff->encrypted ? ff->size_compressed : ff->size;
|
||||
temp_s = ff->encrypted ? align_val(align_val(temp_s, 0x10), f->alignment) : temp_s;
|
||||
void* temp = force_malloc(temp_s);
|
||||
s.read(temp, temp_s);
|
||||
|
||||
|
||||
+9
-1
@@ -53,9 +53,17 @@ struct farc {
|
||||
farc_flags flags;
|
||||
int32_t compression_level;
|
||||
uint32_t alignment;
|
||||
union {
|
||||
uint32_t entry_padding;
|
||||
uint32_t entry_size;
|
||||
};
|
||||
union {
|
||||
uint32_t header_padding;
|
||||
uint32_t header_size;
|
||||
};
|
||||
bool ft;
|
||||
|
||||
farc();
|
||||
farc(farc_signature signature = FARC_FArC, farc_flags flags = (farc_flags)0, bool ft = false);
|
||||
~farc();
|
||||
|
||||
farc_file* add_file(const char* name);
|
||||
|
||||
+67
-14
@@ -6855,7 +6855,7 @@ bool x_pv_game::ctrl() {
|
||||
if (!src || !*src)
|
||||
return 0;
|
||||
|
||||
for (int32_t i = 0; i < size - 1; i++, b++) {
|
||||
for (int32_t i = 0; *src && i < size - 1; i++, b++) {
|
||||
char c = *b = *src++;
|
||||
if (!c) {
|
||||
b++;
|
||||
@@ -7354,6 +7354,9 @@ bool x_pv_game::ctrl() {
|
||||
x_pv_game_write_dsc(pv_data.pv_data.dsc, pv_data.pv_id, x_pack_aft_out_dir);
|
||||
x_pv_game_write_dsc(pv_data.pv_data.dsc, pv_data.pv_id, x_pack_mmp_out_dir);
|
||||
|
||||
time_t t;
|
||||
srand((uint32_t)_time64(&t));
|
||||
|
||||
std::vector<auth_3d*> chara_effect_auth_3ds;
|
||||
std::vector<auth_3d*> song_effect_auth_3ds;
|
||||
std::vector<auth_3d*> stage_data_effect_auth_3ds;
|
||||
@@ -7604,7 +7607,10 @@ bool x_pv_game::ctrl() {
|
||||
|
||||
x_pv_game_write_auth_3d_category(name, &auth_3d_db, avail_uids, x_pack_aft_out_dir);
|
||||
|
||||
farc* effpv_farc = new farc;
|
||||
farc* effpv_farc = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, FARC_NONE);
|
||||
effpv_farc->entry_padding = 0x01 + (rand() % 0x10);
|
||||
effpv_farc->header_padding = 0x01 + (rand() % 0x20);
|
||||
|
||||
for (auth_3d*& i : song_effect_auth_3ds)
|
||||
x_pv_game_write_auth_3d(effpv_farc, i, &auth_3d_db, name, avail_uids, x_pack_aft_out_dir);
|
||||
|
||||
@@ -7621,7 +7627,10 @@ bool x_pv_game::ctrl() {
|
||||
|
||||
x_pv_game_write_auth_3d_category(name, &auth_3d_db, avail_uids, x_pack_aft_out_dir);
|
||||
|
||||
farc* effstgpv_farc = new farc;
|
||||
farc* effstgpv_farc = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, FARC_NONE);
|
||||
effstgpv_farc->entry_padding = 0x01 + (rand() % 0x10);
|
||||
effstgpv_farc->header_padding = 0x01 + (rand() % 0x20);
|
||||
|
||||
for (stage_data_modern& i : stage_data.stage_data.stg_db.stage_modern)
|
||||
for (uint32_t& j : i.auth_3d_ids) {
|
||||
auth_3d* auth = auth_3d_data_get_auth_3d(j);
|
||||
@@ -7663,7 +7672,10 @@ bool x_pv_game::ctrl() {
|
||||
|
||||
x_pv_game_write_auth_3d_category(name, &auth_3d_db, avail_uids, x_pack_mmp_out_dir);
|
||||
|
||||
farc* effpv_farc = new farc;
|
||||
farc* effpv_farc = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, FARC_NONE, true);
|
||||
effpv_farc->entry_size = 0x11 + (rand() % 0x10);
|
||||
effpv_farc->header_size = 0x11 + (rand() % 0x20);
|
||||
|
||||
for (auth_3d*& i : song_effect_auth_3ds)
|
||||
x_pv_game_write_auth_3d(effpv_farc, i, &auth_3d_db, name, avail_uids, x_pack_mmp_out_dir);
|
||||
|
||||
@@ -7680,7 +7692,10 @@ bool x_pv_game::ctrl() {
|
||||
|
||||
x_pv_game_write_auth_3d_category(name, &auth_3d_db, avail_uids, x_pack_mmp_out_dir);
|
||||
|
||||
farc* effstgpv_farc = new farc;
|
||||
farc* effstgpv_farc = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, FARC_NONE, true);
|
||||
effstgpv_farc->entry_size = 0x11 + (rand() % 0x10);
|
||||
effstgpv_farc->header_size = 0x11 + (rand() % 0x20);
|
||||
|
||||
for (stage_data_modern& i : stage_data.stage_data.stg_db.stage_modern)
|
||||
for (uint32_t& j : i.auth_3d_ids) {
|
||||
auth_3d* auth = auth_3d_data_get_auth_3d(j);
|
||||
@@ -9327,9 +9342,11 @@ void FarcCompress::FarcThreadMain(int32_t index) {
|
||||
waitable_timer timer;
|
||||
while (true) {
|
||||
if (thread.state == FARC_COMPRESS_STATE_WORKING) {
|
||||
thread.f->write(thread.path.c_str(), FARC_FArC, FARC_NONE, true, false);
|
||||
delete thread.f;
|
||||
thread.f = 0;
|
||||
if (thread.f) {
|
||||
thread.f->write(thread.path.c_str(), thread.f->signature, thread.f->flags, true, false);
|
||||
delete thread.f;
|
||||
thread.f = 0;
|
||||
}
|
||||
|
||||
if (thread.state == FARC_COMPRESS_STATE_END)
|
||||
break;
|
||||
@@ -10009,9 +10026,10 @@ obj_set_reflect* x_pack_reflect::get_obj_set_reflect(uint32_t id) {
|
||||
|
||||
XPVGameBaker::XPVGameBaker() : charas(), modules(), pv_tit_aet_set_ids(),
|
||||
pv_tit_spr_set_ids(), pv_tit_aet_ids(), obj_set_encode_flags(), pv_tit_init(),
|
||||
wait(), start(), exit(), next(), only_firstread_x(), write_file() {
|
||||
wait(), start(), exit(), next(), write_file(), only_firstread_x() {
|
||||
index = -1;
|
||||
chara_index = CHARA_MIKU;
|
||||
farc = true;
|
||||
|
||||
for (::chara_index& i : charas)
|
||||
i = CHARA_MIKU;
|
||||
@@ -10101,7 +10119,7 @@ void XPVGameBaker::window() {
|
||||
|
||||
float_t w = 360.0f;
|
||||
float_t h = (float_t)height;
|
||||
h = min_def(h, 228.0f);
|
||||
h = min_def(h, 250.0f);
|
||||
|
||||
ImGui::SetNextWindowPos({ (float_t)width - w, 0.0f }, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
||||
@@ -10121,6 +10139,7 @@ void XPVGameBaker::window() {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("FARC", &farc);
|
||||
ImGui::Checkbox("Write only firstread_x.bin", &only_firstread_x);
|
||||
|
||||
ImGui::SeparatorText("Object Set Encode Flags");
|
||||
@@ -12500,7 +12519,16 @@ static bool x_pv_game_write_auth_3d(farc* f, auth_3d* auth, auth_3d_database_fil
|
||||
bool own_farc = !f;
|
||||
|
||||
if (own_farc)
|
||||
f = new farc;
|
||||
if (out_dir == x_pack_mmp_out_dir) {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, FARC_NONE, true);
|
||||
f->entry_size = 0x11 + (rand() % 0x10);
|
||||
f->header_size = 0x11 + (rand() % 0x20);
|
||||
}
|
||||
else {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC);
|
||||
f->entry_padding = 0x01 + (rand() % 0x10);
|
||||
f->header_padding = 0x01 + (rand() % 0x20);
|
||||
}
|
||||
|
||||
farc_file* ff = f->add_file(name);
|
||||
ff->name.append(".a3da");
|
||||
@@ -13197,7 +13225,8 @@ static void x_pv_game_write_glitter(Glitter::EffectGroup* eff_group, const auth_
|
||||
Glitter::FileWriter::Write(Glitter::X, &temp_eff_group,
|
||||
sprintf_s_string("%s\\%s", out_dir, "particle_x\\").c_str(),
|
||||
name, (Glitter::FileWriterFlags)(Glitter::FILE_WRITER_COMPRESS
|
||||
| Glitter::FILE_WRITER_ENCRYPT | Glitter::FILE_WRITER_NO_LIST));
|
||||
| Glitter::FILE_WRITER_ENCRYPT | Glitter::FILE_WRITER_NO_LIST
|
||||
| (out_dir == x_pack_mmp_out_dir ? Glitter::FILE_WRITER_FT : 0)));
|
||||
}
|
||||
|
||||
static void x_pv_game_write_object_set_material_msgpack_read(const char* path,
|
||||
@@ -13439,7 +13468,18 @@ static void x_pv_game_write_object_set(obj_set* obj_set, const std::string& name
|
||||
::obj_set* set = alloc->allocate<::obj_set>();
|
||||
set->move_data(obj_set, alloc);
|
||||
|
||||
farc* f = new farc;
|
||||
farc* f;
|
||||
if (out_dir == x_pack_mmp_out_dir) {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, (farc_flags)(FARC_AES | FARC_GZIP), true);
|
||||
f->entry_size = 0x11 + (rand() % 0x10);
|
||||
f->header_size = 0x11 + (rand() % 0x20);
|
||||
}
|
||||
else {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, (farc_flags)(FARC_AES | FARC_GZIP));
|
||||
f->entry_padding = 0x01 + (rand() % 0x10);
|
||||
f->header_padding = 0x01 + (rand() % 0x20);
|
||||
}
|
||||
|
||||
{
|
||||
data_struct* x_data = &data_list[DATA_X];
|
||||
|
||||
@@ -13460,6 +13500,7 @@ static void x_pv_game_write_object_set(obj_set* obj_set, const std::string& name
|
||||
farc_file* ff_tex = f->add_file((file_name + "_tex.bin").c_str());
|
||||
txp.pack_file(&ff_tex->data, &ff_tex->size, false);
|
||||
ff_tex->compressed = true;
|
||||
ff_tex->encrypted = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13629,6 +13670,7 @@ static void x_pv_game_write_object_set(obj_set* obj_set, const std::string& name
|
||||
farc_file* ff_obj = f->add_file((file_name + "_obj.bin").c_str());
|
||||
set->pack_file(&ff_obj->data, &ff_obj->size);
|
||||
ff_obj->compressed = true;
|
||||
ff_obj->encrypted = true;
|
||||
}
|
||||
|
||||
farc_compress_ptr->AddFarc(f, sprintf_s_string("%s\\objset\\%s", out_dir, file_name.c_str()));
|
||||
@@ -14560,11 +14602,22 @@ static void x_pv_game_write_spr(uint32_t spr_set_id,
|
||||
|
||||
x_pv_game_fix_txp_set(set->txp, out_dir);
|
||||
|
||||
farc* f = new farc;
|
||||
farc* f;
|
||||
if (out_dir == x_pack_mmp_out_dir) {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, (farc_flags)(FARC_AES | FARC_GZIP), true);
|
||||
f->entry_size = 0x11 + (rand() % 0x10);
|
||||
f->header_size = 0x11 + (rand() % 0x20);
|
||||
}
|
||||
else {
|
||||
f = new farc(x_pv_game_baker_ptr->farc ? FARC_FARC : FARC_FArC, (farc_flags)(FARC_AES | FARC_GZIP));
|
||||
f->entry_padding = 0x01 + (rand() % 0x10);
|
||||
f->header_padding = 0x01 + (rand() % 0x20);
|
||||
}
|
||||
|
||||
farc_file* ff_bin = f->add_file(spr_db_spr_set->file_name.c_str());
|
||||
set->pack_file(&ff_bin->data, &ff_bin->size);
|
||||
ff_bin->compressed = true;
|
||||
ff_bin->encrypted = true;
|
||||
|
||||
file_name.assign(spr_db_spr_set->file_name);
|
||||
pos = file_name.rfind(".bin");
|
||||
|
||||
@@ -958,6 +958,7 @@ public:
|
||||
bool next;
|
||||
bool write_file;
|
||||
bool only_firstread_x;
|
||||
bool farc;
|
||||
|
||||
aet_database pv_tit_aet_db;
|
||||
sprite_database pv_tit_spr_db;
|
||||
|
||||
Reference in New Issue
Block a user