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
JavaScript
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