diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index 8a8f00d15..51080a017 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -804,8 +804,9 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock unsigned char* buf=stream->getFinalBuf(); size_t matchSize=MIN_MATCH_SIZE; std::vector matches; + std::vector workMatches; std::vector origs; - std::vector benefits; + MatchBenefit bestBenefit; matches.clear(); @@ -879,15 +880,15 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock // collect matches with this orig value for (size_t j=i; jmaxSize) maxSize=matches[i].len; - testMatches.push_back(matches[i]); + if (matches[j].orig!=orig) break; + if (matches[j].len>maxSize) maxSize=matches[j].len; + testMatches.push_back(matches[j]); } //logD("%d: testing %d matches... (lengths %d-%d)",(int)orig,(int)testMatches.size(),minSize,maxSize); // test all lengths - for (size_t len=maxSize; len<=maxSize; len+=8) { + for (size_t len=minSize; len<=maxSize; len+=8) { testLenMatches.clear(); // filter matches for (BlockMatch& k: testMatches) { @@ -925,132 +926,93 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock testLenMatches.push_back(k); } - // check for bad matches (TODO!!!) - // try with next size if no further matches if (testLenMatches.empty()) continue; + // check for overlapping matches + size_t overlapPos=testLenMatches[0].orig; + size_t validCount=0; + for (BlockMatch& k: testLenMatches) { + //logV("test %d with %d",(int)overlapPos,(int)k.block); + if (OVERLAPS(overlapPos,overlapPos+len,k.block,k.block+len)) { + k.done=true; + //logW("overlap"); + } else { + validCount++; + } + overlapPos=k.block; + } + + // calculate (weighted) benefit const int blockSize=estimateBlockSize(&buf[testLenMatches[0].orig],len,speedDial); - const int gains=((blockSize-3)*testLenMatches.size())-4; + const int gains=((blockSize-3)*validCount)-4; int finalBenefit=gains*2+len*3; if (gains<1) finalBenefit=-1; - // push this benefit to list - if (finalBenefit>0) { - logD("- %x (%d): %d = %d",(int)i,(int)len,(int)testLenMatches.size(),finalBenefit); - benefits.push_back(MatchBenefit(i,finalBenefit,len)); + // check whether this set of matches has greater benefit + if (finalBenefit>bestBenefit.benefit) { + //logD("- %x (%d): %d = %d",(int)i,(int)len,(int)testLenMatches.size(),finalBenefit); + bestBenefit=MatchBenefit(i,finalBenefit,len); + // copy matches so we don't have to select them later + workMatches=testLenMatches; } } } - // quit if we can't go any further - if (benefits.empty()) return stream; + // quit if there isn't benefit + if (bestBenefit.benefit<1) return stream; + + // quit if there's nothing to work on + if (workMatches.empty()) return stream; // pick best benefit - MatchBenefit& bestBenefit=benefits[0]; - for (MatchBenefit& i: benefits) { - if (i.benefit>bestBenefit.benefit) bestBenefit=i; - } - logI("BEST BENEFIT: %d in %x with size %u",bestBenefit.benefit,(int)bestBenefit.index,bestBenefit.len); - /* // work on matches with this benefit - std::vector workMatches; - bool newBlocks=false; - - workMatches.clear(); - - size_t bestBenefitOrig=matches[bestBenefit.index].orig; - size_t bestBenefitLen=matches[bestBenefit.index].len; - for (size_t i=0; iinit(); + newBlock->write(&buf[bestOrig],bestBenefit.len); + newBlock->writeC(0xf9); // ret + // padding + newBlock->writeC(0); + newBlock->writeC(0); + newBlock->writeC(0); + newBlock->writeC(0); + newBlock->writeC(0); + newBlock->writeC(0); + newBlock->writeC(0); + subBlocks.push_back(newBlock); + + // insert call on the original block + buf[bestOrig]=0xf4; + buf[bestOrig+1]=subBlockID&0xff; + buf[bestOrig+2]=(subBlockID>>8)&0xff; + buf[bestOrig+3]=(subBlockID>>16)&0xff; + buf[bestOrig+4]=(subBlockID>>24)&0xff; + buf[bestOrig+5]=0; + buf[bestOrig+6]=0; + buf[bestOrig+7]=0; + + // replace the rest with nop + for (size_t j=bestOrig+8; jinit(); - newBlock->write(&buf[i.orig],i.len); - newBlock->writeC(0xf9); // ret - // padding - newBlock->writeC(0); - newBlock->writeC(0); - newBlock->writeC(0); - newBlock->writeC(0); - newBlock->writeC(0); - newBlock->writeC(0); - newBlock->writeC(0); - subBlocks.push_back(newBlock); - lastOrig=i.orig; - - // insert call on the original block - buf[i.orig]=0xf4; - buf[i.orig+1]=subBlockID&0xff; - buf[i.orig+2]=(subBlockID>>8)&0xff; - buf[i.orig+3]=(subBlockID>>16)&0xff; - buf[i.orig+4]=(subBlockID>>24)&0xff; - buf[i.orig+5]=0; - buf[i.orig+6]=0; - buf[i.orig+7]=0; - - // replace the rest with nop - for (size_t j=i.orig+8; j>8)&0xff; @@ -1071,7 +1033,6 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock // remove nop's stream=stripNops(stream); buf=stream->getFinalBuf(); - */ return stream; }