UScript implementation of reading CompactIndex

Discussions about Coding and Scripting
Post Reply
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

UScript implementation of reading CompactIndex

Post by Barbie »

If you have once read about the Unreal package format, you will have noticed that INDEX data type, the compact representation of integers: small absolute values -64..+64 are stored in one byte only, bigger integers need up to 5 bytes, depending on their distance to zero.

Is there an UScript implementation for reading such from a stream? ("stream" is an array of byte in this case.)
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: UScript implementation of reading CompactIndex

Post by Higor »

Are you serializing through XC_Core?
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: UScript implementation of reading CompactIndex

Post by Barbie »

Higor wrote:Are you serializing through XC_Core?
No, it is intended for a mutator that should be able to run on a default installation.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: UScript implementation of reading CompactIndex

Post by Chris »

Have a look at the serializer.

Code: Select all

//
// FCompactIndex serializer.
//
FArchive& operator<<( FArchive& Ar, FCompactIndex& I )
{
       	INT Original = I.Value;
	DWORD V = Abs(I.Value);
       	BYTE B0 = ((I.Value>=0) ? 0 : 0x80) + ((V < 0x40) ? V : ((V & 0x3f)+0x40));
        I.Value = 0;
        Ar << B0;
        if( B0 & 0x40 )
        {
            V >>= 6;
            BYTE B1 = (V < 0x80) ? V : ((V & 0x7f)+0x80);
            Ar << B1;
            if( B1 & 0x80 )
            {
                V >>= 7;
                BYTE B2 = (V < 0x80) ? V : ((V & 0x7f)+0x80);
                Ar << B2;
                if( B2 & 0x80 )
                {
                    V >>= 7;
                    BYTE B3 = (V < 0x80) ? V : ((V & 0x7f)+0x80);
                    Ar << B3;
                    if( B3 & 0x80 )
                    {
                        V >>= 7;
                        BYTE B4 = V;
                        Ar << B4;
                        I.Value = B4;
                    }
                    I.Value = (I.Value << 7) + (B3 & 0x7f);
                }
                I.Value = (I.Value << 7) + (B2 & 0x7f);
            }
            I.Value = (I.Value << 7) + (B1 & 0x7f);
        }
        I.Value = (I.Value << 6) + (B0 & 0x3f);
        if( B0 & 0x80 )
            I.Value = -I.Value;
        if( Ar.IsSaving() && I.Value!=Original )
            appErrorf("Mismatch: %08X %08X",I.Value,Original);
    }
    return Ar;
}
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: UScript implementation of reading CompactIndex

Post by Barbie »

Thanks for that implementation, but it does not look like UScript ;o). The Wiki page I mentioned in first post has also an C# implementation, and additionally I got one in Delphi Pascal.
To save the time for translating and testing I asked for an existing (hopefully tested) UScript implementation.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: UScript implementation of reading CompactIndex

Post by Chris »

Barbie wrote:Thanks for that implementation, but it does not look like UScript ;o). The Wiki page I mentioned in first post has also an C# implementation, and additionally I got one in Delphi Pascal.
To save the time for translating and testing I asked for an existing (hopefully tested) UScript implementation.
May I ask what the use for this is exactly? That C# version would take a few minutes to port to UScript since the syntax is similar and the necessary bitwise operators are all available. Since the bitwise operators only exist for Integers you will need to work with Integers instead of bytes.

Code: Select all

final function int ReadCompactInteger()
{
	local int output;
	local bool signed;
        local int bytes[4]; //For some reason Epic decided not to implement bitwise ops for bytes. Fill with whatever bytes you want to decode here.
        local int i;
	for(i = 0; i < 5; i++)
	{
		// First byte
		if(i == 0)
		{
			// Bit: X0000000
			if((bytes[i] & 0x80) > 0)
				signed = true;
			// Bits: 00XXXXXX
			output = (output | (bytes[i] & 0x3F));
			// Bit: 0X000000
			if((bytes[i] & 0x40) == 0)
				break;
		}
		// Last byte
		else if(i == 4)
		{
			// Bits: 000XXXXX -- the 0 bits are ignored
			// (hits the 32 bit boundary)
			output = (output | (bytes[i] & 0x1F) << (/*6 + (3 * 7) */ 27)); //Chris: If you need the runtime to do this math for you then you should not be coding at all.
		}
		// Middle bytes
		else
		{
			// Bits: 0XXXXXXX
			output = (output | (bytes[i] & 0x7F) << (6 + ((i - 1) * 7)));
			// Bit: X0000000
			if((bytes[i] & 0x80) == 0)
				break;
		}
	}
	// multiply by negative one here, since the first 6+ bits could be 0
	if(signed)
		output *= -1;
	return output;
}
Atleast you can do the testing yourself.
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: UScript implementation of reading CompactIndex

Post by Barbie »

Thanks for translating into UScript. :tu:
Chris wrote:May I ask what the use for this is exactly?
Of course. I'm still having a Map Patcher Mutator in mind (but on low priority). I'm going to add the description there.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: UScript implementation of reading CompactIndex

Post by Chris »

Barbie wrote:Thanks for translating into UScript. :tu:
Chris wrote:May I ask what the use for this is exactly?
Of course. I'm still having a Map Patcher Mutator in mind (but on low priority). I'm going to add the description there.
I'm kinda curious as to why you need to explicitly decode compact indices in UScript. You probably already know that the compacts are only really relevant when we're dealing with archieves, are you planning to do some file reading within UScript?
Post Reply