home *** CD-ROM | disk | FTP | other *** search
- {
- ************************************************************
- * SEGA`s PRS compression *
- * LZ77 compression with RLE emulation and extended matches *
- ************************************************************
- * *
- * *
- *
- *
- ************************************************************
- }
- unit SEGA_lz77;
-
- interface
-
- uses
- Windows, SysUtils;
-
- Function PSO2Dec(File_Size:integer):integer; // only function you should call
- Function GetByte_00E1F580():byte;
- Function GetBit_00E1F5D0():byte;
- //Function memfwdcpy(dest,src,count:integer):boolean;
-
-
- Var
- //-=-=--=-=-=-=-=-=-=-=-=-==-=-=-=
- // PRS GLOBAL VARIABLES
- //-=-=--=-=-=-=-=-=-=-=-=-==-=-=-=
- buf : Array of Byte; // SRC Compressed File
- buf2: Array of Byte; // DST Decompressed File
- CurBit, SrcPos : Integer;
- CurByte : Byte;
-
- BitCounter : Integer; // DWORD
-
- _EBP_m_4 : DWORD; // unsigned $FF = 255 (Definately not signed)
- _EBP_m_8 : DWORD; //ShortInt; // ShortInt $FF = -1 should be (definately not signed byte)
- _EBP_m_D, _EBP_m_E : Byte; // (Definately not signed)
- {******************************************************************************}
- implementation
-
- //{$R-}
-
- {
- uses
- Messages, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls, XPMan, Unit1;
- }
-
- Function PSO2Dec(File_Size:integer):integer; // Returns the Decompressed FileSize
- var
- _EAX : Byte; // could be BYTE
- DstPos, Count, Off : Integer;
- Begin
- {SET UP SOME VARIABLES}
- CurBit:=0; //
- SrcPos:=0; // Compressed_Data position (buf / ICE_DATA)
- DstPos:=0; // Decompressed_Data position (buf2)
-
- BitCounter := 1;
-
-
-
- While SrcPos < File_Size Do // 57328
- Begin
- {=========== 00E1F219 =============}
-
- // BitCounter := 1; // EDX is BitCounter
- // if BitCounter = 0 then BREAK; // File is Fully Decompressed
-
-
-
- (* === 00E1F226 === *) // ### LOOP ###
- Repeat
- _EAX := GetBit_00E1F5D0(); // EAX is CurBit always 1 or 0
- If _EAX = 1 Then // Repeat the loop
- Begin
- (* === 00E1F232 === *)
- Buf2[DstPos] := GetByte_00E1F580; // We Write 1 decompressed byte into buf2[srcpos]
- DstPos := DstPos + 1; // and inc the destination pos
- // 00E1F248 |.^ EB DC |\JMP SHORT 00E1F226
- End
- Until
- _EAX = 0;
-
-
-
-
-
- Begin // CurBit was 0 and we escaped the first loop BP & line 671 in Prs_Trace.txt
- (* === 00E1F24A === *)
- _EAX := GetBit_00E1F5D0();
-
- If _EAX = 1 then // jump at 00E1F254 WAS NOT taken
- Begin
- (* === 00E1F256 === *)
- _EBP_m_4 := GetByte_00E1F580(); // Call Returns CurByte $F8
- _EBP_m_8 := GetByte_00E1F580(); // Call Returns CurByte $FF
- _EAX := _EBP_m_8 OR _EBP_m_4; // can get these 3 lines onto 1 line CurByte := Curbyte or Curbit? FF and F8
-
-
-
- (* === 00E1F272 === *) // # dont think this is correct
- If _EAX = 0 Then // if true jump to 00E1F279
- begin
- BREAK; // <<<<<<<<<<<< SRCPOS was = to FileSize / File fully decompressed if off = 0 then break; // confusing comments
- end;
-
- (* === 00E1F279 === *)
- _EBP_m_8 := (_EBP_m_8 shl 5) + (_EBP_m_4 shr 3) - $2000; // LEA
- _EBP_m_4 := _EBP_m_4 AND 7; // count := off and 7;
-
-
- (* === 00E1F298 === *)
- If _EBP_m_4 <> 0 then // If Count <> 0 then ?????????? DUNNO WHAT MAKES THIS JUMP
- Begin
- (* === 00E1F29A === *) // JUMP @ 00E1F298 NOT TAKEN
- _EBP_m_4 := _EBP_m_4 + 2; // count := count + 2; or maybe Inc([EBP-4]); Count/[EBP-4] is not the same as BitCounter
- // 00E1F2A3 |. /EB 0E |JMP SHORT 00E1F2B3 ; Alpha-1_.00E1F2B3
- // 00E1F2B3 |> \EB 3B |JMP SHORT 00E1F2F0 ; Alpha-1_.00E1F2F0
- End
- ELSE
- BEGIN
- (* === 00E1F2A5 === *) // JUMP @ 00E1F298 WAS TAKEN
- _EBP_m_4 := GetByte_00E1F580() + $0A;
- // 00E1F2B3 |> EB 3B |JMP SHORT 00E1F2F0 ; Alpha-1_.00E1F2F0
- END;
- End
- ELSE // jump at 00E1F254 WAS taken
- Begin
- (* === 00E1F2B5 === *)
- _EBP_m_D := GetBit_00E1F5D0; // Returns $00
- _EBP_m_E := GetBit_00E1F5D0; // Returns $01
- _EBP_m_4 := (_EBP_m_D * 2) + (_EBP_m_E + 2); // EAX / _EBP_m_4 is count ? $00 * 2 + $01 + 2 = $03
-
- _EBP_m_8 := GetByte_00E1F580() - $100; // FFFFFFFC only need Byte not DWORD
- End;
-
- End;
-
-
- // Form1.mmo1.Lines.Add(IntToStr(DstPos) + #9 + IntToStr(_EBP_m_4) + #9 + IntToStr(_EBP_m_8));
-
-
- // if _EBP_m_4 (nibble_count) not = 0 then do this loop
- // Line 800 in Prs_Trace.txt
-
- (* === 00E1F2F0 === *)
- While _EBP_m_4 > 0 Do // WHAT IS EDX its a counter of some sort for half of a byte/nibble
- Begin
- // ECX := [EBP-C DstPos] + _EBP_m_8; // $FFFFFFFC
- // EDX := [EBP-C DstPos];
-
- // _EBP_m_8 needs to be signed for negative numbers
- Buf2[DstPos] := Buf2[DstPos + _EBP_m_8]; // [EDX] := AL; // Buf2[EBP-C DstPos] := Lo(ECX);
-
- Inc(DstPos); // [EBP-C DstPos] := [EBP-C DstPos] + 1;
- _EBP_m_4 := _EBP_m_4 - 1; // count was 3 becomes 2 // _EBP_m_4 := _EBP_m_4 - 1;
- End;
-
- // GO BACK TO THE START
- End;
- RESULT := DstPos; // [EBP-C DstPos]
-
- {
- NOTE:
- [Tests with CRC ICE debugger]
- 57, 328 DstPos & File_Size
- 40, 467 SrcPos
-
- [Ice Header]
- 57, 328 Decompressed_Size
- 40, 467 Compressed_Size
- }
- End;
-
- Function GetBit_00E1F5D0(): BYTE; // returns the current bit
- var
- EDX : DWORD; // Pointer to BitCounter or Pointer to CurByte (This is the calling Parameter ?)
- begin
- Dec(BitCounter); // [EDX] Points to BitCounter // moving this to end
-
- (* === OPTIMISED CODE === *)
- if BitCounter = 0 then
- begin
- CurByte := GetByte_00E1F580(); // CurByte:=buf[SrcPos]; RETURNS = $31
- BitCounter := 8;
- end;
-
- RESULT := CurByte and 1; // result := CurByte and 1; = 1 BUG it should be $7F not $99 see line 132 of prs_Trace.txt
- CurByte := CurByte shr 1; // CurByte := CurByte div 2; = 127
-
- // [ECX+4] := DecompressedByte; // $7F (127)
- end;
-
- Function GetByte_00E1F580(): BYTE;
- begin
- (* === OPTIMISED CODE === *)
-
- //#### NO FUCKING IDEA DONT THINK ITS CORRECT ####
- (* ==== 00E1F595 ==== *)
- if SrcPos = Length(buf2) then // if SrcPos = DecSize/[EAX+C] then //1020E2DE - 102002f0 = DFEE (should be Grp_x_XOR_KEY / decompressed filesize)
- begin
- SrcPos := $05CCFD2C; // EDX,DWORD PTR DS:[ECX+C] //CONSTANT VALUE [ECX+10] is always $05CCFD2C; // just points to a block of $95 bytes
- end;
-
- (* ==== 00E1F5A3 ==== *)
- RESULT := Buf[SrcPos] xor $95; // [EBP-8] becomes 1 byte from Compressed data buffer @ SrcPos
- INC(SrcPos); // inc SrcPos
-
- // [EBP-8] := CompressedByte; // $63 (which is $F6 xor $95)
- end;
-
- {
- Function memfwdcpy(dest,src,count:integer):boolean; // Writes DeCompressed data into buf2
- var x:integer;
- begin
- for x:=0 to count-1 do
- buf2[dest+x] := buf2[src+x];
- result:=false;
- }
- end.
-
-
-
-
-
-
-
-
-
-
-
- // IGNORE THIS IS JUST NOTES
-
- [memfwdcpy ?]
- 00E1F2F0 |> 8B4D F4 |/MOV ECX,DWORD PTR SS:[EBP-C] ; [EBP-C] is DestPos // DECRYPTED & decompresssed PLAINTEXT FILENAME HASH LIST
- 00E1F2F3 |. |034D F8 ||ADD ECX,DWORD PTR SS:[EBP-8] ; [EBP-8] is the currentbyte thingy $FFFFFFFC
- 00E1F2F6 |. |8B55 F4 ||MOV EDX,DWORD PTR SS:[EBP-C] ; [EBP-C] is DestPos
- 00E1F2F9 |. |8A01 ||MOV AL,BYTE PTR DS:[ECX]
- 00E1F2FB |. |8802 ||MOV BYTE PTR DS:[EDX],AL ; // Writes the new value into buffer $26
- 00E1F2FD |. |8B4D F4 ||MOV ECX,DWORD PTR SS:[EBP-C] ; // Wrote $26 / Wrote $00
- 00E1F300 |. |83C1 01 ||ADD ECX,1 ; // INC(POS)
- 00E1F303 |. |894D F4 ||MOV DWORD PTR SS:[EBP-C],ECX
- 00E1F306 |. |8B55 FC ||MOV EDX,DWORD PTR SS:[EBP-4] ; [EBP-4] is CurBit ?
- 00E1F309 |. |83EA 01 ||SUB EDX,1
- 00E1F30C |. |8955 FC ||MOV DWORD PTR SS:[EBP-4],EDX
- 00E1F30F |.^\75 DF |\JNZ SHORT 00E1F2F0 ; // JUMP if EDX not = 0 ed x is Count
-
-
-
- {============}
- { LOOP } // @Label_00E1F2F0;
- {============}
- While EDX >= 0 Then
- Begin
- (* === OPTIMISED CODE === *) <<<<<<<<<<<<<<<<<<<<<< need to optimise this again memfwdcopy ?
- [EDX] := Lo(DstPos + [EBP-8]);
- EDX := DstPos;
-
- Inc(DstPos);
- Dec([EBP-4]);
- End;
-
- While EDX >= 0 Then
- Begin
- (* === OPTIMISED CODE === *) <<<<<<<<<<<<<<<<<<<<<< need to optimise this again memfwdcopy ?
- ECX := DstPos + [EBP-8];
- EDX := DstPos;
-
- [EDX] := Lo([ECX]);
-
- Inc(DstPos);
- Dec([EBP-4]);
- End;
-
-
-
- =====================================
- [EBP+C] is the buf[0] Compressed
- [EBP+8] is the buf2[0] Decompressed
- =====================================
-
-
-
- 00E1F1E0 /$ 55 PUSH EBP ; <<<<<<<<<<<<<<<<<<<<< PRS CDECOMPRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- 00E1F1E1 |. 8BEC MOV EBP,ESP
- 00E1F1E3 |. 83EC 14 SUB ESP,14
- 00E1F1E6 |. 894D EC MOV DWORD PTR SS:[EBP-14],ECX ; // pointer to pointer to Decompressed buffer (Eax points directly to decom buf)
- 00E1F1E9 |. 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14] ; // eax points to value 1
- 00E1F1EC |. C700 01000000 MOV DWORD PTR DS:[EAX],1 ; // writes the value 1, to the structure
- 00E1F1F2 |. 8B4D EC MOV ECX,DWORD PTR SS:[EBP-14] ; // address of the 1 above (same as eax)
- 00E1F1F5 |. C741 04 00000>MOV DWORD PTR DS:[ECX+4],0 ; // write the value 0 to next dword in structure
- 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
- 00E1F1FF |. 8B45 0C 'MOV EAX,DWORD PTR SS:[EBP+C] ; // pointer to a pointer_to_102044CD (compressed data buffer 0) EAX = 102044CD
- 00E1F202 |. 8942 08 MOV DWORD PTR DS:[EDX+8],EAX ; // writes the address of comp data buffer to [EDX+8]
- 00E1F205 |. 8B4D 08 'MOV ECX,DWORD PTR SS:[EBP+8] ; // ECX became 102002f0 which is the empty decompressed data buffer
- 00E1F208 |. 894D F4 MOV DWORD PTR SS:[DstPos],ECX ; // write to 05CCFCF8 the address of decom data buf to [EBP-C] 05CCFCF8
- 00E1F20B |. C745 F8 00000>MOV DWORD PTR SS:[EBP-8],0 ; // write 0 05CCFCFC
- 00E1F212 |. C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0 ; // write 0 05CCFD00
-
- // Init Variables
- {[EAX]} := // only 1 in the above code
- {[EBP+8]} := // only 1 in the above code
- {[EBP-4]} :=
- {[EBP-8]} buf2 :=
- {[EBP+C]} buf := // only 1 in the above code
- {[EBP-14]} :=
- {[ECX+4]} := // only 1 in the above code
- {[EDX+8]} := // only 1 in the above code
-
- // Main Code
- {[EAX+4]} CurByte
- {[ECX+4]} CurByte
- {[EDX+4]} CurByte
-
- {[EAX+8]} SrcPos
- {[EAX+C]} DstSize
-
- {[EBP-4]} CurByte
- {[EBP-8]} CurByte
-
- {[ECX+10]} := // ?
- ----------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-