cheat-engine/Cheat Engine/custombase85.pas
2019-12-19 17:49:30 +01:00

173 lines
4.5 KiB
ObjectPascal
Executable file

unit CustomBase85;
// uses 85 ascii characters which are better to use in XML ( no &'<"\> chars and no space char = more efficient )
//
// Base85ToBin doesn't support white spaces and line breaks (HexToBin doesn't support it too)
// implementation by mgr.inz.Player http://forum.cheatengine.org/viewtopic.php?t=560886 and http://pastebin.com/EUfGFpZ9
{$mode delphi}
interface
uses
Classes;
procedure BinToBase85(BinValue, outputStringBase85: PChar; BinBufSize: integer);
//
// example:
// getmem(outputstring, (BinarySize div 4) * 5 + 5 );
// BinToBase85(b,outputstring,BinarySize);
//
// it adds a 0 terminator to outputstring
function Base85ToBin(inputStringBase85, BinValue: PChar): integer;
//
// example:
// size:=length(inputstring);
// if (size mod 5) > 1 then
// BinarySize:= (size div 5) * 4 + (size mod 5) - 1
// else
// BinarySize:= (size div 5) * 4;
// getmem(b, BinarySize);
// Base85ToBin(inputstring, b);
//
// Base85ToBin doesn't support: white space between the characters, line breaks. (HexToBin doesn't support it too)
// Base85ToBin doesn't check for data corruption.
implementation
const
customBase85='0123456789'+
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'+
'abcdefghijklmnopqrstuvwxyz'+
'!#$%()*+,-./:;=?@[]^_{}';
procedure BinToBase85(BinValue, outputStringBase85: PChar; BinBufSize: integer);
var
i : integer;
a : dword;
begin
i:=0;
while i<binbufsize do
begin
//first byte ( from 4-tuple )
a:=pbyte(BinValue+i)^ shl 24;
inc(i);
if i<binbufsize then
begin
//second byte
a:=a or pbyte(BinValue+i)^ shl 16;
inc(i);
end;
if i<binbufsize then
begin
//third byte
a:=a or pbyte(BinValue+i)^ shl 8;
inc(i);
end;
if i<binbufsize then
begin
//fourth byte
a:=a or pbyte(BinValue+i)^;
inc(i);
end;
outputStringBase85[4]:= customBase85[a mod 85 + 1]; a:= a div 85;
outputStringBase85[3]:= customBase85[a mod 85 + 1]; a:= a div 85;
outputStringBase85[2]:= customBase85[a mod 85 + 1]; a:= a div 85;
outputStringBase85[1]:= customBase85[a mod 85 + 1]; a:= a div 85;
outputStringBase85[0]:= customBase85[a mod 85 + 1];
inc(outputStringBase85,5);
end;
//add zero terminator at right place
a:= (4 - (BinBufSize mod 4)) mod 4;
dec(outputStringBase85,a);
outputStringBase85[0]:=#0;
end;
function Base85ToBin(inputStringBase85, BinValue: PChar): integer;
var i,j: integer;
size : integer;
a : dword;
begin
size:=length(inputStringBase85);
i:=0;
j:=0;
while i<size do
begin
a:=( pos((inputStringBase85+i)^, customBase85) - 1 )*85*85*85*85;
inc(i);
if i<size then
begin
a:= a + ( pos((inputStringBase85+i)^, customBase85) - 1 )*85*85*85;
inc(i);
end;
if i<size then
begin
a:= a + ( pos((inputStringBase85+i)^, customBase85) - 1 )*85*85;
inc(i);
end;
if i<size then
begin
a:= a + ( pos((inputStringBase85+i)^, customBase85) - 1 )*85;
inc(i);
end;
if i<size then
begin
a:= a + ( pos((inputStringBase85+i)^, customBase85) - 1 );
inc(i);
// 5-tuple
binvalue[j+0]:= char( (a shr 24) and $ff );
binvalue[j+1]:= char( (a shr 16) and $ff );
binvalue[j+2]:= char( (a shr 8) and $ff );
binvalue[j+3]:= char( a and $ff );
inc(j,4);
end;
end;
case (size mod 5) of
2: begin // must be padded with three digits (last radix85 digit used)
a:= a + 84*85*85 + 84*85 + 84;
binvalue[j+0]:= char( (a shr 24) and $ff ); // last three bytes of the output are ignored
inc(j);
end;
3: begin // must be padded with two digits (last radix85 digit used)
a:= a + 84*85 + 84;
binvalue[j+0]:= char( (a shr 24) and $ff );
binvalue[j+1]:= char( (a shr 16) and $ff ); // last two bytes of the output are ignored
inc(j,2);
end;
4: begin // must be padded with one digit (last radix85 digit used)
a:= a + 84;
binvalue[j+0]:= char( (a shr 24) and $ff );
binvalue[j+1]:= char( (a shr 16) and $ff );
binvalue[j+2]:= char( (a shr 8) and $ff ); // last byte of the output is ignored
inc(j,3);
end;
end;
result:=j;
end;
end.