SetClassOfClient's class parameter is an int: both callers pass a whole EDX
nClass is declared uint8_t (DL), but the callers hand over a full 32-bit value: PLAYERSAVE_ParseHeaderAndCreateUnit widens the class byte once and uses the same EDX both as the argument and as its int class local (0056a17a MOVZX EDX,AL; 0056a17d MOV ECX,EDI; 0056a17f MOV [EBP-0xc],EDX; 0056a182 CALL), and _oldSaveGameLoadingPart passes a whole register (005329f6 MOV EDX,EDI; 005329fa CALL). With a byte parameter VC8 loads only DL at the call. The body storing the low byte (00538620 MOV byte ptr [ECX+0x8],DL) is what VC8 makes of an int stored into a byte field. Recompiled with VC8 SP1 (oracle, tree 3dba660): PLAYERSAVE_ParseHeaderAndCreateUnit goes from 0.814 to 0.917; SetClassOfClient itself is unchanged; no function lost.
Changes 1, applied together
Set prototype
win 0x00538620signaturevoid SetClassOfClient(D2ClientStrc * pClient, uint8_t nClass)→void SetClassOfClient(D2ClientStrc * pClient, int nClass)convention__fastcall