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

Issue/fix: IRandomBetween() not working properly on Win32/x86 #355

Open
PierreMarieBaty opened this issue Dec 22, 2023 · 2 comments
Open

Comments

@PierreMarieBaty
Copy link

PierreMarieBaty commented Dec 22, 2023

When compiling on Win32/x86, I couldn't get the new game video, which should be 50% chance either GARAGE1.SMK or GARAGE2.SMK to play the first one.

After investigation it turned out the culprit was this function in src/DETHRACE/common/utility.c:

// IDA: int __usercall IRandomBetween@<EAX>(int pA@<EAX>, int pB@<EDX>)
int IRandomBetween(int pA, int pB) {
    int num;
    char s[32];

    num = rand();
#if RAND_MAX == 0x7fff
    //  If RAND_MAX == 0x7fff, then `num` can be seen as a fixed point number with 15 fractional and 17 integral bits
    return pA + ((num * (pB + 1 - pA)) >> 15);
#else
    //  If RAND_MAX != 0x7fff, then use floating numbers (alternative is using modulo)
    return pA + (int)((pB + 1 - pA) * (num / ((float)RAND_MAX + 1)));
#endif
}

I changed it to the following so that it falls back on the floating-point based code when sizeof(int) is 32 bit:

// IDA: int __usercall IRandomBetween@<EAX>(int pA@<EAX>, int pB@<EDX>)
int IRandomBetween(int pA, int pB) {
    int num;
    char s[32];

    num = rand();
#if (INT_MAX > 0x7fffffff) && (RAND_MAX == 0x7fff) // Pierre-Marie Baty -- looks like this hack doesn't work when sizeof(int) == 4 (e.g. on Windows)
    //  If RAND_MAX == 0x7fff, then `num` can be seen as a fixed point number with 15 fractional and 17 integral bits
    return pA + ((num * (pB + 1 - pA)) >> 15);
#else
    //  If RAND_MAX != 0x7fff, then use floating numbers (alternative is using modulo)
    return pA + (int)((pB + 1 - pA) * (num / ((float)RAND_MAX + 1)));
#endif
}

I haven't tested when compiling for Win32/x64 though, but considering Windows is the only well-known x64 platform where sizeof(int) is 4, it should be the same.

@madebr
Copy link
Collaborator

madebr commented Jan 6, 2024

Looks like IRandomBetween is a bit more complicated.
Does the following work for you on Windows?

int IRandomBetween(int pA, int pB) {
    long long int a = rand() * (pB + 1 - pA);
    a &= 0x7fffffffffffffff;
    return pA + (a  >> 15);
}

@PierreMarieBaty
Copy link
Author

PierreMarieBaty commented Jan 6, 2024 via email

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

2 participants