OP_ShroudUnknown3=0x1573
This one has been most problematic to reverse engineer. It's almost as if the server needs to be directly aware of some object pointer offsets found in eqgame.exe. One thing I found by investigating this was that the value of UniqueID in the above Opcodes cannot be random.
Code:
.text:004FF9C9 sub_4FF9C9 proc near ; CODE XREF: sub_4244BA+Ap
.text:004FF9C9 ; sub_42EC50+Dp ...
.text:004FF9C9
.text:004FF9C9 arg_0= dword ptr 8
.text:004FF9C9
.text:004FF9C9 push esi
.text:004FF9CA mov esi, [esp+arg_0]
.text:004FF9CE mov eax, esi
.text:004FF9D0 xor edx, edx
.text:004FF9D2 div dword ptr [ecx+4]
.text:004FF9D5 mov eax, [ecx]
.text:004FF9D7 mov eax, [eax+edx*4]
.text:004FF9DA jmp short loc_4FF9E4
.text:004FF9DC ; ---------------------------------------------------------------------------
.text:004FF9DC
.text:004FF9DC loc_4FF9DC: ; CODE XREF: sub_4FF9C9+1Dj
.text:004FF9DC cmp [eax+4], esi
.text:004FF9DF jz short loc_4FF9E8
.text:004FF9E1 mov eax, [eax+8]
.text:004FF9E4
.text:004FF9E4 loc_4FF9E4: ; CODE XREF: sub_4FF9C9+11j
.text:004FF9E4 test eax, eax
.text:004FF9E6 jnz short loc_4FF9DC
.text:004FF9E8
.text:004FF9E8 loc_4FF9E8: ; CODE XREF: sub_4FF9C9+16j
.text:004FF9E8 pop esi
.text:004FF9E9 retn 4
.text:004FF9E9 sub_4FF9C9 endp
This subroutine gets used frequently. For the opcode in question, the instruction at 004FF9D2 is problematic:
div dword ptr [ecx+4]
This essentially takes our UniqueID, divides it by 0x17 and only uses the remainder. (UniqueID % 23) It then multiplies by 4 (it's probably doing pointer math), and offsets a pointer by that amount and grabs the value at that new location:
.text:004FF9D7 mov eax, [eax+edx*4]
That value must be non-zero:
.text:004FF9E4 test eax, eax
.text:004FF9E6 jnz short loc_4FF9DC
Then, we assume that value is yet another pointer and compare the second uint32 at the pointer's destination with our original UniqueID:
.text:004FF9DC cmp [eax+4], esi
If we don't find it, we increment our pointer by two unit32s and try the loop back to the non-zero check and do it again.
.text:004FF9DF jz short loc_4FF9E8
.text:004FF9E1 mov eax, [eax+8]
All of this means that the UniqueID is much more than just a UniqueID. It's also an offset for a pointer that expects to find the same offset value somewhere in a structure at its destination.
Its giving me a headache.
Now, I did find only one such possible UniqueID that would satisfy this algorithm. The problem is, that UniqueID was 0x8800001F. As mentioned in a prior post, this value makes an invalid UniqueID because this is < 0 and becomes 0x77FFFFE1 before being saved by the client. :(
Best I can tell, my real problem may be that something hasn't yet been set in the object I'm referencing here. (Faced similar problems getting the other opcodes to work--if the shroud selection window weren't open when the opcode was sent, a subroutine would return a 0 result because an object lookup would fail.)
At this time, I'm not sure what else I need to send to get that object reference to be valid.
Alas, I'll keep hacking away at it.
One last note about this one: the contents of the packet aren't even referenced by this point, but this subroutine's failure cascades into the entire packet being discarded. The UniqueID in this problem is referring to the UniqueID of the currently highlighted template in the shroud selection window. The window must be open for this opcode to even get this far, however. Of that I am certain. So, too, am I certain that OP_ShroudUnknown1=0x6d32 is also handled by this window.