Cleanup, add ImHex patterns
tool binaries now no longer have any linter warnings add imhex patterns (for documentation's sake I guess)
This commit is contained in:
parent
dc6be07ec9
commit
e700c3432d
|
@ -0,0 +1,131 @@
|
|||
#include <std/io.pat>
|
||||
|
||||
|
||||
// TECH types
|
||||
|
||||
// LZSS compression header thingy.
|
||||
struct Lzss_Header {
|
||||
u32 next; // this is formally Lzss_Header*
|
||||
// but hexpat does handle pointers
|
||||
// and I kinda don't want it to.
|
||||
|
||||
u8 cByteId;
|
||||
u8 cHdrSize;
|
||||
u8 nMaxMatch;
|
||||
u8 nFillByte;
|
||||
u16 nRingSize;
|
||||
u16 nErrorId;
|
||||
u32 nUnCompressedBytes;
|
||||
u32 nCompressedBytes;
|
||||
u32 nCRC;
|
||||
u32 nFileId;
|
||||
u32 nCompressedDataCRC;
|
||||
|
||||
// if valid, print out (useful) information
|
||||
//if(cByteId == 0x91 && cHdrSize == 0x20) {
|
||||
//std::print("<lzss>");
|
||||
//std::print(" header_size: {}, max_match: {}, fill_byte: {} ring_size: {}", cHdrSize, nMaxMatch, nFillByte, nRingSize);
|
||||
//std::print(" uncompressed_size: {}, compressed_size: {}, crc: {}, file_id: {}, compressed_crc: {}", nUnCompressedBytes, nCompressedBytes, nCRC, nFileId, nCompressedDataCRC);
|
||||
//std::print("</lzss>");
|
||||
//}
|
||||
};
|
||||
|
||||
// Data strutures actually part of the file:
|
||||
|
||||
// "PGRP" entry.
|
||||
//
|
||||
// This marks the start of a "package group".
|
||||
// Whatever that is.
|
||||
struct JMMT_PGRP {
|
||||
u32 magic;
|
||||
u32 groupNameCrc; // This is in the string table
|
||||
u32 nrfiles;
|
||||
u32 pad; // seemingly always 0xCDCDCDCD
|
||||
};
|
||||
|
||||
// "PFIL" entry.
|
||||
//
|
||||
// This represents a file block,
|
||||
// which can itself represent either a whole file (> 65535 bytes),
|
||||
// or part of a file (which will need to be stiched together).
|
||||
struct JMMT_PFIL {
|
||||
u32 magic;
|
||||
|
||||
u32 unk[2]; // Don't know what these are?
|
||||
|
||||
// Sequence number of the chunk.
|
||||
// This repressents the order of each chunk,
|
||||
// presumably so order can just be whatever.
|
||||
//
|
||||
// However the game seems to order chunks for files
|
||||
// in order, and doesn't start/interleave other files
|
||||
// in between. So this is a nice waste of 16 bits.
|
||||
u16 chunkSequenceNumber;
|
||||
|
||||
// Amount of chunks which need to be read
|
||||
// from to read this file completely.
|
||||
//
|
||||
// 1 means this file starts and ends on this chunk.
|
||||
u16 chunkAmount;
|
||||
|
||||
// This is a CRC32 hash of the path of this file.
|
||||
//
|
||||
// Hashed with jmmt::HashString() (in the jmmt_tools repo).
|
||||
u32 filenameCrc;
|
||||
|
||||
u32 unk2[7]; // more unknown stuff I don't care/know about
|
||||
|
||||
// Uncompressed size of this file chunk. Has a maximum of 65535 bytes.
|
||||
u32 chunkSize;
|
||||
|
||||
// Offset where this file chunk should start,
|
||||
// inside of a larger buffer.
|
||||
u32 blockOffset;
|
||||
|
||||
// ?
|
||||
u32 unk3;
|
||||
|
||||
// Offset inside of the package file where
|
||||
// the compressed data blob starts.
|
||||
u32 dataOffset;
|
||||
|
||||
u32 fileSize;
|
||||
|
||||
// TECH LZSS header.
|
||||
// Used to (shocker) configure LZSS decompression.
|
||||
Lzss_Header lzssHeader;
|
||||
|
||||
// Debug information. This doesn't print literally everything,
|
||||
// just the useful stuff to look at it.
|
||||
if(1) {
|
||||
std::print(" Chunk seqNum: {}, Filename CRC: {:0x}, File Size: {}, Chunk Size: {}, Block Offset: {}, Data Offset: {}", chunkSequenceNumber, filenameCrc, fileSize, chunkSize, blockOffset, dataOffset);
|
||||
}
|
||||
|
||||
//if(lzHeader.cByteId == 0x91)
|
||||
// std::print("file has a valid lzss header");
|
||||
|
||||
};
|
||||
|
||||
// This is a wrapper so we can easily do the chunk viewing in imhex.
|
||||
// While there's probably a way I could do this easier this works.
|
||||
// So it's what I'm gonna use.
|
||||
struct PFIL_WRAPPER {
|
||||
JMMT_PFIL pfilChunkZero;
|
||||
|
||||
if(pfilChunkZero.chunkAmount != 1) {
|
||||
std::print("This file has {} chunks", pfilChunkZero.chunkAmount);
|
||||
JMMT_PFIL pfilChunkExtra[pfilChunkZero.chunkAmount - 1];
|
||||
} else {
|
||||
std::print("File ended with 1 chunk");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Group header is hardcoded for config.pak cause that's what I'm using to test
|
||||
|
||||
// Group header.
|
||||
JMMT_PGRP grp @ 0xd1c30;
|
||||
|
||||
// This isn't right (as one PFIL chunk doesn't actually have to mean one file),
|
||||
// but it works for testing and trying to understand the format.
|
||||
PFIL_WRAPPER files[grp.nrfiles] @ $;
|
|
@ -0,0 +1,35 @@
|
|||
// ImHex pattern for .ps2_palette or palette_*.b files
|
||||
|
||||
struct Pal1Header {
|
||||
u8 magic[4];
|
||||
|
||||
u32 unk;
|
||||
u16 unk2;
|
||||
|
||||
// This is probably implied
|
||||
// by bpp of the image, I guess
|
||||
u16 NrColors;
|
||||
|
||||
u16 PaletteBpp;
|
||||
|
||||
u16 unk3;
|
||||
|
||||
u32 HeaderSize;
|
||||
|
||||
// Don't know what this data is
|
||||
u8 unk4[0x1c];
|
||||
};
|
||||
|
||||
struct Pal1File {
|
||||
Pal1Header Header;
|
||||
|
||||
if(Header.PaletteBpp == 32) {
|
||||
u32 Colors[Header.NrColors];
|
||||
} else if(Header.PaletteBpp == 16) {
|
||||
u16 Colors[Header.Nrcolors];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Pal1File Pal1 @ 0x0;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// ImHex pattern for .ps2_texture or texture_*.b files
|
||||
|
||||
struct Tex1Header {
|
||||
u8 magic[4];
|
||||
|
||||
// I don't know what these are?
|
||||
u32 unk;
|
||||
u16 unk2;
|
||||
|
||||
u16 width;
|
||||
u16 height;
|
||||
|
||||
// bpp of the texture.
|
||||
// > 8 = no palette file
|
||||
u16 bpp;
|
||||
|
||||
u8 unknown[0x40];
|
||||
};
|
||||
|
||||
Tex1Header tex1 @ $;
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef JMMT_TOOLS_FOURCCOBJECT_H
|
||||
#define JMMT_TOOLS_FOURCCOBJECT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace jmmt {
|
||||
|
||||
|
||||
template <class TMagic, TMagic ValidMagic>
|
||||
struct BasicStructureWithMagic {
|
||||
constexpr static TMagic TypeMagic = ValidMagic;
|
||||
};
|
||||
|
||||
template <uint32_t ValidMagic>
|
||||
using FourCCMagic = BasicStructureWithMagic<uint32_t, ValidMagic>;
|
||||
|
||||
}
|
||||
|
||||
#endif // JMMT_TOOLS_FOURCCOBJECT_H
|
|
@ -8,15 +8,10 @@
|
|||
// for LzssHeader
|
||||
#include <jmmt/lzss.h>
|
||||
|
||||
#include "FourCCObject.h"
|
||||
|
||||
namespace jmmt {
|
||||
|
||||
template <class TMagic, TMagic ValidMagic>
|
||||
struct BasicStructureWithMagic {
|
||||
constexpr static TMagic TypeMagic = ValidMagic;
|
||||
};
|
||||
|
||||
template <uint32_t ValidMagic>
|
||||
using FourCCMagic = BasicStructureWithMagic<uint32_t, ValidMagic>;
|
||||
|
||||
// This is the "file header" of sorts.
|
||||
struct PackageEofHeader {
|
||||
|
|
|
@ -27,13 +27,13 @@ T LameRead(std::istream& is) {
|
|||
|
||||
std::string ReadString(std::istream& is) {
|
||||
std::string s;
|
||||
char c {};
|
||||
char c;
|
||||
|
||||
if(!is)
|
||||
return "";
|
||||
|
||||
while(true) {
|
||||
c = is.get();
|
||||
c = static_cast<char>(is.get());
|
||||
|
||||
if(c == '\0')
|
||||
return s;
|
||||
|
@ -60,7 +60,7 @@ struct PackageReader {
|
|||
}
|
||||
|
||||
void Init() {
|
||||
is.seekg(-sizeof(jmmt::PackageEofHeader), std::istream::end);
|
||||
is.seekg(-static_cast<ssize_t>(sizeof(jmmt::PackageEofHeader)), std::istream::end);
|
||||
eofHeader = LameRead<jmmt::PackageEofHeader>(is);
|
||||
|
||||
// We ideally should be at the end of file after reading the eof header.
|
||||
|
@ -79,12 +79,12 @@ struct PackageReader {
|
|||
is.seekg(static_cast<std::streamsize>(eofHeader.headerStartOffset) + static_cast<std::streamsize>(eofHeader.headerSize), std::istream::beg);
|
||||
auto l = is.tellg();
|
||||
|
||||
// seek ahead of the "header" of the debug info/string table,
|
||||
// since we don't care about it (we read strings until we "stop". though
|
||||
// it might be smart to trust it? idk.)
|
||||
// seek ahead of the "header" of the debug string table,
|
||||
// since we don't care about it (we read strings until we hit true EOF.
|
||||
// though it might be smart to trust it? IDK.)
|
||||
is.seekg(sizeof(uint32_t), std::istream::cur);
|
||||
|
||||
while(l != fileSize - static_cast<std::streamsize>(sizeof(eofHeader))) {
|
||||
while(l != fileSize - static_cast<ssize_t>(sizeof(eofHeader))) {
|
||||
auto string = ReadString(is);
|
||||
crcToFilename[jmmt::HashString(string.c_str())] = string;
|
||||
l = is.tellg();
|
||||
|
@ -95,7 +95,7 @@ struct PackageReader {
|
|||
|
||||
// Go to the start of the first file chunk, skipping the group that we just read,
|
||||
// after we have finished creating our CRC->filename map.
|
||||
is.seekg(static_cast<std::streamsize>(eofHeader.headerStartOffset) + sizeof(jmmt::PackageGroup), std::istream::beg);
|
||||
is.seekg(static_cast<ssize_t>(eofHeader.headerStartOffset) + static_cast<ssize_t>(sizeof(jmmt::PackageGroup)), std::istream::beg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +141,7 @@ struct PackageReader {
|
|||
if(currChunk.compressedChunkSize == currChunk.chunkSize) {
|
||||
memcpy(fileWorkBuffer.data() + currChunk.blockOffset, compressedBuffer.data(), currChunk.chunkSize);
|
||||
} else {
|
||||
jmmt::DecompressLzss(nullptr, compressedBuffer.data(), currChunk.compressedChunkSize, fileWorkBuffer.data() + currChunk.blockOffset);
|
||||
jmmt::DecompressLzss(nullptr, compressedBuffer.data(), static_cast<std::int32_t>(currChunk.compressedChunkSize), fileWorkBuffer.data() + currChunk.blockOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ struct PackageReader {
|
|||
ReadFile(cb);
|
||||
}
|
||||
|
||||
jmmt::PackageGroup& GetGroup() {
|
||||
[[maybe_unused]] jmmt::PackageGroup& GetGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
@ -30,7 +29,7 @@ namespace fs = std::filesystem;
|
|||
// We could brute-force these, but since the game has them in executable,
|
||||
// it's a whole lot faster to just try every game filename and see
|
||||
// what sticks (& rename it if it does).
|
||||
constinit static std::array<std::string_view, 20> OriginalFilenames = {
|
||||
constexpr static std::array<std::string_view, 20> OriginalFilenames = {
|
||||
// First loaded by the game
|
||||
"package.toc",
|
||||
|
||||
|
|
Loading…
Reference in New Issue