144 lines
3.0 KiB
C++
144 lines
3.0 KiB
C++
#include "rar.hpp"
|
|
|
|
#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
|
|
|
|
RSCoder::RSCoder(int ParSize)
|
|
{
|
|
RSCoder::ParSize=ParSize;
|
|
FirstBlockDone=false;
|
|
gfInit();
|
|
pnInit();
|
|
}
|
|
|
|
|
|
void RSCoder::gfInit()
|
|
{
|
|
for (int I=0,J=1;I<MAXPAR;I++)
|
|
{
|
|
gfLog[J]=I;
|
|
gfExp[I]=J;
|
|
if ((J<<=1)&256)
|
|
J^=285;
|
|
}
|
|
for (int I=MAXPAR;I<MAXPOL;I++)
|
|
gfExp[I]=gfExp[I-MAXPAR];
|
|
}
|
|
|
|
|
|
inline int RSCoder::gfMult(int a,int b)
|
|
{
|
|
return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]);
|
|
}
|
|
|
|
|
|
void RSCoder::pnInit()
|
|
{
|
|
int p1[MAXPAR+1],p2[MAXPAR+1];
|
|
|
|
Clean(p2,ParSize);
|
|
p2[0]=1;
|
|
for (int I=1;I<=ParSize;I++)
|
|
{
|
|
Clean(p1,ParSize);
|
|
p1[0]=gfExp[I];
|
|
p1[1]=1;
|
|
pnMult(p1,p2,GXPol);
|
|
for (int J=0;J<ParSize;J++)
|
|
p2[J]=GXPol[J];
|
|
}
|
|
}
|
|
|
|
|
|
void RSCoder::pnMult(int *p1,int *p2,int *r)
|
|
{
|
|
Clean(r,ParSize);
|
|
for (int I=0;I<ParSize;I++)
|
|
if (p1[I]!=0)
|
|
for(int J=0;J<ParSize-I;J++)
|
|
r[I+J]^=gfMult(p1[I],p2[J]);
|
|
}
|
|
|
|
|
|
void RSCoder::Encode(byte *Data,int DataSize,byte *DestData)
|
|
{
|
|
int ShiftReg[MAXPAR+1];
|
|
|
|
Clean(ShiftReg,ParSize+1);
|
|
for (int I=0;I<DataSize;I++)
|
|
{
|
|
int D=Data[I]^ShiftReg[ParSize-1];
|
|
for (int J=ParSize-1;J>0;J--)
|
|
ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D);
|
|
ShiftReg[0]=gfMult(GXPol[0],D);
|
|
}
|
|
for (int I=0;I<ParSize;I++)
|
|
DestData[I]=ShiftReg[ParSize-I-1];
|
|
}
|
|
|
|
|
|
bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize)
|
|
{
|
|
int SynData[MAXPOL];
|
|
bool AllZeroes=true;
|
|
for (int I=0;I<ParSize;I++)
|
|
{
|
|
int Sum=Data[0],J=1,Exp=gfExp[I+1];
|
|
for (;J+8<=DataSize;J+=8)
|
|
{
|
|
Sum=Data[J]^gfMult(Exp,Sum);
|
|
Sum=Data[J+1]^gfMult(Exp,Sum);
|
|
Sum=Data[J+2]^gfMult(Exp,Sum);
|
|
Sum=Data[J+3]^gfMult(Exp,Sum);
|
|
Sum=Data[J+4]^gfMult(Exp,Sum);
|
|
Sum=Data[J+5]^gfMult(Exp,Sum);
|
|
Sum=Data[J+6]^gfMult(Exp,Sum);
|
|
Sum=Data[J+7]^gfMult(Exp,Sum);
|
|
}
|
|
for (;J<DataSize;J++)
|
|
Sum=Data[J]^gfMult(Exp,Sum);
|
|
if ((SynData[I]=Sum)!=0)
|
|
AllZeroes=false;
|
|
}
|
|
if (AllZeroes)
|
|
return(true);
|
|
|
|
if (!FirstBlockDone)
|
|
{
|
|
FirstBlockDone=true;
|
|
Clean(PolB,ParSize+1);
|
|
PolB[0]=1;
|
|
for (int EraPos=0;EraPos<EraSize;EraPos++)
|
|
for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--)
|
|
PolB[I]^=gfMult(M,PolB[I-1]);
|
|
|
|
ErrCount=0;
|
|
for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++)
|
|
{
|
|
int Sum=0;
|
|
for (int B=0;B<ParSize+1;B++)
|
|
Sum^=gfMult(gfExp[(B*Root)%MAXPAR],PolB[B]);
|
|
if (Sum==0)
|
|
{
|
|
Dn[ErrCount]=0;
|
|
for (int I=1;I<ParSize+1;I+=2)
|
|
Dn[ErrCount]^= gfMult(PolB[I],gfExp[Root*(I-1)%MAXPAR]);
|
|
ErrorLocs[ErrCount++]=MAXPAR-Root;
|
|
}
|
|
}
|
|
}
|
|
|
|
int PolD[MAXPOL];
|
|
pnMult(PolB,SynData,PolD);
|
|
if ((ErrCount<=ParSize) && ErrCount>0)
|
|
for (int I=0;I<ErrCount;I++)
|
|
{
|
|
int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0;
|
|
for (int J=0;J<ParSize;J++)
|
|
N^=gfMult(PolD[J],gfExp[DLoc*J%MAXPAR]);
|
|
int DataPos=DataSize-Loc-1;
|
|
if (DataPos>=0 && DataPos<DataSize)
|
|
Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dn[I]]]);
|
|
}
|
|
return(ErrCount<=ParSize);
|
|
}
|