mirror of
https://github.com/Elpisdev/unsegaREBORN.git
synced 2026-09-26 16:18:15 +03:00
136 lines
3.3 KiB
C
136 lines
3.3 KiB
C
#ifndef EXFAT_H
|
|
#define EXFAT_H
|
|
|
|
#include "lib.h"
|
|
#include "common.h"
|
|
#include "stream.h"
|
|
|
|
#define EXFAT_ENTRY_SIZE 32
|
|
|
|
#define EXFAT_ENTRY_EOD 0x00
|
|
#define EXFAT_ENTRY_FILE 0x85
|
|
#define EXFAT_ENTRY_STREAM 0xC0
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
typedef struct {
|
|
uint8_t jump_boot[3];
|
|
uint8_t fs_name[8];
|
|
uint8_t must_be_zero[53];
|
|
uint64_t partition_offset;
|
|
uint64_t volume_length;
|
|
uint32_t fat_offset;
|
|
uint32_t fat_length;
|
|
uint32_t cluster_heap_offset;
|
|
uint32_t cluster_count;
|
|
uint32_t first_cluster_of_root_dir;
|
|
uint32_t volume_serial_number;
|
|
uint16_t fs_revision;
|
|
uint16_t volume_flags;
|
|
uint8_t bytes_per_sector_shift;
|
|
uint8_t sectors_per_cluster_shift;
|
|
uint8_t number_of_fats;
|
|
uint8_t drive_select;
|
|
uint8_t percent_in_use;
|
|
uint8_t reserved[7];
|
|
uint8_t boot_code[390];
|
|
uint16_t boot_signature;
|
|
} ExfatBootSector;
|
|
|
|
typedef struct {
|
|
uint8_t entry_type;
|
|
uint8_t secondary_count;
|
|
uint16_t set_checksum;
|
|
uint16_t file_attributes;
|
|
uint16_t reserved1;
|
|
uint32_t create_timestamp;
|
|
uint32_t last_modified_timestamp;
|
|
uint32_t last_access_timestamp;
|
|
uint8_t create_10ms;
|
|
uint8_t last_modified_10ms;
|
|
uint8_t create_utc_offset;
|
|
uint8_t last_modified_utc_offset;
|
|
uint8_t last_access_utc_offset;
|
|
uint8_t reserved2[7];
|
|
} ExfatFileEntry;
|
|
|
|
typedef struct {
|
|
uint8_t entry_type;
|
|
uint8_t flags;
|
|
uint8_t reserved1;
|
|
uint8_t name_length;
|
|
uint16_t name_hash;
|
|
uint16_t reserved2;
|
|
uint64_t valid_data_length;
|
|
uint32_t reserved3;
|
|
uint32_t first_cluster;
|
|
uint64_t data_length;
|
|
} ExfatStreamEntry;
|
|
|
|
typedef struct {
|
|
uint8_t entry_type;
|
|
uint8_t flags;
|
|
uint16_t file_name[15];
|
|
} ExfatFileNameEntry;
|
|
|
|
#pragma pack(pop)
|
|
|
|
typedef struct {
|
|
char name[MAX_PATH_LENGTH];
|
|
uint32_t first_cluster;
|
|
uint64_t data_length;
|
|
bool is_directory;
|
|
bool no_fat_chain;
|
|
uint32_t modify_timestamp;
|
|
uint32_t access_timestamp;
|
|
uint8_t modify_10ms;
|
|
int8_t modify_utc_offset;
|
|
int8_t access_utc_offset;
|
|
} ExfatFileInfo;
|
|
|
|
typedef struct {
|
|
char path[MAX_PATH_LENGTH];
|
|
uint64_t mtime;
|
|
uint64_t atime;
|
|
} DeferredDirTime;
|
|
|
|
static inline bool grow_deferred_dirs(DeferredDirTime** dirs, uint32_t* capacity) {
|
|
uint32_t new_cap = *capacity ? *capacity * 2 : 256;
|
|
DeferredDirTime* new_buf = realloc(*dirs, new_cap * sizeof(DeferredDirTime));
|
|
if (!new_buf) return false;
|
|
*dirs = new_buf;
|
|
*capacity = new_cap;
|
|
return true;
|
|
}
|
|
|
|
typedef struct {
|
|
FILE* fp;
|
|
ExfatBootSector boot_sector;
|
|
uint32_t bytes_per_sector;
|
|
uint32_t bytes_per_cluster;
|
|
uint32_t cluster_heap_offset_bytes;
|
|
uint32_t fat_offset_bytes;
|
|
uint32_t fat_length_bytes;
|
|
uint32_t* fat;
|
|
uint8_t* cluster_buf;
|
|
uint8_t* io_buf;
|
|
uint64_t extracted_bytes;
|
|
uint64_t files_extracted;
|
|
uint64_t raw_file_pos;
|
|
bool silent;
|
|
bool verbose;
|
|
DecryptStream* stream;
|
|
char last_dir[MAX_PATH_LENGTH];
|
|
DirHandle cached_dir;
|
|
DeferredDirTime* deferred_dirs;
|
|
uint32_t deferred_count;
|
|
uint32_t deferred_capacity;
|
|
} ExfatContext;
|
|
|
|
bool exfat_init(ExfatContext* ctx, const char* filename);
|
|
bool exfat_init_stream(ExfatContext* ctx, DecryptStream* stream);
|
|
bool exfat_extract_all(ExfatContext* ctx, const char* output_dir);
|
|
void exfat_close(ExfatContext* ctx);
|
|
|
|
#endif
|