home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 12746 / UnHSQ.7z / unhsq.dpr next >
Encoding:
Text File  |  2017-04-05  |  10.1 KB  |  449 lines

  1. program unhsq;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   SysUtils,
  7.   Windows,
  8.   Classes;
  9.  
  10. var
  11.   M, O: TMemoryStream;
  12.   Header: Array[0..5] of Byte;
  13.   Bits: Word;
  14.   BitsCnt: Byte;
  15.   DecCnt, DecOff: SmallInt;
  16.   DecPos: Integer;
  17.  
  18. function GetBit(): Byte;
  19. begin
  20.   if BitsCnt = 0 then
  21.   begin
  22.     M.ReadBuffer(Bits, 2);
  23.     BitsCnt := 16;
  24.   end;
  25.   Result := Bits and 1;
  26.   Bits := Bits shr 1;
  27.   Dec(BitsCnt);
  28. end;
  29.  
  30. function SetMask: Word;
  31. var
  32.   I: Integer;
  33.   U, L: Word;
  34. begin
  35.   U := Word(not 0);
  36.   L := U;
  37.   for I := 1 to Header[5] do
  38.   begin
  39.     U := U shr 1;
  40.     L := L shl 1;
  41.   end;
  42.   Result := (not U) or (not L);
  43. end;
  44.  
  45. function IsHSQ: Boolean;
  46. var
  47.   Chk: Byte;
  48.   I: Integer;
  49. begin
  50.   // Header[0] - word DecompSize
  51.   // Header[1]
  52.   // Header[2] - byte Null = 0
  53.   // Header[3] - word CompSize
  54.   // Header[4]
  55.   // Header[5] - byte Checksum
  56.   Result := False;
  57.   if Header[2] > 0 then
  58.   begin
  59.     //Writeln('Wrong check byte.');
  60.     Exit;
  61.   end;
  62.   if PWord(@Header[3])^ <> M.Size then
  63.   begin
  64.     //Writeln('Wrong compressed size.');
  65.     Exit;
  66.   end;
  67.   Chk := 0;
  68.   for I := 0 to 6 - 1 do
  69.     Chk := (Chk + Header[I]) and $FF;
  70.   if Chk <> $AB then
  71.   begin
  72.     //Writeln('Wrong checksum.');
  73.     Exit;
  74.   end;
  75.   Result := True;
  76. end;
  77.  
  78. function IsSQX: Boolean;
  79. begin
  80.   // Header[0] - word OutbufInit
  81.   // Header[1]
  82.   // Header[2] - byte SQX flag #1
  83.   // Header[3] - byte SQX flag #2
  84.   // Header[4] - byte SQX flag #3
  85.   // Header[5] - byte CntOffPart
  86.   Result := False;
  87.   if Header[2] > 2 then
  88.   begin
  89.     //Writeln('Wrong SQX flag #1.');
  90.     Exit;
  91.   end;
  92.   if Header[3] > 2 then
  93.   begin
  94.     //Writeln('Wrong SQX flag #2.');
  95.     Exit;
  96.   end;
  97.   if Header[3] > 2 then
  98.   begin
  99.     //Writeln('Wrong SQX flag #3.');
  100.     Exit;
  101.   end;
  102.   if (Header[5] = 0)
  103.   or (Header[5] > 15) then
  104.   begin
  105.     //Writeln('Wrong bit count.');
  106.     Exit;
  107.   end;
  108.   Result := True;
  109. end;
  110.  
  111. procedure DecHSQ;
  112. var
  113.   B: Byte;
  114.   I: Integer;
  115. begin
  116.   BitsCnt := 0;
  117.   DecCnt := 0;
  118.   while O.Size < PWord(@Header[0])^ do
  119.   begin
  120.     if GetBit() > 0 then
  121.     begin
  122.       M.ReadBuffer(B, 1);
  123.       O.WriteBuffer(B, 1);
  124.     end
  125.     else
  126.     begin
  127.       if GetBit() > 0 then
  128.       begin
  129.         M.ReadBuffer(DecCnt, 2);
  130.         DecOff := (Word(DecCnt) shr 3) - 8192;
  131.         DecCnt := Word(DecCnt) and 7;
  132.         if DecCnt = 0 then
  133.           M.ReadBuffer(DecCnt, 1);
  134.         if DecCnt = 0 then
  135.           Break;
  136.       end
  137.       else
  138.       begin
  139.         DecCnt := GetBit() * 2 + GetBit();
  140.         M.ReadBuffer(B, 1);
  141.         DecOff := B - 256;
  142.       end;
  143.       DecCnt := DecCnt + 2;
  144.       DecPos := O.Position;
  145.       for I := 0 to DecCnt - 1 do
  146.       begin
  147.         O.Position := DecPos + DecOff + I;
  148.         if O.Position >= 0 then
  149.         begin
  150.           O.ReadBuffer(B, 1);
  151.           O.Position := O.Size;
  152.           O.WriteBuffer(B, 1);
  153.         end;
  154.       end;
  155.     end;
  156.   end;
  157. end;
  158.  
  159. procedure DecSQX;
  160. var
  161.   Mask: Word;
  162.   Chk, ChkS, B: Byte;
  163.  
  164.   procedure CopyOutStr(DecOff, DecCnt: SmallInt);
  165.   var
  166.     DecPos, OutPos, I: Integer;
  167.     B: Byte;
  168.   begin
  169.     DecCnt := DecCnt + 2;
  170.     DecPos := O.Position;
  171.     OutPos := DecPos;
  172.     for I := 0 to DecCnt - 1 do
  173.     begin
  174.       O.Position := DecPos + DecOff + I;
  175.       if O.Position >= 0 then
  176.       begin
  177.         O.ReadBuffer(B, 1);
  178.         O.Position := OutPos;
  179.         O.WriteBuffer(B, 1);
  180.         OutPos := O.Position;
  181.       end;
  182.     end;
  183.   end;
  184. begin
  185.   // SQX flags: 0, 1, 2
  186.   O.SetSize(65528);
  187.   FillChar(O.Memory^, O.Size, 0);
  188.   O.WriteBuffer(PWord(@Header[0])^, 2);
  189.   O.Seek(0, soFromBeginning);
  190.   Mask := SetMask;
  191.   Bits := 1;
  192.   while True do
  193.   begin
  194.     Chk := Bits and 1;
  195.     Bits := Bits shr 1;
  196.     if Bits = 0 then
  197.     begin
  198.       ChkS := Chk;
  199.       M.ReadBuffer(Bits, 2);
  200.       Chk := Bits and 1;
  201.       Bits := Bits shr 1;
  202.       if ChkS <> 0 then
  203.         Bits := Bits or $8000;
  204.     end;
  205.     if (Chk = 0) then
  206.       case Header[2] of
  207.         0:
  208.         begin
  209.           M.ReadBuffer(B, 1);
  210.           O.WriteBuffer(B, 1);
  211.           Continue;
  212.         end;
  213.         1:
  214.         begin
  215.           DecCnt := 0;
  216.           Chk := Bits and 1;
  217.           Bits := Bits shr 1;
  218.           if Bits = 0 then
  219.           begin
  220.             M.ReadBuffer(Bits, 2);
  221.             ChkS := Chk;
  222.             Chk := Bits and 1;
  223.             Bits := Bits shr 1;
  224.             if ChkS <> 0 then
  225.               Bits := Bits or $8000;
  226.             DecCnt := Chk;
  227.             Chk := Bits and 1;
  228.             Bits := Bits shr 1;
  229.           end
  230.           else
  231.           begin
  232.             DecCnt := Chk;
  233.             Chk := Bits and 1;
  234.             Bits := Bits shr 1;
  235.             if Bits = 0 then
  236.             begin
  237.               M.ReadBuffer(Bits, 2);
  238.               ChkS := Chk;
  239.               Chk := Bits and 1;
  240.               Bits := Bits shr 1;
  241.               if ChkS <> 0 then
  242.                 Bits := Bits or $8000;
  243.             end;
  244.           end;
  245.           DecCnt := (DecCnt shl 1) + Chk;
  246.           M.ReadBuffer(B, 1);
  247.           DecOff := B - 256;
  248.           CopyOutStr(DecOff, DecCnt);
  249.           Continue;
  250.         end;
  251.         2:
  252.         begin
  253.           M.ReadBuffer(DecCnt, 2);
  254.           DecOff := (DecCnt shr Header[5]) or (Mask and $FF00);
  255.           DecCnt := DecCnt and Lo(Mask);
  256.           if DecCnt = 0 then
  257.           begin
  258.             M.ReadBuffer(B, 1);
  259.             DecCnt := B;
  260.             if DecCnt = 0 then
  261.               Break;
  262.           end;
  263.           CopyOutStr(DecOff, DecCnt);
  264.           Continue;
  265.         end;
  266.       end
  267.     else
  268.     begin
  269.       Chk := Bits and 1;
  270.       Bits := Bits shr 1;
  271.       if Bits = 0 then
  272.       begin
  273.         M.ReadBuffer(Bits, 2);
  274.         ChkS := Chk;
  275.         Chk := Bits and 1;
  276.         Bits := Bits shr 1;
  277.         if ChkS <> 0 then
  278.           Bits := Bits or $8000;
  279.       end;
  280.       if (Chk = 0) then
  281.         case Header[3] of
  282.           0:
  283.           begin
  284.             M.ReadBuffer(B, 1);
  285.             O.WriteBuffer(B, 1);
  286.             Continue;
  287.           end;
  288.           1:
  289.           begin
  290.             DecCnt := 0;
  291.             Chk := Bits and 1;
  292.             Bits := Bits shr 1;
  293.             if Bits = 0 then
  294.             begin
  295.               M.ReadBuffer(Bits, 2);
  296.               ChkS := Chk;
  297.               Chk := Bits and 1;
  298.               Bits := Bits shr 1;
  299.               if ChkS <> 0 then
  300.                 Bits := Bits or $8000;
  301.               DecCnt := Chk;
  302.               Chk := Bits and 1;
  303.               Bits := Bits shr 1;
  304.             end
  305.             else
  306.             begin
  307.               DecCnt := Chk;
  308.               Chk := Bits and 1;
  309.               Bits := Bits shr 1;
  310.               if Bits = 0 then
  311.               begin
  312.                 M.ReadBuffer(Bits, 2);
  313.                 ChkS := Chk;
  314.                 Chk := Bits and 1;
  315.                 Bits := Bits shr 1;
  316.                 if ChkS <> 0 then
  317.                   Bits := Bits or $8000;
  318.               end;
  319.             end;
  320.             DecCnt := (DecCnt shl 1) + Chk;
  321.             M.ReadBuffer(B, 1);
  322.             DecOff := B - 256;
  323.             CopyOutStr(DecOff, DecCnt);
  324.             Continue;
  325.           end;
  326.           2:
  327.           begin
  328.             M.ReadBuffer(DecCnt, 2);
  329.             DecOff := (DecCnt shr Header[5]) or (Mask and $FF00);
  330.             DecCnt := DecCnt and Lo(Mask);
  331.             if DecCnt = 0 then
  332.             begin
  333.               M.ReadBuffer(B, 1);
  334.               DecCnt := B;
  335.               if DecCnt = 0 then
  336.                 Break;
  337.             end;
  338.             CopyOutStr(DecOff, DecCnt);
  339.             Continue;
  340.           end;
  341.         end
  342.       else
  343.         case Header[4] of
  344.           0:
  345.           begin
  346.             M.ReadBuffer(B, 1);
  347.             O.WriteBuffer(B, 1);
  348.             Continue;
  349.           end;
  350.           1:
  351.           begin
  352.             DecCnt := 0;
  353.             Chk := Bits and 1;
  354.             Bits := Bits shr 1;
  355.             if Bits = 0 then
  356.             begin
  357.               M.ReadBuffer(Bits, 2);
  358.               ChkS := Chk;
  359.               Chk := Bits and 1;
  360.               Bits := Bits shr 1;
  361.               if ChkS <> 0 then
  362.                 Bits := Bits or $8000;
  363.               DecCnt := Chk;
  364.               Chk := Bits and 1;
  365.               Bits := Bits shr 1;
  366.             end
  367.             else
  368.             begin
  369.               DecCnt := Chk;
  370.               Chk := Bits and 1;
  371.               Bits := Bits shr 1;
  372.               if Bits = 0 then
  373.               begin
  374.                 M.ReadBuffer(Bits, 2);
  375.                 ChkS := Chk;
  376.                 Chk := Bits and 1;
  377.                 Bits := Bits shr 1;
  378.                 if ChkS <> 0 then
  379.                   Bits := Bits or $8000;
  380.               end;
  381.             end;
  382.             DecCnt := (DecCnt shl 1) + Chk;
  383.             M.ReadBuffer(B, 1);
  384.             DecOff := B - 256;
  385.             CopyOutStr(DecOff, DecCnt);
  386.             Continue;
  387.           end;
  388.           2:
  389.           begin
  390.             M.ReadBuffer(DecCnt, 2);
  391.             DecOff := (DecCnt shr Header[5]) or (Mask and $FF00);
  392.             DecCnt := DecCnt and Lo(Mask);
  393.             if DecCnt = 0 then
  394.             begin
  395.               M.ReadBuffer(B, 1);
  396.               DecCnt := B;
  397.               if DecCnt = 0 then
  398.                 Break;
  399.             end;
  400.             CopyOutStr(DecOff, DecCnt);
  401.             Continue;
  402.           end;
  403.         end;
  404.     end;
  405.   end;
  406.   O.SetSize(O.Position);
  407. end;
  408.  
  409. begin
  410.   try
  411.     { TODO -oUser -cConsole Main : Insert code here }
  412.  
  413.   M := TMemoryStream.Create;
  414.   M.LoadFromFile(ParamStr(1));
  415.   if M.Size < 6 then
  416.   begin
  417.     Writeln('File too small.');
  418.     M.Free;
  419.     Exit;
  420.   end;
  421.   M.ReadBuffer(Header, 6);
  422.   O := TMemoryStream.Create;
  423.   if IsHSQ then
  424.   begin
  425.     Writeln('File HSQ compressed.');
  426.     DecHSQ;
  427.     Writeln('Decompression done.');
  428.   end else
  429.   if IsSQX then
  430.   begin
  431.     Writeln('File SQX compressed.');
  432.     DecSQX;
  433.     Writeln('Decompression done.');
  434.   end else
  435.   begin
  436.     Writeln('File is uncompressed.');
  437.     Exit;
  438.   end;
  439.  
  440.   M.Free;
  441.   O.SaveToFile(ChangeFileExt(ParamStr(1), '.raw'));
  442.   O.Free;
  443.  
  444.   except
  445.     on E: Exception do
  446.       Writeln(E.ClassName, ': ', E.Message);
  447.   end;
  448. end.
  449.