Files

140 lines
3.5 KiB
Plaintext
Raw Permalink Normal View History

2023-02-15 10:09:07 -08:00
#ifndef _CPAKFILE
#define _CPAKFILE
2025-12-07 10:37:47 -08:00
#include "Common.bt"
struct File;
2023-02-13 13:22:03 -05:00
struct CPakFile;
2023-02-13 16:25:12 -05:00
typedef struct
{
2023-02-13 01:30:24 -05:00
FourCC type;
GUID id;
2023-02-15 13:02:51 -05:00
if (!isDKCTF)
2023-02-14 19:55:38 -08:00
{
uint32 versionA;
uint32 versionB;
}
2023-02-15 13:02:51 -05:00
uint64 offset <format=hex>;
if (!isDKCTF)
2023-02-14 19:55:38 -08:00
{
2023-02-15 13:02:51 -05:00
uint64 decompressedSize <format=hex>;
2023-02-14 19:55:38 -08:00
}
2023-02-15 13:02:51 -05:00
uint64 size <format=hex>;
if (isDKCTF)
2023-02-14 19:55:38 -08:00
{
2023-02-15 13:02:51 -05:00
local uint64 decompressedSize <hidden=true> = size;
2023-02-14 19:55:38 -08:00
}
2025-12-07 10:37:47 -08:00
if (pak.toc.readerVersion == 4) {
uint64 unk;
}
2023-02-13 01:30:24 -05:00
local uint64 pos <format=hex, hidden=true> = FTell();
2025-12-07 10:37:47 -08:00
2023-02-13 01:30:24 -05:00
FSeek(offset);
2023-02-15 13:02:51 -05:00
if (size == decompressedSize) {
2023-02-13 16:25:12 -05:00
File data <size=size>;
2025-12-07 10:37:47 -08:00
} else {
2023-02-15 13:02:51 -05:00
CompressionType compressionType;
byte pad[3] <hidden=true>;
byte compressedData[size - 4];
}
2023-02-13 01:30:24 -05:00
FSeek(pos);
2023-02-13 16:25:12 -05:00
} AssetDirectoryEntry <
2025-12-09 22:49:14 -07:00
size=(isDKCTF ? 36 : (pak.toc.readerVersion == 4 ? 60 : 52)), // Parse on-demand
2023-02-15 13:02:51 -05:00
name=AssetDirectoryEntryName,
comment=(SizeComment(this.size))
2023-02-13 16:25:12 -05:00
>;
2023-02-13 01:30:24 -05:00
2023-02-15 13:02:51 -05:00
string AssetDirectoryEntryName(AssetDirectoryEntry& entry)
{
if (isDKCTF) {
// Read the chunk ver and subver from form descriptor
2023-02-20 12:11:22 -08:00
return Str("%s v%d.%d %s", entry.type, entry.data.form.readerVersion, entry.data.form.writerVersion, GUIDToString(entry.id)); //Fix broken DKCTF version display
2023-02-15 13:02:51 -05:00
} else {
return Str("%s v%d.%d %s", entry.type, entry.versionA, entry.versionB, GUIDToString(entry.id));
}
}
2023-02-13 16:25:12 -05:00
typedef struct
{
2023-02-13 01:30:24 -05:00
GUID id;
2023-02-15 13:02:51 -05:00
uint32 offset <format=hex>;
2023-02-13 13:22:03 -05:00
// Find the FourCC for the asset ID
// Assumes TOCC chunk 0 is ADIR
local FourCC type <hidden=true>;
2023-02-14 19:55:38 -08:00
local uint64 fileOffset <hidden=true>;
2023-02-13 16:25:12 -05:00
local uint32 i <hidden=true>;
for (i = 0; i < pak.chunk[0].count; i++) {
if (pak.chunk[0].entry[i].id == id) {
type = pak.chunk[0].entry[i].type;
2023-02-14 19:55:38 -08:00
fileOffset = pak.chunk[0].entry[i].offset;
2023-02-13 16:25:12 -05:00
break;
2023-02-13 13:22:03 -05:00
}
}
local uint64 pos <format=hex, hidden=true> = FTell();
FSeek(start + offset);
2023-02-15 13:02:51 -05:00
uint32 size <format=hex>;
2023-02-14 19:55:38 -08:00
Meta data(type, size, fileOffset);
2023-02-13 13:22:03 -05:00
FSeek(pos);
2023-02-13 16:25:12 -05:00
} MetaEntry <
size=20, // Parse on-demand
name=(Str("%s %s", this.type, GUIDToString(this.id))),
comment=(SizeComment(size))
>;
2023-02-13 01:30:24 -05:00
2023-02-13 16:25:12 -05:00
typedef struct
{
// Byteswapped
2023-02-13 13:22:03 -05:00
uint32 type <read=FourCCInt>;
2023-02-13 01:30:24 -05:00
GUID id;
2023-02-15 13:47:06 -05:00
// Wii U DKCTF uses a null terminated string here
// but PACK/TOCC version is the same
if (!isDKCTF || ReadByte() == 0) {
uint32 length;
char name[length];
} else {
string name;
}
2023-02-13 16:25:12 -05:00
} StringEntry <
name=(Str("%s (%s) %s", name, FourCCInt(type), GUIDToString(id)))
>;
2023-02-13 01:30:24 -05:00
2023-02-13 16:25:12 -05:00
typedef struct(CPakFile& pak)
2023-02-13 01:30:24 -05:00
{
ChunkDescriptor chunk;
2023-02-13 01:46:39 -05:00
local uint64 start <format=hex, hidden=true> = FTell();
2023-02-13 01:30:24 -05:00
switch (chunk.id)
{
case "ADIR":
2023-02-13 16:25:12 -05:00
uint32 count <format=decimal, name="ADIR entry count">;
AssetDirectoryEntry entry[count] <optimize=false>;
2023-02-13 01:30:24 -05:00
break;
case "META":
2023-02-13 16:25:12 -05:00
uint32 count <format=decimal, name="META entry count">;
MetaEntry entry[count] <optimize=false>;
2023-02-13 01:30:24 -05:00
break;
case "STRG":
2023-02-13 16:25:12 -05:00
uint32 count <format=decimal, name="STRG entry count">;
2023-02-13 01:30:24 -05:00
StringEntry entry[count] <optimize=false>;
break;
}
FSeek(start + chunk.size);
2023-02-13 16:25:12 -05:00
} TOCChunk <
name=(Str("%s chunk", chunk.id)),
comment=(Str("%d entries", count))
>;
2023-02-13 01:30:24 -05:00
2023-02-13 16:25:12 -05:00
typedef struct
2023-02-13 01:30:24 -05:00
{
FormDescriptor toc;
local uint64 start <format=hex, hidden=true> = FTell();
2023-02-13 16:25:12 -05:00
while (FTell() < start + toc.size)
{
2023-02-13 13:22:03 -05:00
TOCChunk chunk(this);
2023-02-13 01:30:24 -05:00
}
2023-02-13 16:25:12 -05:00
} CPakFile <name="PACK chunks">;
2023-02-15 10:09:07 -08:00
#endif// _CPAKFILE