2014年2月1日 星期六

BWT, MTF, RLE Decode by Delphi

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;

沒有留言:

張貼留言