forked from Mirror/GodMode9
130 lines
3.7 KiB
C
130 lines
3.7 KiB
C
|
#pragma once
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
|
||
|
// info taken from here:
|
||
|
// http://3dbrew.org/wiki/DISA_and_DIFF
|
||
|
// https://github.com/wwylele/3ds-save-tool
|
||
|
|
||
|
#define DISA_MAGIC 'D', 'I', 'S', 'A', 0x00, 0x00, 0x04, 0x00
|
||
|
#define DIFF_MAGIC 'D', 'I', 'F', 'F', 0x00, 0x00, 0x03, 0x00
|
||
|
#define IVFC_MAGIC 'I', 'V', 'F', 'C', 0x00, 0x00, 0x02, 0x00
|
||
|
#define DPFS_MAGIC 'D', 'P', 'F', 'S', 0x00, 0x00, 0x01, 0x00
|
||
|
#define DIFI_MAGIC 'D', 'I', 'F', 'I', 0x00, 0x00, 0x01, 0x00
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
u8 magic[8]; // "DISA" 0x00040000
|
||
|
u32 n_partitions;
|
||
|
u8 padding0[4];
|
||
|
u64 offset_table1;
|
||
|
u64 offset_table0;
|
||
|
u64 size_table;
|
||
|
u64 offset_descA;
|
||
|
u64 size_descA;
|
||
|
u64 offset_descB;
|
||
|
u64 size_descB;
|
||
|
u64 offset_partitionA;
|
||
|
u64 size_partitionA;
|
||
|
u64 offset_partitionB;
|
||
|
u64 size_partitionB;
|
||
|
u8 active_table; // 0 or 1
|
||
|
u8 padding1[3];
|
||
|
u8 hash_table[0x20]; // for the active table
|
||
|
u8 unused[0x74];
|
||
|
} __attribute__((packed)) DisaHeader;
|
||
|
|
||
|
typedef struct {
|
||
|
u8 magic[8]; // "DIFF" 0x00030000
|
||
|
u64 offset_table1; // also desc offset
|
||
|
u64 offset_table0; // also desc offset
|
||
|
u64 size_table; // includes desc size
|
||
|
u64 offset_partition;
|
||
|
u64 size_partition;
|
||
|
u32 active_table; // 0 or 1
|
||
|
u8 hash_table[0x20]; // for the active table
|
||
|
u64 unique_id; // see: http://3dbrew.org/wiki/Extdata
|
||
|
u8 unused[0xA4];
|
||
|
} __attribute__((packed)) DiffHeader;
|
||
|
|
||
|
typedef struct {
|
||
|
u8 magic[8]; // "DIFI" 0x00010000
|
||
|
u64 offset_ivfc; // always 0x44
|
||
|
u64 size_ivfc; // always 0x78
|
||
|
u64 offset_dpfs; // always 0xBC
|
||
|
u64 size_dpfs; // always 0x50
|
||
|
u64 offset_hash; // always 0x10C
|
||
|
u64 size_hash; // may include padding
|
||
|
u8 ivfc_use_extlvl4;
|
||
|
u8 dpfs_lvl1_selector;
|
||
|
u8 padding[2];
|
||
|
u64 ivfc_offset_extlvl4;
|
||
|
} __attribute__((packed)) DifiHeader;
|
||
|
|
||
|
typedef struct {
|
||
|
u8 magic[8]; // "IVFC" 0x00020000
|
||
|
u64 size_hash; // same as the one in DIFI, may include padding
|
||
|
u64 offset_lvl1;
|
||
|
u64 size_lvl1;
|
||
|
u32 log_lvl1;
|
||
|
u8 padding0[4];
|
||
|
u64 offset_lvl2;
|
||
|
u64 size_lvl2;
|
||
|
u32 log_lvl2;
|
||
|
u8 padding1[4];
|
||
|
u64 offset_lvl3;
|
||
|
u64 size_lvl3;
|
||
|
u32 log_lvl3;
|
||
|
u8 padding2[4];
|
||
|
u64 offset_lvl4;
|
||
|
u64 size_lvl4;
|
||
|
u64 log_lvl4;
|
||
|
u64 size_ivfc; // 0x78
|
||
|
} __attribute__((packed)) IvfcDescriptor;
|
||
|
|
||
|
typedef struct {
|
||
|
u8 magic[8]; // "DPFS" 0x00010000
|
||
|
u64 offset_lvl1;
|
||
|
u64 size_lvl1;
|
||
|
u32 log_lvl1;
|
||
|
u8 padding0[4];
|
||
|
u64 offset_lvl2;
|
||
|
u64 size_lvl2;
|
||
|
u32 log_lvl2;
|
||
|
u8 padding1[4];
|
||
|
u64 offset_lvl3;
|
||
|
u64 size_lvl3;
|
||
|
u32 log_lvl3;
|
||
|
u8 padding2[4];
|
||
|
} __attribute__((packed)) DpfsDescriptor;
|
||
|
|
||
|
typedef struct {
|
||
|
DifiHeader difi;
|
||
|
IvfcDescriptor ivfc;
|
||
|
DpfsDescriptor dpfs;
|
||
|
u8 hash[0x20];
|
||
|
u8 padding[4]; // all zeroes when encrypted
|
||
|
} __attribute__((packed)) DifiStruct;
|
||
|
|
||
|
// condensed info to enable reading IVFC lvl4
|
||
|
typedef struct {
|
||
|
u32 offset_dpfs_lvl1; // relative to start of file
|
||
|
u32 offset_dpfs_lvl2; // relative to start of file
|
||
|
u32 offset_dpfs_lvl3; // relative to start of file
|
||
|
u32 size_dpfs_lvl1;
|
||
|
u32 size_dpfs_lvl2;
|
||
|
u32 size_dpfs_lvl3;
|
||
|
u32 log_dpfs_lvl2;
|
||
|
u32 log_dpfs_lvl3;
|
||
|
u32 offset_ivfc_lvl4; // relative to DPFS lvl3 if not external
|
||
|
u32 size_ivfc_lvl4;
|
||
|
u8 dpfs_lvl1_selector;
|
||
|
u8 ivfc_use_extlvl4;
|
||
|
u8* dpfs_lvl2_cache; // optional, NULL when unused
|
||
|
} __attribute__((packed)) DisaDiffReaderInfo;
|
||
|
|
||
|
u32 GetDisaDiffReaderInfo(const char* path, DisaDiffReaderInfo* info, bool partitionB);
|
||
|
u32 BuildDisaDiffDpfsLvl2Cache(const char* path, DisaDiffReaderInfo* info, u8* cache, u32 cache_size);
|
||
|
u32 ReadDisaDiffIvfcLvl4(const char* path, DisaDiffReaderInfo* info, u32 offset, u32 size, void* buffer);
|