UNPKG

igir

Version:

🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.

75 lines (74 loc) • 2.97 kB
import IgirException from "../../exceptions/igirException.js"; import IOFile from "../../models/files/ioFile.js"; import FsUtil from "../../utils/fsUtil.js"; import Patch from "./patch.js"; class DPSPatch extends Patch { static SUPPORTED_EXTENSIONS = [".dps"]; /** * Parse a .dps patch file and return a {@link DPSPatch}. */ static patchFrom(file) { const crcBefore = super.getCrcFromPath(file.getExtractedFilePath()); return new DPSPatch(file, crcBefore); } /** * Apply this patch to the input ROM file and write the patched result to the output path. */ async createPatchedFile(inputRomFile, outputRomPath, callback) { await this.getFile().extractToTempIOFile("r", async (patchFile) => { patchFile.skipNext(64); patchFile.skipNext(64); patchFile.skipNext(64); patchFile.skipNext(1); patchFile.skipNext(1); const originalSize = (await patchFile.readNext(4)).readUInt32LE(); if (inputRomFile.getSize() !== originalSize) { throw new IgirException( `DPS patch expected ROM size of ${FsUtil.sizeReadable(originalSize)}: ${this.getFile().toString()}` ); } await DPSPatch.writeOutputFile(inputRomFile, outputRomPath, patchFile, callback); }); } static async writeOutputFile(inputRomFile, outputRomPath, patchFile, callback) { await inputRomFile.extractToTempFile(async (tempRomFile) => { const sourceFile = await IOFile.fileFrom(tempRomFile, "r"); await FsUtil.copyFile(tempRomFile, outputRomPath); const targetFile = await IOFile.fileFrom(outputRomPath, "r+"); try { await this.applyPatch(patchFile, sourceFile, targetFile, callback); } finally { await targetFile.close(); await sourceFile.close(); } }); } static async applyPatch(patchFile, sourceFile, targetFile, callback) { while (patchFile.getPosition() < patchFile.getSize()) { const mode = (await patchFile.readNext(1)).readUInt8(); const outputOffset = (await patchFile.readNext(4)).readUInt32LE(); let data; if (mode === 0) { const inputOffset = (await patchFile.readNext(4)).readUInt32LE(); const inputLength = (await patchFile.readNext(4)).readUInt32LE(); data = await sourceFile.readAt(inputOffset, inputLength); } else if (mode === 1) { const dataLength = (await patchFile.readNext(4)).readUInt32LE(); data = await patchFile.readNext(dataLength); } else { throw new IgirException( `DPS patch mode type ${mode} isn't supported: ${patchFile.getPathLike().toString()}` ); } await targetFile.writeAt(data, outputOffset); if (callback !== void 0) { const progressPercentage = patchFile.getPosition() / patchFile.getSize(); callback(Math.floor(progressPercentage * targetFile.getSize())); } } } } export { DPSPatch as default }; //# sourceMappingURL=dpsPatch.js.map