Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in UUID reading logic #7

Open
Flachdachs opened this issue Aug 11, 2018 · 0 comments
Open

Error in UUID reading logic #7

Flachdachs opened this issue Aug 11, 2018 · 0 comments

Comments

@Flachdachs
Copy link

Concerning GameObject.java line 322 ff.

public void readBinary(ArkArchive archive) {
    long highOfHigh = archive.getInt();
    long lowOfHigh = archive.getInt();
    long high = (highOfHigh << 32) + lowOfHigh;
    long highOfLow = archive.getInt();
    long lowOfLow = archive.getInt();
    long low = (highOfLow << 32) + lowOfLow;

    uuid = uuidCache.computeIfAbsent(new UUID(high, low), uuid -> uuid);

In case archive.getInt() returns a negative integer, then storing it as long the upper 32 bits are set to 1. This doesn't matter for both highOfHigh and highOfLow because these 1 bits are shifted away. But adding such a negative number in lowOfHigh or lowOfLow it gives a slighlty wrong result. Changing the type of lowOfHigh and lowOfLow to int isn't the solution, because they seem to be converted to long (with the upper 32 bits set to 1) before the addition takes place. The following code (same for the Low part) seems to do it right:

    long highOfHigh = archive.getInt();
    int lowOfHigh = archive.getInt();
    long high = (highOfHigh << 32) | (lowOfHigh & 0xffffffffL);

First getting rid of the upper 32 bits (which will be added because lowOfHigh is implicitly typecasted to long), then doing a bitwise OR, not an addition which was also semantically questionable.

For example if high is -1496803910 and low is -550970168 then the result is -6428723842525897528 but has to be -6428723838230930232. You can see it better in hex:
high A6C895BA‬,
low ‭DF28DCC8‬,
the result of the addition is ‭A6C895B9 DF28DCC8‬. Note the 9 instead of A at the end of the high part.


Another thing, the writeBinary() method writes the UUID in a different way than the readBinary() reads it:

      archive.putLong(uuid.getMostSignificantBits());
      archive.putLong(uuid.getLeastSignificantBits());

Because the file is written Little-Endian (and ArkArchive uses this byte order) the values from above are in the file as BA 95 C8 A6‬ - C8‬ DC 28 DF. It is read in two parts (marked by the dash) with the higher part first. But written as long the second and lower part is written first: C8‬ DC 28 DF - BA 95 C8 A6‬.

Additionally a GUID in the Microsoft world is written in a scrambled way. The GUID 00010203-0405-0607-0809-0A0B0C0D0E0F converted to a byte array (using C#) results into this order: 03 02 01 00 05 04 07 06 08 09 0A 0B 0C 0D 0E 0F. So I assume that reading it as four 32 bit parts isn't the right way at all. However it doesn't matter for the game if the GUIDs are treated a different way but equally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant