Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
232 lines
5.0 KiB
C++
232 lines
5.0 KiB
C++
// Span.cpp: implementation of the Span class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "PatchIT.h"
|
|
#include "Span.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
void Span::DeleteChildren()
|
|
{
|
|
if(Next) Next->DeleteChildren();
|
|
delete Next;
|
|
Next=NULL;
|
|
}
|
|
|
|
void Span::InsertNodeAfter(Span *span)
|
|
{
|
|
|
|
if(Next)
|
|
{
|
|
Next->Prev=span;
|
|
}
|
|
span->Next=Next;
|
|
span->Prev=this;
|
|
Next=span;
|
|
}
|
|
|
|
int Span::FindLargestSpan(Span *comspan,DWORD *pos1,DWORD *pos2,DWORD minsize)
|
|
{
|
|
DWORD maxspan=minsize;
|
|
|
|
BYTE *comsbuf=comspan->Buffer;
|
|
|
|
|
|
DWORD pos,cspos,dpos;
|
|
|
|
for(pos=0;pos<Size && (pos+maxspan)<=Size;pos++)
|
|
{
|
|
|
|
for(cspos=0;cspos<comspan->Size && (cspos+maxspan)<=comspan->Size;cspos++)
|
|
{
|
|
|
|
if(Buffer[pos]==comsbuf[cspos] &&
|
|
Buffer[pos+(maxspan-1)]==comsbuf[cspos+(maxspan-1)]
|
|
)
|
|
{
|
|
//Check First and Last for Early out
|
|
|
|
for(dpos=1;(cspos+dpos)<comspan->Size &&
|
|
(pos+dpos)<Size &&
|
|
Buffer[pos+dpos]==comsbuf[cspos+dpos];dpos++);
|
|
|
|
if(dpos>maxspan)
|
|
{
|
|
maxspan=dpos;
|
|
*pos1=pos;
|
|
*pos2=cspos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return maxspan;
|
|
} //End of Find Span
|
|
|
|
|
|
int Span::MapLargestSpan(Span *comspan,DWORD minsize)
|
|
{
|
|
DWORD spansize;
|
|
DWORD pos,cspos;
|
|
|
|
|
|
spansize=FindLargestSpan(comspan,&pos,&cspos,minsize);
|
|
|
|
|
|
if(spansize>minsize)
|
|
{ // Missed creeping up Take Last One
|
|
Span *new_span1,*new_span2;
|
|
new_span1=AddSpanAt(Buffer+pos,spansize);
|
|
new_span2=comspan->AddSpanAt(comspan->Buffer+cspos,spansize);
|
|
new_span1->MappedTo=new_span2;
|
|
new_span2->MappedTo=new_span1;
|
|
|
|
if(new_span1->Prev!=NULL && new_span1->Prev->MappedTo==NULL &&
|
|
new_span2->Prev!=NULL && new_span2->Prev->MappedTo==NULL) //Map the left
|
|
new_span1->Prev->MapLargestSpan(new_span2->Prev,minsize);
|
|
|
|
if(new_span1->Next!=NULL && new_span1->Next->MappedTo==NULL &&
|
|
new_span2->Next!=NULL && new_span2->Next->MappedTo==NULL) //Map the right
|
|
new_span1->Next->MapLargestSpan(new_span2->Next,minsize);
|
|
|
|
return spansize;
|
|
|
|
}
|
|
return spansize;
|
|
} //End of Find Span
|
|
|
|
|
|
Span *Span::AddSpanAt(BYTE * loc,DWORD size)
|
|
{
|
|
/* // This will put it in the right place
|
|
if(loc<Buffer)
|
|
{ // Location is in a forward Box
|
|
ASSERT(Next);
|
|
Next->AddSpanAt(loc,size,map);
|
|
return;
|
|
}
|
|
*/
|
|
ASSERT(loc>=Buffer && (loc+size)<=(Buffer+Size)); //Must Be a Sub Span
|
|
ASSERT(MappedTo==NULL); //Cannot Split a Mapped Span
|
|
|
|
|
|
|
|
DWORD endsize;
|
|
Span *new_span;
|
|
|
|
if((loc-Buffer)==0) //Don't Need a new one Adjust them
|
|
{
|
|
endsize=Size-size;
|
|
Size=size;
|
|
new_span=this;
|
|
}
|
|
else
|
|
{
|
|
new_span= new Span(loc,size); // Make our Span
|
|
InsertNodeAfter(new_span);
|
|
endsize=Size-((loc-Buffer)+size);
|
|
Size=(loc-Buffer);
|
|
}
|
|
|
|
|
|
ASSERT(endsize>=0);
|
|
if(endsize>0)
|
|
{
|
|
new_span->InsertNodeAfter(new Span(loc+size,endsize)); // At end span if needed;
|
|
}
|
|
|
|
return new_span;
|
|
}
|
|
|
|
void Span::SpanInfo(CString &fstr,BYTE *base1,BYTE *base2)
|
|
{
|
|
CString str;
|
|
str.Format("Location = %i Size = %i ",Buffer-base1,Size);
|
|
if(MappedTo)
|
|
{
|
|
CString str2;
|
|
str2.Format(" -> Location = %i",MappedTo->Buffer-base2);
|
|
str+=str2;
|
|
}
|
|
str+="\n";
|
|
fstr+=str;
|
|
if(Next) Next->SpanInfo(fstr,base1,base2);
|
|
}
|
|
|
|
void Span::BuildOps(Span *sspan,CPatchOperation *OpList,const BYTE *base1,const BYTE *base2)
|
|
{
|
|
Span *cur_node1,*cur_node2;
|
|
|
|
DWORD lastloc=0;
|
|
cur_node1=this;
|
|
cur_node2=sspan;
|
|
|
|
while(cur_node1 && cur_node2)
|
|
{
|
|
if(cur_node2->MappedTo==NULL)
|
|
{
|
|
OpList->Next=new CInsert(cur_node1->Buffer-base1,cur_node2->Size,cur_node2->Buffer-base2);
|
|
OpList=OpList->Next;
|
|
cur_node2=cur_node2->Next;
|
|
}
|
|
|
|
if(cur_node1->MappedTo==NULL)
|
|
{
|
|
OpList->Next=new CDelete(cur_node1->Buffer-base1,cur_node1->Size);
|
|
OpList=OpList->Next;
|
|
lastloc=cur_node1->Buffer-base1+cur_node1->Size;
|
|
cur_node1=cur_node1->Next;
|
|
}
|
|
|
|
|
|
ASSERT((!cur_node1 || cur_node1->MappedTo!=NULL));
|
|
ASSERT((!cur_node2 || cur_node2->MappedTo!=NULL));
|
|
|
|
if(cur_node1 || cur_node2)
|
|
{
|
|
ASSERT(cur_node2 && cur_node1);
|
|
lastloc=cur_node1->Buffer-base1+cur_node1->Size;
|
|
cur_node1=cur_node1->Next;
|
|
cur_node2=cur_node2->Next;
|
|
}
|
|
|
|
}
|
|
|
|
if(cur_node1)
|
|
{
|
|
ASSERT(cur_node1->MappedTo==NULL);
|
|
OpList->Next=new CDelete(cur_node1->Buffer-base1,cur_node1->Size);
|
|
OpList=OpList->Next;
|
|
lastloc=cur_node1->Buffer-base1+cur_node1->Size;
|
|
cur_node1=cur_node1->Next;
|
|
}
|
|
|
|
if(cur_node2)
|
|
{
|
|
ASSERT(cur_node2->MappedTo==NULL);
|
|
OpList->Next=new CInsert(lastloc,cur_node2->Size,cur_node2->Buffer-base2);
|
|
OpList=OpList->Next;
|
|
cur_node2=cur_node2->Next;
|
|
}
|
|
|
|
ASSERT(!cur_node1 && !cur_node2);
|
|
|
|
}
|
|
|
|
Span::~Span()
|
|
{
|
|
DeleteChildren();
|
|
|
|
}
|