home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 5506 / src.7z / SEGA_lz77.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2012-02-20  |  11.3 KB  |  343 lines

  1. {
  2. ************************************************************
  3. * SEGA`s PRS compression                                   *
  4. * LZ77 compression with RLE emulation and extended matches *
  5. ************************************************************
  6. *                                                          *
  7. *                                                          *
  8. *
  9. ************************************************************
  10. }
  11. unit SEGA_lz77;
  12.  
  13. interface
  14.  
  15. uses
  16.   Windows, SysUtils;
  17.  
  18. Function PSO2Dec(File_Size:integer):integer; // only function you should call
  19. Function GetByte_00E1F580():byte;
  20. Function GetBit_00E1F5D0():byte;
  21. //Function memfwdcpy(dest,src,count:integer):boolean;
  22.  
  23.  
  24. Var
  25.   //-=-=--=-=-=-=-=-=-=-=-=-==-=-=-=
  26.   // PRS GLOBAL VARIABLES
  27.   //-=-=--=-=-=-=-=-=-=-=-=-==-=-=-=
  28.   buf : Array of Byte;   // SRC  Compressed File
  29.   buf2: Array of Byte;   // DST  Decompressed File
  30.   CurBit, SrcPos : Integer;
  31.   CurByte : Byte;
  32.   
  33.   BitCounter : Integer; // DWORD
  34.  
  35.   _EBP_m_4 : DWORD;    // unsigned $FF = 255  (Definately not signed)
  36.   _EBP_m_8 : DWORD; //ShortInt; // ShortInt $FF = -1 should be (definately not signed byte)
  37.   _EBP_m_D, _EBP_m_E : Byte; // (Definately not signed)
  38. {******************************************************************************}
  39. implementation
  40.  
  41. //{$R-}  
  42.  
  43. {
  44. uses
  45.   Messages, Variants, Classes, Graphics, Controls, Forms,
  46.   Dialogs, StdCtrls, XPMan, Unit1;
  47. }
  48.  
  49. Function PSO2Dec(File_Size:integer):integer; // Returns the Decompressed FileSize
  50. var
  51.   _EAX : Byte; // could be BYTE
  52.   DstPos, Count, Off : Integer;
  53. Begin
  54.   {SET UP SOME VARIABLES}
  55.   CurBit:=0;   //
  56.   SrcPos:=0;   // Compressed_Data   position (buf / ICE_DATA)
  57.   DstPos:=0;   // Decompressed_Data position (buf2)
  58.  
  59.   BitCounter := 1;
  60.  
  61.  
  62.  
  63.     While SrcPos < File_Size Do // 57328
  64.     Begin
  65.         {=========== 00E1F219 =============}
  66.  
  67.     //    BitCounter := 1;  // EDX is BitCounter
  68.     //    if BitCounter = 0 then BREAK; // File is Fully Decompressed
  69.  
  70.  
  71.  
  72.         (* === 00E1F226 === *) // ### LOOP ###
  73.         Repeat
  74.             _EAX := GetBit_00E1F5D0(); // EAX is CurBit always 1 or 0
  75.             If _EAX = 1 Then // Repeat the loop
  76.             Begin
  77.             (* === 00E1F232 === *)
  78.               Buf2[DstPos] := GetByte_00E1F580; // We Write 1 decompressed byte into buf2[srcpos]
  79.               DstPos := DstPos + 1;                      // and inc the destination pos
  80.               // 00E1F248  |.^ EB DC         |\JMP SHORT 00E1F226
  81.             End
  82.         Until
  83.           _EAX = 0;
  84.  
  85.  
  86.  
  87.  
  88.  
  89.         Begin // CurBit was 0 and we escaped the first loop   BP & line 671 in Prs_Trace.txt
  90.         (* === 00E1F24A === *)
  91.             _EAX := GetBit_00E1F5D0();
  92.               
  93.             If _EAX = 1 then // jump at 00E1F254 WAS NOT taken
  94.             Begin
  95.             (* === 00E1F256 === *)
  96.                 _EBP_m_4 := GetByte_00E1F580(); // Call Returns CurByte $F8
  97.                 _EBP_m_8 := GetByte_00E1F580(); // Call Returns CurByte $FF
  98.                 _EAX := _EBP_m_8 OR _EBP_m_4;   // can get these 3 lines onto 1 line   CurByte := Curbyte or Curbit?   FF and F8
  99.  
  100.  
  101.  
  102.             (* === 00E1F272 === *)  // # dont think this is correct
  103.                 If _EAX = 0 Then  // if true jump to 00E1F279
  104.         begin
  105.           BREAK; // <<<<<<<<<<<< SRCPOS was = to FileSize / File fully decompressed       if off = 0 then break;  // confusing comments
  106.         end;
  107.  
  108.             (* === 00E1F279 === *)
  109.                 _EBP_m_8 := (_EBP_m_8 shl 5) + (_EBP_m_4 shr 3) - $2000; // LEA
  110.                 _EBP_m_4 := _EBP_m_4 AND 7;                                   // count := off and 7;
  111.  
  112.  
  113.             (* === 00E1F298 === *)
  114.                 If _EBP_m_4 <> 0 then // If Count <> 0 then ??????????  DUNNO WHAT MAKES THIS JUMP
  115.                 Begin
  116.                   (* === 00E1F29A === *) // JUMP @ 00E1F298 NOT TAKEN
  117.                   _EBP_m_4 := _EBP_m_4 + 2; // count := count + 2;  or maybe Inc([EBP-4]);   Count/[EBP-4] is not the same as BitCounter
  118.                   // 00E1F2A3  |. /EB 0E         |JMP SHORT 00E1F2B3                      ;  Alpha-1_.00E1F2B3
  119.                   // 00E1F2B3  |> \EB 3B         |JMP SHORT 00E1F2F0                      ;  Alpha-1_.00E1F2F0
  120.                 End
  121.                 ELSE
  122.                 BEGIN
  123.                   (* === 00E1F2A5 === *) // JUMP @ 00E1F298 WAS TAKEN
  124.                   _EBP_m_4 := GetByte_00E1F580() + $0A;
  125.                   // 00E1F2B3  |>  EB 3B         |JMP SHORT 00E1F2F0                      ;  Alpha-1_.00E1F2F0
  126.                 END;
  127.             End
  128.             ELSE // jump at 00E1F254 WAS taken
  129.             Begin
  130.           (* === 00E1F2B5 === *)
  131.                 _EBP_m_D := GetBit_00E1F5D0;          // Returns $00
  132.                 _EBP_m_E := GetBit_00E1F5D0;          // Returns $01
  133.                 _EBP_m_4 := (_EBP_m_D * 2) + (_EBP_m_E + 2);          // EAX / _EBP_m_4 is count ?    $00 * 2 + $01 + 2 = $03
  134.                 
  135.                 _EBP_m_8 := GetByte_00E1F580() - $100;     // FFFFFFFC   only need Byte not DWORD
  136.             End;
  137.         
  138.     End;
  139.  
  140.  
  141.   //  Form1.mmo1.Lines.Add(IntToStr(DstPos) + #9 + IntToStr(_EBP_m_4) + #9 + IntToStr(_EBP_m_8));
  142.  
  143.  
  144.     // if  _EBP_m_4 (nibble_count) not = 0 then do this loop
  145.     // Line 800 in Prs_Trace.txt
  146.  
  147.     (* === 00E1F2F0 === *)
  148.     While _EBP_m_4 > 0 Do // WHAT IS EDX its a counter of some sort for half of a byte/nibble
  149.     Begin
  150.     //  ECX := [EBP-C DstPos] + _EBP_m_8;   // $FFFFFFFC
  151.     //  EDX := [EBP-C DstPos];
  152.  
  153.       // _EBP_m_8 needs to be signed for negative numbers
  154.       Buf2[DstPos] := Buf2[DstPos + _EBP_m_8];      // [EDX] := AL;       // Buf2[EBP-C DstPos] := Lo(ECX);
  155.  
  156.       Inc(DstPos);                                        // [EBP-C DstPos] := [EBP-C DstPos] + 1;
  157.       _EBP_m_4 := _EBP_m_4 - 1; // count was 3 becomes 2  // _EBP_m_4 := _EBP_m_4 - 1;
  158.     End;
  159.  
  160.   // GO BACK TO THE START
  161.   End;
  162.   RESULT := DstPos; // [EBP-C DstPos]
  163.  
  164.   {
  165.   NOTE:
  166.       [Tests with CRC ICE debugger]
  167.       57, 328 DstPos & File_Size
  168.       40, 467 SrcPos
  169.  
  170.       [Ice Header]
  171.       57, 328 Decompressed_Size
  172.       40, 467 Compressed_Size
  173.   }
  174. End;
  175.  
  176. Function GetBit_00E1F5D0(): BYTE; // returns the current bit
  177. var
  178.   EDX : DWORD; // Pointer to BitCounter or Pointer to CurByte (This is the calling Parameter ?)
  179. begin
  180.   Dec(BitCounter); // [EDX] Points to BitCounter   // moving this to end
  181.   
  182.   (* === OPTIMISED CODE === *)
  183.   if BitCounter = 0 then
  184.   begin
  185.     CurByte := GetByte_00E1F580(); // CurByte:=buf[SrcPos];        RETURNS = $31
  186.       BitCounter := 8;
  187.   end;
  188.  
  189.   RESULT  := CurByte and 1;  // result  := CurByte and 1;   = 1    BUG it should be $7F not $99  see line 132 of prs_Trace.txt
  190.   CurByte := CurByte shr 1;  // CurByte := CurByte div 2;   = 127
  191.  
  192.   // [ECX+4] := DecompressedByte;  // $7F (127)
  193. end;
  194.  
  195. Function GetByte_00E1F580(): BYTE;
  196. begin
  197.   (* === OPTIMISED CODE === *)
  198.  
  199.   //#### NO FUCKING IDEA DONT THINK ITS CORRECT ####
  200.   (* ==== 00E1F595 ==== *)
  201.   if SrcPos = Length(buf2) then          // if SrcPos = DecSize/[EAX+C] then          //1020E2DE - 102002f0 = DFEE (should be Grp_x_XOR_KEY / decompressed filesize)
  202.   begin
  203.     SrcPos := $05CCFD2C;             // EDX,DWORD PTR DS:[ECX+C]        //CONSTANT VALUE [ECX+10] is always $05CCFD2C; // just points to a block of $95 bytes
  204.   end;
  205.  
  206.   (* ==== 00E1F5A3 ==== *)
  207.   RESULT := Buf[SrcPos] xor $95;   // [EBP-8] becomes 1 byte from Compressed data buffer @ SrcPos
  208.   INC(SrcPos);                      // inc SrcPos
  209.  
  210.   // [EBP-8] := CompressedByte;  // $63  (which is $F6 xor $95)
  211. end;
  212.  
  213. {
  214. Function memfwdcpy(dest,src,count:integer):boolean; // Writes DeCompressed data into buf2
  215. var x:integer;
  216. begin
  217.     for x:=0 to count-1 do
  218.         buf2[dest+x] := buf2[src+x];
  219.     result:=false;
  220. }
  221. end.
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233. // IGNORE THIS IS JUST NOTES
  234.  
  235. [memfwdcpy ?]
  236. 00E1F2F0  |>  8B4D F4       |/MOV ECX,DWORD PTR SS:[EBP-C]           ;  [EBP-C] is DestPos     // DECRYPTED & decompresssed PLAINTEXT FILENAME HASH LIST
  237. 00E1F2F3  |. |034D F8       ||ADD ECX,DWORD PTR SS:[EBP-8]           ;  [EBP-8] is the currentbyte thingy $FFFFFFFC
  238. 00E1F2F6  |. |8B55 F4       ||MOV EDX,DWORD PTR SS:[EBP-C]           ;  [EBP-C] is DestPos
  239. 00E1F2F9  |. |8A01          ||MOV AL,BYTE PTR DS:[ECX]
  240. 00E1F2FB  |. |8802          ||MOV BYTE PTR DS:[EDX],AL               ;  // Writes the new value into buffer $26
  241. 00E1F2FD  |. |8B4D F4       ||MOV ECX,DWORD PTR SS:[EBP-C]           ;  // Wrote $26 / Wrote $00
  242. 00E1F300  |. |83C1 01       ||ADD ECX,1                              ;  // INC(POS)
  243. 00E1F303  |. |894D F4       ||MOV DWORD PTR SS:[EBP-C],ECX
  244. 00E1F306  |. |8B55 FC       ||MOV EDX,DWORD PTR SS:[EBP-4]           ;  [EBP-4] is CurBit ?
  245. 00E1F309  |. |83EA 01       ||SUB EDX,1
  246. 00E1F30C  |. |8955 FC       ||MOV DWORD PTR SS:[EBP-4],EDX
  247. 00E1F30F  |.^\75 DF         |\JNZ SHORT 00E1F2F0                     ;  // JUMP if EDX not = 0    ed x is Count
  248.  
  249.  
  250.  
  251.     {============}
  252.     {    LOOP    } // @Label_00E1F2F0;
  253.     {============}
  254.     While EDX >= 0 Then
  255.     Begin
  256.       (* === OPTIMISED CODE === *) <<<<<<<<<<<<<<<<<<<<<< need to optimise this again memfwdcopy ?
  257.       [EDX] := Lo(DstPos + [EBP-8]);
  258.       EDX := DstPos;
  259.  
  260.       Inc(DstPos);
  261.       Dec([EBP-4]);
  262.     End;
  263.  
  264.     While EDX >= 0 Then
  265.     Begin
  266.       (* === OPTIMISED CODE === *) <<<<<<<<<<<<<<<<<<<<<< need to optimise this again memfwdcopy ?
  267.       ECX := DstPos + [EBP-8];
  268.       EDX := DstPos;
  269.       
  270.       [EDX] := Lo([ECX]);
  271.  
  272.       Inc(DstPos);
  273.       Dec([EBP-4]);
  274.     End;
  275.  
  276.  
  277.  
  278. =====================================
  279. [EBP+C] is the buf[0]  Compressed
  280. [EBP+8] is the buf2[0] Decompressed
  281. =====================================
  282.  
  283.  
  284.  
  285. 00E1F1E0  /$  55            PUSH EBP                                 ;  <<<<<<<<<<<<<<<<<<<<< PRS CDECOMPRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  286. 00E1F1E1  |.  8BEC          MOV EBP,ESP
  287. 00E1F1E3  |.  83EC 14       SUB ESP,14
  288. 00E1F1E6  |.  894D EC       MOV DWORD PTR SS:[EBP-14],ECX            ;  // pointer to pointer to Decompressed buffer (Eax points directly to decom buf)
  289. 00E1F1E9  |.  8B45 EC       MOV EAX,DWORD PTR SS:[EBP-14]            ;  // eax points  to value 1
  290. 00E1F1EC  |.  C700 01000000 MOV DWORD PTR DS:[EAX],1                 ;  // writes the value 1, to the structure
  291. 00E1F1F2  |.  8B4D EC       MOV ECX,DWORD PTR SS:[EBP-14]            ;  // address of the 1 above (same as eax)
  292. 00E1F1F5  |.  C741 04 00000>MOV DWORD PTR DS:[ECX+4],0               ;  // write the value 0 to next dword in structure
  293. 00E1F1FC  |.  8B55 EC       MOV EDX,DWORD PTR SS:[EBP-14]            ;  // edx becomes the address of the 1 above (now EAX, ECX & EDX all  point to that 1) 05CCFE54
  294. 00E1F1FF  |.  8B45 0C       'MOV EAX,DWORD PTR SS:[EBP+C]             ;  // pointer to a pointer_to_102044CD (compressed data buffer 0)         EAX = 102044CD
  295. 00E1F202  |.  8942 08       MOV DWORD PTR DS:[EDX+8],EAX             ;  // writes the address of comp data buffer to [EDX+8]
  296. 00E1F205  |.  8B4D 08       'MOV ECX,DWORD PTR SS:[EBP+8]             ;  // ECX became 102002f0 which is the empty decompressed data buffer
  297. 00E1F208  |.  894D F4       MOV DWORD PTR SS:[DstPos],ECX             ;  // write to 05CCFCF8 the address of decom data buf to [EBP-C] 05CCFCF8
  298. 00E1F20B  |.  C745 F8 00000>MOV DWORD PTR SS:[EBP-8],0               ;  // write 0   05CCFCFC
  299. 00E1F212  |.  C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0               ;  // write 0   05CCFD00
  300.  
  301. // Init Variables
  302. {[EAX]}    := // only 1 in the above code
  303. {[EBP+8]}  := // only 1 in the above code
  304. {[EBP-4]}  :=
  305. {[EBP-8]}  buf2 :=
  306. {[EBP+C]}  buf  := // only 1 in the above code
  307. {[EBP-14]} :=
  308. {[ECX+4]}  := // only 1 in the above code
  309. {[EDX+8]}  := // only 1 in the above code
  310.  
  311. // Main Code
  312. {[EAX+4]}  CurByte
  313. {[ECX+4]}  CurByte
  314. {[EDX+4]}  CurByte
  315.  
  316. {[EAX+8]}  SrcPos
  317. {[EAX+C]}  DstSize
  318.  
  319. {[EBP-4]}  CurByte
  320. {[EBP-8]}  CurByte
  321.  
  322. {[ECX+10]} := // ?
  323. ----------------------------------------------------------------------
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.