LostWinds 1-2 .ovl

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: LostWinds 1-2 .ovl

Post by aluigi »

I have noticed that there are various topics about these OVL archives with "FRES" magic and all of them are without a solution:
viewtopic.php?t=3000
viewtopic.php?t=3159
viewtopic.php?t=949
viewtopic.php?t=1517

What's particularly bad is my comment here:
viewtopic.php?p=8279#p8279

I trust what I said there and follow my suggestion, better to not spend time on it.
makc_ar
Posts: 1193
Joined: Sun Aug 17, 2014 7:27 pm

Re: LostWinds 1-2 .ovl

Post by makc_ar »

Binary Template Elite Dangerous to make script?

Code: Select all

//------------------------------------------------
//--- 010 Editor v7.0 Binary Template
//
//      File: OVL.bt
//    Author: Andrew McRae
//   Version: 0.3
//   Purpose: Parse Elite Dangerous ovl files
//  Category: Archive
// File Mask: *.ovl
//  ID Bytes: 46 52 45 53 // FRES
//   History:
//   0.3   2016-03-30 Andrew McRae: Updated header for repo
//   0.2   2015-08-03 Andrew McRae: Merge changes
//   0.1   2015-03-10 Andrew McRae: Initial revision
//------------------------------------------------

typedef uint64 u8;
typedef uint32 u4;
typedef uint16 u2;
typedef ubyte  u1;
typedef int64  s8;
typedef int32  s4;
typedef int16  s2;
typedef byte   s1;

local u4 zlib_length = 0;
local u4 zlib_uncomp_length = 0;

typedef struct {
    char sig[4];                        // 1575F48

    u1 flags;                           // 1575F4C
    u1 version;                         // 1575F4D

    u1 need_bswap;                      // 1575F4E
    u1 unknown07 <bgcolor=0xd8d8d8>;    // 1575F4F
    u4 flags2;                          // 1575F50
    u4 unknown0C <bgcolor=0xd8d8d8>;    // 1575F54

    u4 names_length;                    // 1575F58

    u4 unknown2_count <format=decimal>; // 1575F5C
    u4 other_count <format=decimal>;    // 1575F60
    u2 dir_count <format=decimal>;      // 1575F64
    u2 type_count <format=decimal>;     // 1575F66
    u4 file_count <format=decimal>;     // 1575F68
    u4 file_count2 <format=decimal>;    // 1575F6C
    u4 part_count <format=decimal>;     // 1575F70
    u4 archive_count <format=decimal>;  // 1575F74

    u4 unknown30 <bgcolor=0xd8d8d8>;    // 1575F78
    u4 unknown34 <bgcolor=0xd8d8d8>;    // 1575F7C
    u4 unknown38 <bgcolor=0xd8d8d8>;    // 1575F80
    u4 unknown3C <bgcolor=0xd8d8d8>;    // 1575F84

    u4 unknown_count <format=decimal>;  // 1575F88

    u4 unknown44 <bgcolor=0xd8d8d8>;    // 1575F8C
    u4 unknown48 <bgcolor=0xd8d8d8>;    // 1575F90
    u4 unknown4C <bgcolor=0xd8d8d8>;    // 1575F94

    //Assert((flags == 0) || (flags == 0x08), "HEADER flags not 0 or 0x08");
    Assert((version == 0x12) || (version == 0x13), "HEADER version not 0x12 or 0x13");
    Assert(file_count2 == file_count, "HEADER file_count2 mismatch");
    Assert((file_count == 0) || (names_length > 0), "HEADER names_length is 0");
    //Assert(dir_count == 0, "HEADER dir_count not 0");
    //Assert(part_count == 0, "HEADER part_count not 0");
    //Assert(other_count == 0, "HEADER other_count not 0");
    //Assert(archive_count == 1, "HEADER archive_count not 1");
    Assert(unknown2_count == 0, "HEADER unknown2_count not 0");
    //Assert(!(dir_count != 0 && part_count != 0), "HEADER dir and part");
    Assert(!(dir_count != 0 && other_count != 0), "HEADER dir and other");
    Assert(!(part_count != 0 && other_count != 0), "HEADER part and other");

    //Assert(flags2 == 0x00006094, "HEADER flags2 not 0x00006094");
} HEADER;

typedef struct {
    u4 archive_names_length;
    u4 file_count3 <format=decimal>;
    u4 type_names_length;

    u4 zero0C <hidden=true,bgcolor=cNone>;
    u4 zero10 <hidden=true,bgcolor=cNone>;
    u4 zero14 <hidden=true,bgcolor=cNone>;
    u4 zero18 <hidden=true,bgcolor=cNone>;
    u4 zero1C <hidden=true,bgcolor=cNone>;
    u4 zero20 <hidden=true,bgcolor=cNone>;
    u4 zero24 <hidden=true,bgcolor=cNone>;
    u4 zero28 <hidden=true,bgcolor=cNone>;
    u4 zero2C <hidden=true,bgcolor=cNone>;
    u4 zero30 <hidden=true,bgcolor=cNone>;
    u4 zero34 <hidden=true,bgcolor=cNone>;
    u4 zero38 <hidden=true,bgcolor=cNone>;
    u4 zero3C <hidden=true,bgcolor=cNone>;

    Assert((h.archive_count == 0) || (archive_names_length > 0), "HEADER archive_names_length is 0");
    Assert((h.file_count == 0) || (type_names_length > 0), "HEADER2 type_names_length is 0");
    Assert(file_count3 == h.file_count, "HEADER2 file_count3 mismatch");

    Assert(zero0C == 0, "HEADER2 zero0C");
    Assert(zero10 == 0, "HEADER2 zero10");
    Assert(zero14 == 0, "HEADER2 zero14");
    Assert(zero18 == 0, "HEADER2 zero18");
    Assert(zero1C == 0, "HEADER2 zero1C");
    Assert(zero20 == 0, "HEADER2 zero20");
    Assert(zero24 == 0, "HEADER2 zero24");
    Assert(zero28 == 0, "HEADER2 zero28");
    Assert(zero2C == 0, "HEADER2 zero2C");
    Assert(zero30 == 0, "HEADER2 zero30");
    Assert(zero34 == 0, "HEADER2 zero34");
    Assert(zero38 == 0, "HEADER2 zero38");
    Assert(zero3C == 0, "HEADER2 zero3C");
} HEADER2;

typedef struct {
    u4 name_offset;
    if (is64bit) {
        u4 zero04 <hidden=true,bgcolor=cNone>;;
    }
    u4 hash;

    u2 unknown08 <bgcolor=0xffd8d8>;
    u2 unknown0A <bgcolor=0xffd8d8>;
    u4 unknown0C <bgcolor=0xffd8d8>;
    u4 count <format=decimal>;

    Assert(name_offset < h.names_length, "TYPE name_offset too high");
    if (is64bit) {
        Assert(zero04 == 0, "TYPE zero60");
    }

    local quad o = FTell();
    FSeek(name_offset + full_names_offset);

    string name <bgcolor=0xff6060>;

    FSeek(o);
} TYPE <optimize=false,read=read_TYPE>;
string read_TYPE(TYPE &in) {
    local string out;
    SPrintf(out, "\"%s\" %08Xh %Xh %Xh %Xh %d", in.name, in.hash, in.unknown08, in.unknown0A, in.unknown0C, in.count);
    return out;
}

typedef struct {
    TYPE t[h.type_count];
} TYPES <read=read_TYPES>;
string read_TYPES(TYPES &in) {
    local string out;
    SPrintf(out, "%u", h.type_count);
    return out;
}

typedef struct {
    u4 name_offset;
    u4 hash;

    u2 unknown08 <bgcolor=0xd8ffd8>;

    u2 type <format=decimal>;

    Assert(type < h.type_count, "FILE type too high");
    Assert(name_offset < h.names_length, "FILE name_offset too high");

    local quad o = FTell();
    FSeek(name_offset + full_names_offset);

    string name <bgcolor=0x60ff60>;

    FSeek(o);
} FILE <optimize=false,read=read_FILE>;
string read_FILE(FILE &in) {
    local string out;
    SPrintf(out, "\"%s\" \"%s\" %08Xh %Xh", in.name, t.t[in.type].name, in.hash, in.unknown08);
    return out;
}

typedef struct {
    FILE f[h.file_count];
} FILES <read=read_FILES>;
string read_FILES(FILES &in) {
    local string out;
    SPrintf(out, "%u", h.file_count);
    return out;
}

typedef struct {
    u4 name_offset;

    u4 unknown04 <bgcolor=0xd8d8ff>;
    u4 unknown08 <bgcolor=0xd8d8ff>;
    u4 fh2_count <format=decimal>;
    u2 fh3_count <format=decimal>;
    u2 fh1_count <format=decimal>;
    u4 zero14 <bgcolor=0xd8d8ff>;
    u4 unknown18 <bgcolor=0xd8d8ff>;
    u4 fh6_count <format=decimal>;
    u4 fh5_count <format=decimal>;
    u4 zero24 <bgcolor=0xd8d8ff>;
    u4 unknown28 <bgcolor=0xd8d8ff>;

    u4 comp_size;
    u4 uncomp_size;

    u4 zero34 <bgcolor=0xd8d8ff>;
    u4 unknown38 <bgcolor=0xd8d8ff>;
    u4 header2_size;
    u4 unknown40 <bgcolor=0xd8d8ff>;

    Assert(name_offset < h2.archive_names_length, "FILE name_offset too high");

    local quad o = FTell();
    FSeek(name_offset + full_archive_names_offset);

    string name <bgcolor=0x6060ff>;

    FSeek(o);

    // check if STATIC archive
    if (name == "STATIC") {
        zlib_length = comp_size;
        zlib_uncomp_length = uncomp_size;
    }

    //Assert(unknown04 == 0, "ARCHIVE unknown04");
    //Assert(unknown08 == 0, "ARCHIVE unknown08");
    Assert(zero14 == 0, "ARCHIVE zero14");
    Assert(zero24 == 0, "ARCHIVE zero24");
    Assert(zero34 == 0, "ARCHIVE zero34");
    //Assert(unknown38 == 0, "ARCHIVE unknown38");
    //Assert(unknown40 == 0, "ARCHIVE unknown40");
} ARCHIVE <optimize=false,read=read_ARCHIVE>;
string read_ARCHIVE(ARCHIVE &in) {
    local string out;
    SPrintf(out, "\"%s\" %Xh %Xh", in.name, in.comp_size, in.uncomp_size);
    return out;
}

typedef struct {
    ARCHIVE a[h.archive_count];
} ARCHIVES <read=read_ARCHIVES>;
string read_ARCHIVES(ARCHIVES &in) {
    local string out;
    SPrintf(out, "%u", h.archive_count);
    return out;
}

typedef struct {
    u4 name_offset;

    Assert(name_offset < h.names_length, "DIR name_offset too high");

    local quad o = FTell();
    FSeek(name_offset + full_names_offset);

    string name <bgcolor=0x60ffff>;

    FSeek(o);
} DIR <optimize=false,read=read_DIR>;
string read_DIR(DIR &in) {
    local string out;
    SPrintf(out, "\"%s\"", in.name);
    return out;
}

typedef struct {
    DIR d[h.dir_count];
} DIRS <read=read_DIRS>;
string read_DIRS(DIRS &in) {
    local string out;
    SPrintf(out, "%u", h.dir_count);
    return out;
}

typedef struct {
    u4 hash;
    u4 name_offset;

    u4 unknown08 <bgcolor=0xffd8ff>;
    u4 unknown0C <bgcolor=0xffd8ff>;
    u4 unknown10 <bgcolor=0xffd8ff>;

    Assert(name_offset < h.names_length, "PART name_offset too high");

    local quad o = FTell();
    FSeek(name_offset + full_names_offset);

    string name <bgcolor=0xff60ff>;

    FSeek(o);
} PART <optimize=false,read=read_PART>;
string read_PART(PART &in) {
    local string file_name;
    SPrintf(file_name, "%08Xh", in.hash);
    local int i;
    for (i = 0; i < h.file_count; i++) {
        if (f.f[i].hash == in.hash) {
            SPrintf(file_name, "\"%s\"", f.f[i].name);
            break;
        }
    }

    local string out;
    SPrintf(out, "%s \"%s\" %Xh %Xh %Xh", file_name, in.name, in.unknown08, in.unknown0C, in.unknown10);
    return out;
}

typedef struct {
    PART p[h.part_count];
} PARTS <read=read_PARTS>;
string read_PARTS(PARTS &in) {
    local string out;
    SPrintf(out, "%u", h.part_count);
    return out;
}

typedef struct {
    u4 unknown00 <bgcolor=0xffffd8>;

    u4 name_offset;

    u4 unknown08 <bgcolor=0xffffd8>;

    Assert(name_offset < h.names_length, "OTHER name_offset too high");

    local quad o = FTell();
    FSeek(name_offset + full_names_offset);

    string name <bgcolor=0xffff60>;

    FSeek(o);
} OTHER <optimize=false,read=read_OTHER>;
string read_OTHER(OTHER &in) {
    local string out;
    SPrintf(out, "\"%s\" %Xh %08Xh", in.name, in.unknown00, in.unknown08);
    return out;
}

typedef struct {
    OTHER o[h.other_count];
} OTHERS <read=read_OTHERS>;
string read_OTHERS(OTHERS &in) {
    local string out;
    SPrintf(out, "%u", h.other_count);
    return out;
}

typedef struct {
    u4 unknown00 <bgcolor=0x6cd0ff>;
    u4 unknown04 <bgcolor=0x6cd0ff>;
    u4 unknown08 <bgcolor=0x6cd0ff>;
} UNKNOWN <optimize=false,read=read_UNKNOWN>;
string read_UNKNOWN(UNKNOWN &in) {
    local string out;
    SPrintf(out, "%Xh %Xh %Xh", in.unknown00, in.unknown04, in.unknown08);
    return out;
}

typedef struct {
    UNKNOWN u[h.unknown_count];
} UNKNOWNS <read=read_UNKNOWNS>;
string read_UNKNOWNS(UNKNOWNS &in) {
    local string out;
    SPrintf(out, "%u", h.unknown_count);
    return out;
}

typedef struct {
    u4 unknown00 <bgcolor=0xffd06c>;
    u4 data_size <bgcolor=0xffd06c>;
} ARCHIVE2 <optimize=false,read=read_ARCHIVE2>;
string read_ARCHIVE2(ARCHIVE2 &in) {
    local string out;
    SPrintf(out, "%Xh %Xh", in.unknown00, in.data_size);
    return out;
}

typedef struct {
    ARCHIVE2 a2[h.archive_count];
} ARCHIVES2 <read=read_ARCHIVES2>;
string read_ARCHIVES2(ARCHIVES2 &in) {
    local string out;
    SPrintf(out, "%u", h.archive_count);
    return out;
}

typedef struct {
    Assert(zlib_length > 0, "ZLIB zlib_length is 0");
    Assert(ReadUShort() == 0x9c78, "ZLIB bad zlib header");

    u1 data[zlib_length];

    Assert(FTell() == FileSize(), "ZLIB trailing data");
} ZLIB <read=read_ZLIB>;
string read_ZLIB(ZLIB &in) {
    local string out;
    SPrintf(out, "%Xh %Xh", zlib_length, zlib_uncomp_length);
    return out;
}

DisplayFormatHex();
LittleEndian();

local int i;

Assert(ReadString(0, 4) == "FRES", "Bad sig!");

local u4 full_names_offset = 0x90;

SetBackColor(0xb0b0b0);
HEADER h;
HEADER2 h2;

local int is64bit = h.flags & 0x08;

// skip main name table
local u4 full_types_offset = h.names_length + full_names_offset;
FSeek(full_types_offset);

SetBackColor(0xffb0b0);
if (h.type_count) {
    TYPES t;
}

SetBackColor(0xb0ffb0);
if (h.file_count) {
    FILES f;
}

// skip archive name table
local u4 full_archive_names_offset;
local u4 full_archives_offset;
if (is64bit) {
    full_archive_names_offset = h.file_count * 0x0C + h.type_count * 0x18 + full_types_offset;
} else {
    full_archive_names_offset = h.file_count * 0x0C + h.type_count * 0x14 + full_types_offset;
}
full_archives_offset = h2.archive_names_length + full_archive_names_offset;
FSeek(full_archives_offset);

SetBackColor(0xb0b0ff);
if (h.archive_count) {
    ARCHIVES a;
}

SetBackColor(0xb0ffff);
if (h.dir_count) {
    DIRS d;
}

SetBackColor(0xffb0ff);
if (h.part_count) {
    PARTS p;
}

SetBackColor(0xffffb0);
if (h.other_count) {
    OTHERS o;
}

SetBackColor(0x48a0ff);
if (h.unknown_count) {
    UNKNOWNS u;
}

SetBackColor(0xffa048);
if (h.archive_count) {
    ARCHIVES2 a2;
}

SetBackColor(0x909090);
ZLIB z;

if (h.archive_count) {
    for (i = 0; i < h.archive_count; i++) {
        Printf("\nname: %s, comp_size: %Xh, uncomp_size: %Xh\n", a.a[i].name, a.a[i].comp_size, a.a[i].uncomp_size);
        Printf("header2_size: %Xh, data_size: %Xh\n", a.a[i].header2_size, a2.a2[i].data_size);
        Printf("(%d, %d, %d, ?, %d, %d, ?)\n", a.a[i].fh1_count, a.a[i].fh2_count, a.a[i].fh3_count, a.a[i].fh5_count, a.a[i].fh6_count);
    }
}
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: LostWinds 1-2 .ovl

Post by aluigi »

Sure, I need time and moreover desire :D
In short: no.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: LostWinds 1-2 .ovl

Post by aluigi »

Just FYI, that 010 script doesn't work with most of the ovl files that you provided and there is not even zlib/deflate data.