@chicowall/grf-loader
Version:
A loader for GRF files (Ragnarok Online game file)
1 lines • 25.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/grf-base.ts","../src/des.ts","../src/grf-browser.ts","../src/grf-node.ts"],"sourcesContent":["export {GrfBrowser} from './grf-browser';\nexport {GrfNode} from './grf-node';\nexport type {TFileEntry} from './grf-base';\n","import {inflate} from 'pako';\nimport jDataview from 'jdataview';\nimport {decodeFull, decodeHeader} from './des';\n\nexport interface TFileEntry {\n type: number;\n offset: number;\n realSize: number;\n compressedSize: number;\n lengthAligned: number;\n}\n\nconst FILELIST_TYPE_FILE = 0x01;\nconst FILELIST_TYPE_ENCRYPT_MIXED = 0x02; // encryption mode 0 (header DES + periodic DES/shuffle)\nconst FILELIST_TYPE_ENCRYPT_HEADER = 0x04; // encryption mode 1 (header DES only)\n\nconst HEADER_SIGNATURE = 'Master of Magic';\nconst HEADER_SIZE = 46;\nconst FILE_TABLE_SIZE = Uint32Array.BYTES_PER_ELEMENT * 2;\n\nexport abstract class GrfBase<T> {\n public version = 0x200;\n public fileCount = 0;\n public loaded = false;\n public files = new Map<string, TFileEntry>();\n private fileTableOffset = 0;\n\n constructor(private fd: T) {}\n\n abstract getStreamBuffer(\n fd: T,\n offset: number,\n length: number\n ): Promise<Uint8Array>;\n\n public async getStreamReader(\n offset: number,\n length: number\n ): Promise<jDataview> {\n const buffer = await this.getStreamBuffer(this.fd, offset, length);\n\n return new jDataview(buffer, void 0, void 0, true);\n }\n\n public async load(): Promise<void> {\n if (!this.loaded) {\n await this.parseHeader();\n await this.parseFileList();\n this.loaded = true;\n }\n }\n\n private async parseHeader(): Promise<void> {\n const reader = await this.getStreamReader(0, HEADER_SIZE);\n\n const signature = reader.getString(15);\n if (signature !== HEADER_SIGNATURE) {\n throw new Error('Not a GRF file (invalid signature)');\n }\n\n reader.skip(15);\n this.fileTableOffset = reader.getUint32() + HEADER_SIZE;\n const reservedFiles = reader.getUint32();\n this.fileCount = reader.getUint32() - reservedFiles - 7;\n this.version = reader.getUint32();\n\n if (this.version !== 0x200) {\n throw new Error(`Unsupported version \"0x${this.version.toString(16)}\"`);\n }\n }\n\n private async parseFileList(): Promise<void> {\n // Read table list, stored information\n const reader = await this.getStreamReader(\n this.fileTableOffset,\n FILE_TABLE_SIZE\n );\n const compressedSize = reader.getUint32();\n const realSize = reader.getUint32();\n\n // Load the chunk and uncompress it\n const compressed = await this.getStreamBuffer(\n this.fd,\n this.fileTableOffset + FILE_TABLE_SIZE,\n compressedSize\n );\n\n const data = inflate(compressed, {\n //chunkSize: realSize\n });\n\n // Optimized version without using jDataView (faster)\n for (let i = 0, p = 0; i < this.fileCount; ++i) {\n let filename = '';\n while (data[p]) {\n filename += String.fromCharCode(data[p++]);\n }\n\n p++;\n\n // prettier-ignore\n const entry: TFileEntry = {\n compressedSize: data[p++] | (data[p++] << 8) | (data[p++] << 16) | (data[p++] << 24),\n lengthAligned: data[p++] | (data[p++] << 8) | (data[p++] << 16) | (data[p++] << 24),\n realSize: data[p++] | (data[p++] << 8) | (data[p++] << 16) | (data[p++] << 24),\n type: data[p++],\n offset: (data[p++] | (data[p++] << 8) | (data[p++] << 16) | (data[p++] << 24)) >>> 0\n };\n\n // Not a file (folder ?)\n if (entry.type & FILELIST_TYPE_FILE) {\n this.files.set(filename, entry);\n }\n }\n }\n\n private decodeEntry(data: Uint8Array, entry: TFileEntry): Uint8Array {\n // Decode the file\n if (entry.type & FILELIST_TYPE_ENCRYPT_MIXED) {\n decodeFull(data, entry.lengthAligned, entry.compressedSize);\n } else if (entry.type & FILELIST_TYPE_ENCRYPT_HEADER) {\n decodeHeader(data, entry.lengthAligned);\n }\n\n // No compression\n if (entry.realSize === entry.compressedSize) {\n return data;\n }\n\n // Uncompress\n return inflate(data, {\n //chunkSize: entry.realSize\n });\n }\n\n public async getFile(\n filename: string\n ): Promise<{data: null | Uint8Array; error: null | string}> {\n if (!this.loaded) {\n return Promise.resolve({data: null, error: 'GRF not loaded yet'});\n }\n\n const path = filename;\n\n // Not exists\n if (!this.files.has(path)) {\n return Promise.resolve({data: null, error: `File \"${path}\" not found`});\n }\n\n const entry = this.files.get(path);\n\n if (!entry) {\n return { data: null, error: `File \"${path}\" not found` };\n }\n\n const data = await this.getStreamBuffer(\n this.fd,\n entry.offset + HEADER_SIZE,\n entry.lengthAligned\n );\n\n try {\n const result = this.decodeEntry(data, entry);\n return Promise.resolve({data: result, error: null});\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n return { data: null, error: message };\n }\n }\n}\n","/**\n * Ragnarok Online DES decoder implementation\n * It's a custom one with some alterations\n */\nexport {decodeFull, decodeHeader};\n\nconst mask = new Uint8Array([0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]);\nconst tmp = new Uint8Array(8);\nconst tmp2 = new Uint8Array(8);\nconst clean = new Uint8Array(8);\n\n// prettier-ignore\nconst initialPermutationTable = new Uint8Array([\n 58, 50, 42, 34, 26, 18, 10, 2,\n 60, 52, 44, 36, 28, 20, 12, 4,\n 62, 54, 46, 38, 30, 22, 14, 6,\n 64, 56, 48, 40, 32, 24, 16, 8,\n 57, 49, 41, 33, 25, 17, 9, 1,\n 59, 51, 43, 35, 27, 19, 11, 3,\n 61, 53, 45, 37, 29, 21, 13, 5,\n 63, 55, 47, 39, 31, 23, 15, 7\n]);\n\n// prettier-ignore\nconst finalPermutationTable = new Uint8Array([\n 40, 8, 48, 16, 56, 24, 64, 32,\n 39, 7, 47, 15, 55, 23, 63, 31,\n 38, 6, 46, 14, 54, 22, 62, 30,\n 37, 5, 45, 13, 53, 21, 61, 29,\n 36, 4, 44, 12, 52, 20, 60, 28,\n 35, 3, 43, 11, 51, 19, 59, 27,\n 34, 2, 42, 10, 50, 18, 58, 26,\n 33, 1, 41, 9, 49, 17, 57, 25\n]);\n\n// prettier-ignore\nconst transpositionTable = new Uint8Array([\n 16, 7, 20, 21,\n 29, 12, 28, 17,\n 1, 15, 23, 26,\n 5, 18, 31, 10,\n 2, 8, 24, 14,\n 32, 27, 3, 9,\n 19, 13, 30, 6,\n 22, 11, 4, 25\n]);\n\n// prettier-ignore\nconst substitutionBoxTable = [\n new Uint8Array([\n 0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47, 0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,\n 0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba, 0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,\n 0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21, 0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,\n 0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec, 0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9 \n ]),\n new Uint8Array([\n 0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95, 0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,\n 0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec, 0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,\n 0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06, 0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,\n 0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b, 0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce\n ]),\n new Uint8Array([\n 0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2, 0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,\n 0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae, 0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,\n 0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c, 0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,\n 0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97, 0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d\n ]),\n new Uint8Array([\n 0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78, 0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,\n 0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb, 0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,\n 0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87, 0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,\n 0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0, 0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb\n ])\n];\n\n/**\n * Initial permutation (IP).\n */\nfunction initialPermutation(src: Uint8Array, index: number): void {\n for (let i = 0; i < 64; ++i) {\n const j = initialPermutationTable[i] - 1;\n if (src[index + ((j >> 3) & 7)] & mask[j & 7]) {\n tmp[(i >> 3) & 7] |= mask[i & 7];\n }\n }\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * Final permutation (IP^-1).\n */\nfunction finalPermutation(src: Uint8Array, index: number): void {\n for (let i = 0; i < 64; ++i) {\n const j = finalPermutationTable[i] - 1;\n if (src[index + ((j >> 3) & 7)] & mask[j & 7]) {\n tmp[(i >> 3) & 7] |= mask[i & 7];\n }\n }\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * Transposition (P-BOX).\n */\nfunction transposition(src: Uint8Array, index: number): void {\n for (let i = 0; i < 32; ++i) {\n const j = transpositionTable[i] - 1;\n if (src[index + (j >> 3)] & mask[j & 7]) {\n tmp[(i >> 3) + 4] |= mask[i & 7];\n }\n }\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * Expansion (E).\n * Expands upper four 8-bits (32b) into eight 6-bits (48b).\n */\nfunction expansion(src: Uint8Array, index: number): void {\n tmp[0] = ((src[index + 7] << 5) | (src[index + 4] >> 3)) & 0x3f; // ..0 vutsr\n tmp[1] = ((src[index + 4] << 1) | (src[index + 5] >> 7)) & 0x3f; // ..srqpo n\n tmp[2] = ((src[index + 4] << 5) | (src[index + 5] >> 3)) & 0x3f; // ..o nmlkj\n tmp[3] = ((src[index + 5] << 1) | (src[index + 6] >> 7)) & 0x3f; // ..kjihg f\n tmp[4] = ((src[index + 5] << 5) | (src[index + 6] >> 3)) & 0x3f; // ..g fedcb\n tmp[5] = ((src[index + 6] << 1) | (src[index + 7] >> 7)) & 0x3f; // ..cba98 7\n tmp[6] = ((src[index + 6] << 5) | (src[index + 7] >> 3)) & 0x3f; // ..8 76543\n tmp[7] = ((src[index + 7] << 1) | (src[index + 4] >> 7)) & 0x3f; // ..43210 v\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * Substitution boxes (S-boxes).\n * NOTE: This implementation was optimized to process two nibbles in one step (twice as fast).\n */\nfunction substitutionBox(src: Uint8Array, index: number): void {\n for (let i = 0; i < 4; ++i) {\n tmp[i] =\n (substitutionBoxTable[i][src[i * 2 + 0 + index]] & 0xf0) |\n (substitutionBoxTable[i][src[i * 2 + 1 + index]] & 0x0f);\n }\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * DES round function.\n * XORs src[0..3] with TP(SBOX(E(src[4..7]))).\n */\nfunction roundFunction(src: Uint8Array, index: number): void {\n for (let i = 0; i < 8; i++) {\n tmp2[i] = src[index + i];\n }\n\n expansion(tmp2, 0);\n substitutionBox(tmp2, 0);\n transposition(tmp2, 0);\n\n src[index + 0] ^= tmp2[4];\n src[index + 1] ^= tmp2[5];\n src[index + 2] ^= tmp2[6];\n src[index + 3] ^= tmp2[7];\n}\n\n/**\n * DEcrypt a block\n */\nfunction decryptBlock(src: Uint8Array, index: number): void {\n initialPermutation(src, index);\n roundFunction(src, index);\n finalPermutation(src, index);\n}\n\n/**\n * Decode the whole file\n */\nfunction decodeFull(\n src: Uint8Array,\n length: number,\n entryLength: number\n): void {\n // compute number of digits of the entry length\n const digits = entryLength.toString().length;\n\n // choose size of gap between two encrypted blocks\n // digits: 0 1 2 3 4 5 6 7 8 9 ...\n // cycle: 1 1 1 4 5 14 15 22 23 24 ...\n const cycle =\n digits < 3\n ? 1\n : digits < 5\n ? digits + 1\n : digits < 7\n ? digits + 9\n : digits + 15;\n\n const nblocks = length >> 3;\n\n // first 20 blocks are all des-encrypted\n for (let i = 0; i < 20 && i < nblocks; ++i) {\n decryptBlock(src, i * 8);\n }\n\n for (let i = 20, j = -1; i < nblocks; ++i) {\n // decrypt block\n if (i % cycle === 0) {\n decryptBlock(src, i * 8);\n continue;\n }\n\n // de-shuffle block\n if (++j && j % 7 === 0) {\n shuffleDec(src, i * 8);\n }\n }\n}\n\n/**\n * Decode only the header\n */\nfunction decodeHeader(src: Uint8Array, length: number): void {\n const count = length >> 3;\n\n // first 20 blocks are all des-encrypted\n for (let i = 0; i < 20 && i < count; ++i) {\n decryptBlock(src, i * 8);\n }\n\n // the rest is plaintext, done.\n}\n\n/**\n * Shuffle decode\n */\nfunction shuffleDec(src: Uint8Array, index: number) {\n tmp[0] = src[index + 3];\n tmp[1] = src[index + 4];\n tmp[2] = src[index + 6];\n tmp[3] = src[index + 0];\n tmp[4] = src[index + 1];\n tmp[5] = src[index + 2];\n tmp[6] = src[index + 5];\n tmp[7] = shuffleDecTable[src[index + 7]];\n\n src.set(tmp, index);\n tmp.set(clean);\n}\n\n/**\n * GRF substitution table\n */\nconst shuffleDecTable = (() => {\n // prettier-ignore\n const list = new Uint8Array([\n 0x00, 0x2b, 0x6c, 0x80, 0x01, 0x68, 0x48,\n 0x77, 0x60, 0xff, 0xb9, 0xc0, 0xfe, 0xeb\n ]);\n\n const out = new Uint8Array(Array.from({length: 256}, (_, k) => k));\n const count = list.length;\n\n for (let i = 0; i < count; i += 2) {\n out[list[i + 0]] = list[i + 1];\n out[list[i + 1]] = list[i + 0];\n }\n\n return out;\n})();\n","import jDataview from 'jdataview';\nimport {GrfBase} from './grf-base';\n\n/**\n * Using this Browser, we work from a File or Blob object.\n * We are use the FileReader API to read only some part of the file to avoid\n * loading 2 gigas into memory\n */\nexport class GrfBrowser extends GrfBase<File | Blob> {\n public async getStreamBuffer(\n buffer: File | Blob,\n offset: number,\n length: number\n ): Promise<Uint8Array> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = reject;\n reader.onload = () =>\n resolve(new Uint8Array(reader.result as ArrayBuffer));\n reader.readAsArrayBuffer(buffer.slice(offset, offset + length));\n });\n }\n}\n","// src/grf-node.ts\nimport { readSync, fstatSync } from 'fs';\nimport { GrfBase } from './grf-base';\n\nexport class GrfNode extends GrfBase<number> {\n constructor(fd: number) {\n super(fd);\n\n // Na nossa API, apenas FDs para arquivos regulares são válidos.\n // fstatSync lança erro se o descritor não existir ou não for arquivo.\n try {\n const stat = fstatSync(fd);\n if (!stat.isFile()) {\n throw new Error('GRFNode: file descriptor must point to a regular file');\n }\n } catch {\n // Converte em mensagem clara para o usuário\n throw new Error('GRFNode: invalid file descriptor');\n }\n }\n\n public async getStreamBuffer(\n fd: number,\n offset: number,\n length: number\n ): Promise<Uint8Array> {\n const buffer = Buffer.allocUnsafe(length);\n const bytesRead = readSync(fd, buffer, 0, length, offset);\n\n if (bytesRead !== length) {\n // ERRO TYPE: GRFNode: unexpected EOF\n throw new Error('Not a GRF file (invalid signature)');\n }\n return buffer;\n }\n}\n"],"mappings":"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","names":["index_exports","__export","GrfBrowser","GrfNode","__toCommonJS","import_pako","import_jdataview","mask","tmp","tmp2","clean","initialPermutationTable","finalPermutationTable","transpositionTable","substitutionBoxTable","initialPermutation","src","index","i","j","finalPermutation","transposition","expansion","substitutionBox","roundFunction","decryptBlock","decodeFull","length","entryLength","digits","cycle","nblocks","shuffleDec","decodeHeader","count","shuffleDecTable","list","out","_","k","FILELIST_TYPE_FILE","FILELIST_TYPE_ENCRYPT_MIXED","FILELIST_TYPE_ENCRYPT_HEADER","HEADER_SIGNATURE","HEADER_SIZE","FILE_TABLE_SIZE","GrfBase","fd","offset","length","buffer","jDataview","reader","reservedFiles","compressedSize","realSize","compressed","data","i","p","filename","entry","decodeFull","decodeHeader","path","result","error","GrfBrowser","GrfBase","buffer","offset","length","resolve","reject","reader","import_fs","GrfNode","GrfBase","fd","offset","length","buffer"]}