1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-20 11:47:46 +00:00

Add a fiin parser

Don't know what this file format is actually used for, but it was fun
to reverse engineer, and I don't think anyone has done it for this
format yet!
This commit is contained in:
Joshua Goins 2022-03-09 09:25:01 -05:00
parent 0b3f438819
commit 1c71d69a84
3 changed files with 90 additions and 1 deletions

View file

@ -32,7 +32,9 @@ set(SRC
src/launcherwindow.cpp
include/launcherwindow.h
src/gamescopesettingswindow.cpp
include/gamescopesettingswindow.h)
include/gamescopesettingswindow.h
src/fiinparser.cpp
include/fiinparser.h)
include(FetchContent)

40
include/fiinparser.h Normal file
View file

@ -0,0 +1,40 @@
#pragma once
#include <cstdint>
#include <vector>
#include <string_view>
// this is methods dedicated to parsing "fiin" files, commonly shown as "fileinfo.fiin"
// header is 1024 bytes
// for some reason, they store unknown1 and unknown 2 in this weird format,
// unknown1 is capped at 256 (in decimal) and will overflow into unknown 2
// for example, 1 is equal to unknown1 = 96 and unknown2 = 0
// 96 / 1 == 1
// if you have say, 14 entries, then unknown1 = 64 and unknown2 = 5
// 5 (unknown2) * 256 = 1280 + 64 (unknown1) = 1344
// 1344 / 96 = 14
// i could've made a mistake and this is actually really common but i don't know
struct FileInfoHeader {
char magic[9];
uint8_t dummy1[16];
uint8_t unknown; // version? always seems to be 4
uint8_t dummy2[2];
uint8_t unknown1;
uint8_t unknown2;
uint8_t dummy[994];
};
// each entry is 96 bytes
struct FileInfoEntry {
uint8_t dummy[8]; // length of file name in some format
char str[64]; // simple \0 encoded string
uint8_t dummy2[24]; // sha1
};
struct FileInfo {
FileInfoHeader header;
std::vector<FileInfoEntry> entries;
};
FileInfo readFileInfo(const std::string_view path);

47
src/fiinparser.cpp Normal file
View file

@ -0,0 +1,47 @@
#include "fiinparser.h"
#include <cstdio>
#include <QDebug>
FileInfo readFileInfo(const std::string_view path) {
FILE* file = fopen(path.data(), "rb");
if(!file) {
qInfo() << "Failed to read file info " << path.data();
return {};
}
FileInfo info;
fread(&info.header, sizeof info.header, 1, file);
char magic[9] = "FileInfo";
if(strcmp(info.header.magic, magic) != 0)
qInfo() << "Invalid magic for fileinfo.";
else
qInfo() << "Got matching magic:" << info.header.magic;
qInfo() << "unknown (version?) = " << info.header.unknown;
qInfo() << "unknown1 = " << info.header.unknown1;
qInfo() << "unknown2 = " << info.header.unknown2;
int overflow = info.header.unknown2;
int extra = overflow * 256;
int first = info.header.unknown1 / 96;
int first2 = extra / 96;
int actualEntries = first + first2 + 1; // is this 1 really needed? lol
qInfo() << "Guessed number of entries: " << actualEntries;
int numEntries = actualEntries;
for(int i = 0; i < numEntries; i++) {
FileInfoEntry entry;
fread(&entry, sizeof entry, 1, file);
info.entries.push_back(entry);
qDebug() << entry.str;
}
fclose(file);
return info;
}