afritz1/OpenTESArena

Incorrect .exe data offsets

Closed this issue · 6 comments

I've noticed that there seem to be some mistakes in the locations for .exe data in the aExeStrings.txt file and the acdExeStrings.txt file.

aExeStrings.txt contains:

MaleMainRaceAttributes=0x35FC3
FemaleMainRaceAttributes=0x35FCB
GuardAttributes=0x35FD3

but I've found that this GuardAttributes value actually points at the data for male Redguards. It should be GuardAttributes=0x36043. Same issue in acdExeStrings.txt: the value there reads GuardAttributes=0x361D3, but it should be GuardAttributes=0x36243.

Also, aExeStrings.txt contains CreatureAttributes=0x35FDC, but this points into the attribute array for the Redguard female (starting at index 1, not 0, so it's also off by 1 in that regard). It should be CreatureAttributes=0x3608B‬. For acdExeStrings.txt it should be CreatureAttributes=0x3628B‬.

The data in that area of the executable looks like this (from the decompressed A.EXE file (1.06)), starting from 0x39CF3 (0x35FC3 in aExeStrings.txt (a difference of 0x3D30)).

            MaleBretonAttributes
                 4d 80 80        db[8]
                 66 66 4d 
                 66 66
            FemaleBretonAttributes
                 4d 80 80        db[8]
                 66 66 4d 
                 66 66
            MaleRedguardAttributes (`GuardAttributes` currently points here)
                 66 4d 4d        db[8]
                 66 80 80 
                 66 66
            FemaleRedguardAttributes (`CreatureAttributes` currently points here, at index 1)
                 4d 4d 4d        db[8]
                 80 80 80 
                 66 66
            MaleNordAttributes
                 80 4d 4d        db[8]
                 4d 66 80 
                 66 66
            FemaleNordAttributes
                 66 4d 66        db[8]
                 66 66 66 
                 66 80
            MaleDarkElfAttributes
                 80 80 4d        db[8]
                 80 80 66 
                 66 66
            FemaleDarkElfAttributes
                 66 80 4d        db[8]
                 66 66 66 
                 66 66
            MaleHighElfAttributes
                 4d 80 80        db[8]
                 66 66 4d 
                 66 66
            FemaleHighElfAttributes
                 4d 80 66        db[8]
                 66 66 4d 
                 80 66
            MaleWoodElfAttributes
                 66 66 66        db[8]
                 80 80 4d 
                 66 4d
            FemaleWoodElfAttributes
                 66 66 66        db[8]
                 66 66 66 
                 66 66
            MaleKhajiitAttributes
                 66 66 4d        db[8]
                 80 66 4d 
                 66 80
            FemaleKhajiitAttributes
                 66 66 4d        db[8]
                 66 80 4d 
                 66 80
            MaleArgonianAttributes
                 66 66 66        db[8]
                 80 80 4d 
                 66 4d
            FemaleArgonianAttributes
                 66 66 66        db[8]
                 66 66 66 
                 66 66
            GuardAttributes0 (I'm suggesting pointing `GuardAttributes` here)
                 b3 80 80        db[8]
                 99 99 b3 
                 80 80
            GuardAttributes1
                 cc 80 80        db[8]
                 b3 b3 cc 
                 80 80
            GuardAttributes2
                 e6 80 80        db[8]
                 cc cc e6 
                 80 80
            GuardAttributes3
                 99 80 80        db[8]
                 80 80 99 
                 80 80
            GuardAttributes4
                 b3 80 80        db[8]
                 99 99 b3 
                 80 80
            GuardAttributes5
                 cc 80 80        db[8]
                 b3 b3 cc 
                 80 80
            GuardAttributes6
                 80 80 80        db[8]
                 66 66 80 
                 80 80
            GuardAttributes7
                 99 80 80        db[8]
                 80 80 99 
                 80 80
            GuardAttributes8
                 b3 80 80        db[8]
                 99 99 b3 
                 80 80
            RatAttributes (I'm suggesting pointing `CreatureAttributes` here)
                 33 19 19        db[8]
                 5a 4c 4c 
                 66 80
(Continues with GoblinAttributes, etc.)

Thanks @Allofich. I fixed the attribute offsets and printed the values after converting them to 0-100. These look correct to me, so I'll commit the changes.

Rat: 20, 10, 10, 35, 30, 30, 40, 50
Goblin: 30, 20, 30, 40, 30, 30, 30, 50
Lizard Man: 70, 30, 40, 60, 70, 60, 30, 50
...
Vampire: 80, 33, 90, 95, 70, 90, 80, 70
Lich: 90, 90, 90, 90, 80, 90, 20, 80
Jagar Tharn: 60, 100, 90, 95, 85, 90, 60, 75
Male 0: 30, 50, 50, 40, 40, 30, 40, 40
Male 1: 30, 50, 50, 40, 40, 30, 40, 40
...
Male 6: 50, 50, 30, 50, 50, 40, 40, 40
Male 7: 40, 50, 30, 40, 40, 40, 40, 40
Female 0: 30, 50, 50, 40, 40, 30, 40, 40
Female 1: 40, 30, 30, 40, 50, 50, 40, 40
...
Female 6: 40, 50, 30, 40, 40, 40, 40, 40
Female 7: 30, 50, 50, 40, 40, 30, 40, 40
Guard 0: 70, 50, 50, 60, 60, 70, 50, 50
Guard 1: 80, 50, 50, 70, 70, 80, 50, 50
...
Guard 7: 60, 50, 50, 50, 50, 60, 50, 50
Guard 8: 70, 50, 50, 60, 60, 70, 50, 50

It seems the formula for conversion is

uint8_t oldValue = ...;
double percent = (double)oldValue / 256.0;
int newValue = (int)round(percent * 100.0);

Edit: actually I think I messed up, the Redguard ones don't seem to match. Maybe I should've left them in hex format :/

@afritz1, if those values in your comment above are what are being loaded then the loading function probably needs adjustment. It looks like for male and female attributes you started at MaleMainRaceAttributes and FemaleMainRaceAttributes, respectively, and then loaded in the next 8 contiguous byte arrays, but if you want to load all of them you should be reading an array, then skipping the next array (because it is for the other gender), then reading the next, then skipping the next, etc. because they go in the pattern Male, Female, Male, Female.

The original game gets the position for the needed array like:

if male
arrayPosition = MaleMainRaceAttributes + 16 bytes * RaceID

if female
arrayPosition = FemaleMainRaceAttributes + 16 bytes * RaceID

I will fix it now.

These are my new results:

  Male 0: 4d, 80, 80, 66, 66, 4d, 66, 66
Female 0: 4d, 80, 80, 66, 66, 4d, 66, 66

  Male 1: 66, 4d, 4d, 66, 80, 80, 66, 66
Female 1: 4d, 4d, 4d, 80, 80, 80, 66, 66

  Male 2: 80, 4d, 4d, 4d, 66, 80, 66, 66
Female 2: 66, 4d, 66, 66, 66, 66, 66, 80

  Male 3: 80, 80, 4d, 80, 80, 66, 66, 66
Female 3: 66, 80, 4d, 66, 66, 66, 66, 66

  Male 4: 4d, 80, 80, 66, 66, 4d, 66, 66
Female 4: 4d, 80, 66, 66, 66, 4d, 80, 66

  Male 5: 66, 66, 66, 80, 80, 4d, 66, 4d
Female 5: 66, 66, 66, 66, 66, 66, 66, 66

  Male 6: 66, 66, 4d, 80, 66, 4d, 66, 80
Female 6: 66, 66, 4d, 66, 80, 4d, 66, 80

  Male 7: 66, 66, 66, 80, 80, 4d, 66, 4d
Female 7: 66, 66, 66, 66, 66, 66, 66, 66

Looks correct!