/* VCDIFF module for RomPatcher.js v20181021 - Marc Robledo 2018 - http://www.marcrobledo.com/license */ /* File format specification: https://tools.ietf.org/html/rfc3284 */ /* Mostly based in: https://github.com/vic-alexiev/TelerikAcademy/tree/master/C%23%20Fundamentals%20II/Homework%20Assignments/3.%20Methods/000.%20MiscUtil/Compression/Vcdiff some code and ideas borrowed from: https://hack64.net/jscripts/libpatch.js?6 */ //const VCDIFF_MAGIC=0xd6c3c400; const VCDIFF_MAGIC='\xd6\xc3\xc4'; /* const XDELTA_014_MAGIC='%XDELTA'; const XDELTA_018_MAGIC='%XDZ000'; const XDELTA_020_MAGIC='%XDZ001'; const XDELTA_100_MAGIC='%XDZ002'; const XDELTA_104_MAGIC='%XDZ003'; const XDELTA_110_MAGIC='%XDZ004'; */ function VCDIFF(patchFile){ this.file=patchFile; } VCDIFF.prototype.toString=function(){ return 'VCDIFF patch' } VCDIFF.prototype.apply=function(romFile, validate){ //romFile._u8array=new Uint8Array(romFile._dataView.buffer); //var t0=performance.now(); var parser=new VCDIFF_Parser(this.file); //read header parser.seek(4); var headerIndicator=parser.readU8(); if(headerIndicator & VCD_DECOMPRESS){ //has secondary decompressor, read its id var secondaryDecompressorId=parser.readU8(); if(secondaryDecompressorId!==0) throw new Error('not implemented: secondary decompressor'); } if(headerIndicator & VCD_CODETABLE){ var codeTableDataLength=parser.read7BitEncodedInt(); if(codeTableDataLength!==0) throw new Error('not implemented: custom code table'); // custom code table } if(headerIndicator & VCD_APPHEADER){ // ignore app header data var appDataLength=parser.read7BitEncodedInt(); parser.skip(appDataLength); } var headerEndOffset=parser.offset; //calculate target file size var newFileSize=0; while(!parser.isEOF()){ var winHeader=parser.decodeWindowHeader(); newFileSize+=winHeader.targetWindowLength; parser.skip(winHeader.addRunDataLength + winHeader.addressesLength + winHeader.instructionsLength); } tempFile=new MarcFile(newFileSize); parser.seek(headerEndOffset); var cache = new VCD_AdressCache(4,3); var codeTable = VCD_DEFAULT_CODE_TABLE; var targetWindowPosition = 0; //renombrar while(!parser.isEOF()){ var winHeader = parser.decodeWindowHeader(); var addRunDataStream = new VCDIFF_Parser(this.file, parser.offset); var instructionsStream = new VCDIFF_Parser(this.file, addRunDataStream.offset + winHeader.addRunDataLength); var addressesStream = new VCDIFF_Parser(this.file, instructionsStream.offset + winHeader.instructionsLength); var addRunDataIndex = 0; cache.reset(addressesStream); var addressesStreamEndOffset = addressesStream.offset; while(instructionsStream.offset0){ this.near[this.nextNearSlot]=address; this.nextNearSlot=(this.nextNearSlot+1)%this.nearSize; } if(this.sameSize>0){ this.same[address%(this.sameSize*256)]=address; } }