Reimplement decode_f4(). It uses RLE.

This commit is contained in:
lzwdgc 2018-01-28 03:28:43 +03:00
parent aad50f9160
commit 13be828ef6
4 changed files with 111 additions and 18 deletions

View file

@ -222,7 +222,7 @@ int decode_f3(char *input, int size, char *output)
v10 = v21;
memset32(v16, v18, v15 >> 1);
v19 = (int)((char *)v16 + 4 * (v15 >> 1));
for (i = (v13 + 3) & 1; i; --i)
for (i = v15 & 1; i; --i)
{
*(_WORD *)v19 = v18;
v19 += 2;
@ -231,7 +231,10 @@ int decode_f3(char *input, int size, char *output)
}
goto LABEL_13;
}
*(_WORD *)v11 = *(_WORD *)&v4[2 * idx];
else
{
*(_WORD *)v11 = *(_WORD *)&v4[2 * idx];
}
}
else
{
@ -307,3 +310,69 @@ int decode_f4(char *input, int size, char *output, int segment_offset)
}
return result;
}
void decode_rle(const short *input, const int size, short *output)
{
if (size < 2)
return;
// input ptr, also rle_indicator
const auto rle_indicator = input++;
while (1)
{
auto c = *input++;
if ((c & 0xFF00) != (*rle_indicator << 8))
*output++ = c;
else
{
uint32_t count = (uint8_t)c;
if (count == (*rle_indicator << 8) + 255)
*output++ = c; // insert indicator byte itself
else
{
count += 3;
for (int i = 0; i < count / 2; i++)
{
*output++ = *input;
*output++ = *input;
}
for (int i = 0; i < ((count / 2) & 1); i++)
{
*output++ = *input;
}
}
}
if (input >= rle_indicator + size)
return;
}
}
void decode_rle(const char *input, const int size, char *output)
{
if (size < 2)
return;
// input ptr, also rle_indicator
const auto rle_indicator = input++;
while (1)
{
auto c = *input++;
if (c != *rle_indicator)
*output++ = c;
else
{
uint32_t count = (uint8_t)*input++;
if (count == 255)
*output++ = *rle_indicator; // insert indicator byte itself
else
{
memset(output, *input++, count += 3);
output += count;
}
}
if (input >= rle_indicator + size)
return;
}
}

View file

@ -27,8 +27,6 @@
#define FREAD(var) fread(&var, 1, sizeof(var), f)
const int header_size = 0xC;
void header::load(FILE *f)
{
FREAD(unk1);
@ -42,7 +40,9 @@ void header::load(FILE *f)
void record::load(FILE *f)
{
FREAD(name);
char n[0x50];
FREAD(n);
name = n;
FREAD(pos);
FREAD(len);
}
@ -96,7 +96,7 @@ int record::read(pak *pak, void *output, int size)
void segment::load_header(FILE *f)
{
FREAD(unk1);
FREAD(flags);
FREAD(algorithm);
FREAD(offset);
}
@ -105,7 +105,7 @@ void segment::load_segment()
auto f = file;
fseek(f, offset, SEEK_SET);
if (flags == 0)
if (algorithm == 0)
{
std::cerr << "Something is wrong. Maybe you trying to open aim2 files?\n";
std::cerr << "They can be opened with SDK extractor.\n";
@ -114,7 +114,7 @@ void segment::load_segment()
FREAD(size1);
size2 = size1;
if ((flags & 0x3) && (flags & 0xC))
if ((algorithm & 0x3) && (algorithm & 0xC))
{
FREAD(size2);
fread(&decoded[0], 1, size2, f);
@ -129,19 +129,30 @@ void segment::decompress(int segment_id)
{
load_segment();
if (flags & 0xC)
if ((algorithm & DA_1) || (algorithm & DA_2))
{
if (flags & 0x4)
if (algorithm & DA_1)
decode_f1((char*)decoded, size2, (char*)encoded);
else
decode_f2((char*)decoded, size2, (char*)encoded);
}
if (flags & 0x3)
if ((algorithm & RLE_1_byte) || (algorithm & RLE_2_bytes))
{
if (flags & 0x1)
decode_f3((char*)encoded, size1, (char*)decoded);
if (algorithm & RLE_2_bytes)
{
//static std::vector<uint8_t> buf(4194432);
decode_f3((char*)encoded, size1, (char*)decoded/*buf.data()*/);
//decode_rle((short*)encoded, size1, (short*)decoded);
//assert(memcmp(decoded, buf.data(), size1) == 0);
}
else
decode_f4((char*)encoded, size1, (char*)decoded, segment_id * header_size);
{
//static std::vector<uint8_t> buf(4194432);
//const int header_size = 0xC;
//decode_f4((char*)encoded, size1, (char*)buf.data(), segment_id * header_size);
decode_rle((char*)encoded, size1, (char*)decoded);
//assert(memcmp(decoded, buf.data(), size1) == 0);
}
}
}

View file

@ -40,7 +40,7 @@ struct header
struct record
{
char name[0x50];
std::string name;
uint32_t pos;
uint32_t len;
@ -55,8 +55,16 @@ struct record
struct segment
{
enum decode_algorithm
{
RLE_2_bytes = 0x1,
RLE_1_byte = 0x2,
DA_1 = 0x4,
DA_2 = 0x8,
};
uint32_t unk1;
uint32_t flags;
decode_algorithm algorithm;
uint32_t offset;
uint32_t size1;

View file

@ -27,14 +27,19 @@ void unpak(string fn)
return;
pak p;
p.load(f);
for (auto &f : p.files)
auto unpack = [&](auto &file)
{
record &file = f.second;
cout << "Unpacking " << file.name << "\n";
vector<char> buf(file.len);
file.read(&p, &buf[0], file.len);
file.write(fn + ".dir", buf);
};
unpack(p.files["arena.mmp"]);
//for (auto &[n,f] : p.files)
//unpack(f);
fclose(f);
}