/** * Detect whether a buffer is a known Granny2 file by inspecting its * first 16 bytes. Tries LE first, then BE-with-swap. Returns the * endianness + pointer width baked into the file so the caller can wire * its u32 reader accordingly. * * @param {GR2Input} buffer — the candidate .gr2 bytes. * @returns {GR2DetectResult} */ export function detectGR2(buffer: GR2Input): GR2DetectResult; /** * Parse a GR2 buffer into `{ header, sections, data, sectionBytes(...) }`. * * Reads the 32-byte magic, the post-magic header (60 or 72 bytes depending * on `version`), and the section array. Does NOT decompress section * payloads — call `decompressSection(section, file.sectionBytes(section))` * from `./Granny.js` for that. * * @param {GR2Input} buffer — the .gr2 bytes. * @returns {GR2File} * @throws {Error} on non-Granny input. * @throws {RangeError} when the declared section array escapes the buffer. */ export function parseGR2File(buffer: GR2Input): GR2File; /** Acceptable input shapes for the parser. * @typedef {ArrayBuffer | Uint8Array | DataView | ArrayBufferView} GR2Input */ /** Quad of u32 magic words (4 × 4 bytes at the file start). * @typedef {readonly [number, number, number, number]} GR2Magic */ /** Compression tag, see {@link COMPRESSION_NAMES}. * @typedef {0 | 1 | 2 | 3 | 4} CompressionTag */ /** Granny section-slot index, see {@link SECTION_NAMES}. * @typedef {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7} SectionIndex */ /** * One entry in the GR2 section table (44 bytes on disk — see * `docs/gr2-format.md` § Section record). `compression_name` and * `semantic_name` are computed accessors ; the rest map 1-to-1 to the * on-disk u32s. * * @typedef {object} GR2Section * @property {number} index — 0-based position in the section table. * @property {number} compression — compression algorithm tag (0=none, 1=Oodle0, 2=Oodle1, 3=BitKnit, 4=BitKnit2). * @property {number} data_offset — offset of this section's compressed bytes, relative to the file start. * @property {number} data_size — length of this section's compressed bytes on disk. * @property {number} expanded_size — target length of the section once decompressed. * @property {number} internal_alignment — required alignment for this section's data buffer (4 / 8 / …). * @property {number} first_16bit — Oodle0 block-stop 1 : decoded-byte offset where the 16-bit length context ends. * @property {number} first_8bit — Oodle0 block-stop 2 : decoded-byte offset where the 8-bit length context ends. * @property {number} pointer_fixup_offset — pointer-fixup table offset (S5+). * @property {number} pointer_fixup_count — pointer-fixup entry count, 12 bytes each. * @property {number} mixed_marshalling_offset — mixed-marshalling table offset (S5+). * @property {number} mixed_marshalling_count — mixed-marshalling entry count, 12 bytes each. * @property {string} compression_name — computed : human name for {@link GR2Section.compression}. * @property {string} semantic_name — computed : Granny semantic name for {@link GR2Section.index}. */ /** * Top-level GR2 file header (~72 bytes for version ≥ 7, ~60 bytes otherwise). * * @typedef {object} GR2Header * @property {number} version — Granny file format version — ≥ 7 across our iRO ver12 corpus. * @property {number} total_size — total file size as declared by the writer. * @property {number} crc — CRC32 of the file's contents. * @property {number} section_array_offset — offset of the section array relative to the end of the magic. * @property {number} section_count — number of entries in the section array. * @property {readonly [number, number]} root_type — `[section_index, offset_within_section]`. * @property {readonly [number, number]} root_object — `[section_index, offset_within_section]`. * @property {number} type_tag — type-tag identifying the .gr2 schema generation. * @property {readonly number[]} extra_tags — 4 user / auxiliary tag values. * @property {number} string_db_crc — string-database CRC (version ≥ 7). * @property {readonly number[]} reserved — 3 reserved u32 (version ≥ 7). * @property {32 | 64} pointer_size — pointer width baked into the file's serialized references. * @property {boolean} byte_reversed — true if u32s are stored byte-reversed. */ /** * Parsed GR2 file, ready for section decompression. * * @typedef {object} GR2File * @property {GR2Header} header * @property {readonly GR2Section[]} sections * @property {Uint8Array} data — raw input bytes — kept for sliced reads via {@link GR2File.sectionBytes}. * @property {(section: GR2Section) => Uint8Array} sectionBytes — slice of `data` * carrying `section`'s on-disk compressed bytes. */ /** * Result of magic detection (precedes a full parse). * * @typedef {object} GR2DetectResult * @property {boolean} ok — true if the buffer's first 16 bytes match one of the known magics. * @property {boolean} byteReversed — true if u32s should be read big-endian. * @property {0 | 32 | 64} pointerSize — pointer width baked into the file (`0` when `ok === false`). */ /** `MAGIC_OLD` — earliest Granny 2.x ; LE u32s, 32-bit pointers. * @type {GR2Magic} */ export const MAGIC_OLD: GR2Magic; /** `MAGIC_32LE` — standard Granny 2.x, LE u32s, 32-bit pointers. **All iRO ver12 .gr2 use this**. * @type {GR2Magic} */ export const MAGIC_32LE: GR2Magic; /** `MAGIC_32BE` — `MAGIC_32LE`'s u32s each byte-reversed (big-endian on disk). * @type {GR2Magic} */ export const MAGIC_32BE: GR2Magic; /** `MAGIC_64LE` — 64-bit-pointer Granny 2.x, LE u32s. * @type {GR2Magic} */ export const MAGIC_64LE: GR2Magic; /** `MAGIC_64BE` — `MAGIC_64LE`'s u32s each byte-reversed. * @type {GR2Magic} */ export const MAGIC_64BE: GR2Magic; /** Number of bytes the magic quad occupies at the file start (16 used + 16 reserved). */ export const MAGIC_SIZE: 32; /** Bytes per entry in the section array (= 11 × u32). */ export const SECTION_RECORD_SIZE: 44; /** Number of `extra_tags` u32s in the header. */ export const EXTRA_TAG_COUNT: 4; /** Compression tag — section bytes are stored raw (no decompression). */ export const COMPRESSION_NONE: 0; /** Compression tag — RAD Oodle0 classic LZ + arithmetic codec. */ export const COMPRESSION_OODLE0: 1; /** Compression tag — RAD Oodle1 (not implemented ; no iRO ver12 asset uses it). */ export const COMPRESSION_OODLE1: 2; /** Compression tag — RAD BitKnit (not implemented). */ export const COMPRESSION_BITKNIT: 3; /** Compression tag — RAD BitKnit2 (not implemented). */ export const COMPRESSION_BITKNIT2: 4; /** Compression tag → human name. Used by `GR2Section.compression_name`. * @type {Readonly>} */ export const COMPRESSION_NAMES: Readonly>; /** Section-slot index → Granny semantic name. See `docs/gr2-format.md` § Section slots. * @type {Readonly>} */ export const SECTION_NAMES: Readonly>; /** * Acceptable input shapes for the parser. */ export type GR2Input = ArrayBuffer | Uint8Array | DataView | ArrayBufferView; /** * Quad of u32 magic words (4 × 4 bytes at the file start). */ export type GR2Magic = readonly [ number, number, number, number ]; /** * Compression tag, see {@link COMPRESSION_NAMES}. */ export type CompressionTag = 0 | 1 | 2 | 3 | 4; /** * Granny section-slot index, see {@link SECTION_NAMES}. */ export type SectionIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; /** * One entry in the GR2 section table (44 bytes on disk — see * `docs/gr2-format.md` § Section record). `compression_name` and * `semantic_name` are computed accessors ; the rest map 1-to-1 to the * on-disk u32s. */ export type GR2Section = { /** * — 0-based position in the section table. */ index: number; /** * — compression algorithm tag (0=none, 1=Oodle0, 2=Oodle1, 3=BitKnit, 4=BitKnit2). */ compression: number; /** * — offset of this section's compressed bytes, relative to the file start. */ data_offset: number; /** * — length of this section's compressed bytes on disk. */ data_size: number; /** * — target length of the section once decompressed. */ expanded_size: number; /** * — required alignment for this section's data buffer (4 / 8 / …). */ internal_alignment: number; /** * — Oodle0 block-stop 1 : decoded-byte offset where the 16-bit length context ends. */ first_16bit: number; /** * — Oodle0 block-stop 2 : decoded-byte offset where the 8-bit length context ends. */ first_8bit: number; /** * — pointer-fixup table offset (S5+). */ pointer_fixup_offset: number; /** * — pointer-fixup entry count, 12 bytes each. */ pointer_fixup_count: number; /** * — mixed-marshalling table offset (S5+). */ mixed_marshalling_offset: number; /** * — mixed-marshalling entry count, 12 bytes each. */ mixed_marshalling_count: number; /** * — computed : human name for {@link GR2Section.compression}. */ compression_name: string; /** * — computed : Granny semantic name for {@link GR2Section.index}. */ semantic_name: string; }; /** * Top-level GR2 file header (~72 bytes for version ≥ 7, ~60 bytes otherwise). */ export type GR2Header = { /** * — Granny file format version — ≥ 7 across our iRO ver12 corpus. */ version: number; /** * — total file size as declared by the writer. */ total_size: number; /** * — CRC32 of the file's contents. */ crc: number; /** * — offset of the section array relative to the end of the magic. */ section_array_offset: number; /** * — number of entries in the section array. */ section_count: number; /** * — `[section_index, offset_within_section]`. */ root_type: readonly [ number, number ]; /** * — `[section_index, offset_within_section]`. */ root_object: readonly [ number, number ]; /** * — type-tag identifying the .gr2 schema generation. */ type_tag: number; /** * — 4 user / auxiliary tag values. */ extra_tags: readonly number[]; /** * — string-database CRC (version ≥ 7). */ string_db_crc: number; /** * — 3 reserved u32 (version ≥ 7). */ reserved: readonly number[]; /** * — pointer width baked into the file's serialized references. */ pointer_size: 32 | 64; /** * — true if u32s are stored byte-reversed. */ byte_reversed: boolean; }; /** * Parsed GR2 file, ready for section decompression. */ export type GR2File = { header: GR2Header; sections: readonly GR2Section[]; /** * — raw input bytes — kept for sliced reads via {@link GR2File.sectionBytes}. */ data: Uint8Array; /** * — slice of `data` * carrying `section`'s on-disk compressed bytes. */ sectionBytes: (section: GR2Section) => Uint8Array; }; /** * Result of magic detection (precedes a full parse). */ export type GR2DetectResult = { /** * — true if the buffer's first 16 bytes match one of the known magics. */ ok: boolean; /** * — true if u32s should be read big-endian. */ byteReversed: boolean; /** * — pointer width baked into the file (`0` when `ok === false`). */ pointerSize: 0 | 32 | 64; }; export {};