BWT, MTF, RLE 3種解碼法,只為破解一種圖檔。
以下是源碼:
procedure MTFDecode(Src:PByte; SrcSize:integer);
var
Table:array [0..$FF] of Byte;
i,j,k:integer;
begin
for i:=0 to 255 do
Table[i]:=i;
i:=0;
while i<SrcSize do
begin
k:=Src^;
Src^:=Table[k];
if k<>0 then
for j:=k-1 downto 0 do
Table[j+1]:=Table[j];
Table[0]:=Src^;
inc(i);
inc(Src);
end;
end;
procedure BWTDecode(Src:PByte; SrcSize, Key:integer);
var
Table:array[0..$FF] of Longword;
SrcBuf, P:PByte;
DataBuf, Q:PInt;
i,j:integer;
begin
ZeroMemory(@Table, $400);
GetMem(SrcBuf, SrcSize);
DataBuf:=AllocMem(SrcSize*4);
CopyMemory(SrcBuf, Src, SrcSize);
P:=SrcBuf;
for j:=0 to SrcSize-1 do
begin
inc(Table[P^]);
inc(P);
end;
for j:=1 to $FF do
Table[j]:=Table[j-1]+Table[j];
P:=SrcBuf;
inc(P, SrcSize-1);
for j:=SrcSize-1 downto 1 do
begin
dec(Table[P^]);
Q:=DataBuf;
inc(Q, Table[P^]);
Q^:= j;
dec(P);
end;
j:=Key;
for i:=1 to SrcSize do
begin
Q:=DataBuf;
inc(Q, j);
j:=Q^;
P:=SrcBuf;
inc(P, j);
Src^:=P^;
inc(Src);
end;
FreeMem(SrcBuf);
FreeMem(DataBuf);
end;
procedure RLEDecode(Img, Src:PByte; ImgSize, SrcSize, Step :integer);
var
Count, Remain, y, m, n, k, i:integer;
Q:PByte;
begin
asm
mov eax, ImgSize
cdq
idiv Step
mov Count, eax
mov Remain, edx
end;
for k:= 0 to Step-1 do
begin //3
Q:=Img;
inc(Q, k);
y:=Count;
if k<=Remain -1 then
inc(y);
while (y>0) do
begin //4
i:=Src^;
inc(Src);
m:=1;
if (i=Src^) and (y>1) then //repeat write last byte
begin
inc(Src);
if (Src^>$7F) then //repeat count
begin
m:=Src^ and $7F shl 8 + $82;
inc(Src);
m:=m+Src^;
end
else
m:=2+Src^;
inc(Src);
end;
dec(y, m);
for n:=1 to m do
begin
Q^:=i;
inc(Q, Step);
end;
end; //4
end; //3
end;
function ReadCode(Src:PByte; Count:integer; var SrcPos, BitRemain:integer):integer;
const Mask:array [0..8] of byte=(0,1,3,7,15,31,63,127,255);
var
Data:Byte;
begin
inc(Src, SrcPos);
if BitRemain<Count then
begin
Data:=Src^ and Mask[BitRemain];
Count:=Count-BitRemain;
inc(Src);
inc(SrcPos);
BitRemain:=8-Count;
Result:=(Data shl Count) or (Src^ shr BitRemain);
end
else
begin
Result:=(Src^ and Mask[BitRemain]) shr (BitRemain-Count);
BitRemain:=BitRemain-Count;
end;
end;
type
TNodes=packed record
Leaf:array [0..1] of integer;
end;
TBMRHdr=packed record
ID:array [0..2] of char;
Step:Byte;
ImgSize,
Key,
OutSize,
DataSize:integer;
end;
procedure GetBMRImg;
var
BitRemain, RecentNode, ParentNode, Node, i,n, Pos:integer;
SrcBuf, OutBuf, ImgBuf, Src, Dest:PByte;
HufTree: array [0..$1FF] of TNodes; //0..$FF useless, $100..$1FF nodes
Done:Boolean;
BMRHeader:TBMRHdr;
procedure WriteLeaf(Code:integer);
begin
if Code=$100 then
begin
Done:=True;
Exit;
end;
if HufTree[RecentNode].Leaf[0]=-1 then
HufTree[RecentNode].Leaf[0]:=Code
else
if HufTree[RecentNode].Leaf[1]=-1 then
begin
HufTree[RecentNode].Leaf[1]:=Code;
ParentNode:=RecentNode;
dec(RecentNode);
WriteLeaf(ParentNode);
end
else
begin
dec(RecentNode);
WriteLeaf(ParentNode);
end;
end;
begin
SFile.Position:=Offset;
SFile.Read(BMRHeader, sizeof(BMRHeader));
if BMRHeader.ID='BMR' then
begin
GetMem(SrcBuf, BMRHeader.DataSize);
GetMem(OutBuf, BMRHeader.OutSize);
GetMem(ImgBuf, BMRHeader.ImgSize);
SFile.Read(SrcBuf^, BMRHeader.DataSize);
for n:=0 to $1FF do
for i:=0 to 1 do
HufTree[n].Leaf[i]:=-1;
BitRemain:=8;
Node:=$FF;
RecentNode:=Node;
ParentNode:=Node;
Src:=SrcBuf;
Pos:=0;
Done:=False;
while (Node<$200) and (BMRHeader.DataSize>Pos) and not Done do
begin
i:=ReadCode(Src, 1, Pos, BitRemain);
if i=0 then
begin
i:=ReadCode(Src, 8, Pos, BitRemain);
WriteLeaf(i);
end
else
begin
inc(Node);
RecentNode:=Node;
ParentNode:=Node;
end;
end;
RecentNode:=$100;
Dest:=OutBuf;
n:=BMRHeader.OutSize;
while (BMRHeader.DataSize>Pos) and (n>0) do
begin
i:=ReadCode(Src, 1, Pos, BitRemain);
if HufTree[RecentNode].Leaf[i]>$FF then
begin
RecentNode:=HufTree[RecentNode].Leaf[i];
continue;
end
else
begin
Dest^:=HufTree[RecentNode].Leaf[i];
dec(n);
inc(Dest);
RecentNode:=$100;
end;
end;
MTFDecode(OutBuf, BMRHeader.OutSize);
BWTDecode(OutBuf, BMRHeader.OutSize, BMRHeader.Key);
if BMRHeader.Step>0 then
begin
RLEDecode(ImgBuf, OutBuf, BMRHeader.ImgSize,
BMRHeader.OutSize, BMRHeader.Step);
BMR_SelectCG(ImgBuf, BMRHeader.ImgSize);
end
else
BMR_SelectCG(OutBuf, BMRHeader.ImgSize);
FreeMem(OutBuf);
FreeMem(ImgBuf);
FreeMem(SrcBuf);
end;
end;
沒有留言:
張貼留言