Here is reproduction of the damage formula with the ASM in /*comments*/
/*
00404470 83 EC 14 sub esp,14h
00404473 53 push ebx
00404474 8B 5C 24 1C mov ebx,dword ptr [esp+1Ch]
00404478 81 7B 14 18 1A 9C 01 cmp dword ptr [ebx+14h],19C1A18h
0040447F 56 push esi
00404480 C7 44 24 0C 00 00 00 00 mov dword ptr [esp+0Ch],0
00404488 C7 44 24 10 00 00 00 00 mov dword ptr [esp+10h],0
00404490 C7 44 24 14 00 00 00 00 mov dword ptr [esp+14h],0
00404498 C7 44 24 18 00 00 00 00 mov dword ptr [esp+18h],0
004044A0 C7 44 24 08 00 00 00 00 mov dword ptr [esp+8],0
004044A8 75 2F jne 004044D9
*/
float srcBase[2] = {0,0};
float dstBase[2] = {0,0};
if(*(DWORD*)(ebx+0x14)==0x19C1A18)
{
//always player, but src must be a weapon
//with the holder's stats in front instead???
//assert(src==player_src);
/*
004044AA 33 C0 xor eax,eax
004044AC 66 8B 03 mov ax,word ptr [ebx]
004044AF 33 C9 xor ecx,ecx
004044B1 66 8B 4B 02 mov cx,word ptr [ebx+2]
004044B5 89 44 24 20 mov dword ptr [esp+20h],eax
004044B9 DB 44 24 20 fild dword ptr [esp+20h]
004044BD 89 4C 24 20 mov dword ptr [esp+20h],ecx
004044C1 D8 0D BC 82 45 00 fmul dword ptr ds:[4582BCh]
004044C7 D9 5C 24 0C fstp dword ptr [esp+0Ch]
004044CB DB 44 24 20 fild dword ptr [esp+20h]
004044CF D8 0D BC 82 45 00 fmul dword ptr ds:[4582BCh]
004044D5 D9 5C 24 10 fstp dword ptr [esp+10h]
*/
srcBase[0] = float(*(WORD*)(ebx))/5;
srcBase[1] = float(*(WORD*)(ebx+2))/5;
}
/*
004044D9 8B 73 40 mov esi,dword ptr [ebx+40h]
004044DC 81 FE 18 1A 9C 01 cmp esi,19C1A18h
004044E2 75 3A jne 0040451E
*/
DWORD esi = *(DWORD*)(ebx+0x40);
if(esi==0x19C1A18)
{
assert(dst==player_dst); //19C1C24 is Strength. 19C1C28 Magic
/*
004044E4 8B 15 24 1C 9C 01 mov edx,dword ptr ds:[19C1C24h]
004044EA A1 28 1C 9C 01 mov eax,dword ptr ds:[019C1C28h]
004044EF 81 E2 FF FF 00 00 and edx,0FFFFh
004044F5 89 54 24 20 mov dword ptr [esp+20h],edx
004044F9 DB 44 24 20 fild dword ptr [esp+20h]
004044FD 25 FF FF 00 00 and eax,0FFFFh
00404502 89 44 24 20 mov dword ptr [esp+20h],eax
00404506 D8 0D BC 82 45 00 fmul dword ptr ds:[4582BCh]
0040450C D9 5C 24 14 fstp dword ptr [esp+14h]
00404510 DB 44 24 20 fild dword ptr [esp+20h]
00404514 D8 0D BC 82 45 00 fmul dword ptr ds:[4582BCh]
0040451A D9 5C 24 18 fstp dword ptr [esp+18h]
*/
dstBase[0] = float(SOM::L.pcstatus[SOM::PC::str])/5;
dstBase[1] = float(SOM::L.pcstatus[SOM::PC::mag])/5;
}
/*
0040451E 83 7B 3C 02 cmp dword ptr [ebx+3Ch],2
00404522 55 push ebp
00404523 57 push edi
00404524 75 6A jne 00404590
*/
float mystery = 0; //???
if(*(DWORD*)(ebx+0x3C)==2)
{
/*
00404526 33 C0 xor eax,eax
00404528 66 8B 46 20 mov ax,word ptr [esi+20h]
0040452C 8D 0C 40 lea ecx,[eax+eax*2]
0040452F 8D 0C 89 lea ecx,[ecx+ecx*4]
00404532 8D 14 88 lea edx,[eax+ecx*4]
00404535 8B 4E 68 mov ecx,dword ptr [esi+68h]
00404538 33 C0 xor eax,eax
0040453A 66 8B 04 D5 C8 A1 4D 00 mov ax,word ptr [edx*8+4DA1C8h]
00404542 8D 3C D5 C8 A1 4D 00 lea edi,[edx*8+4DA1C8h]
00404549 51 push ecx
0040454A 8B 2C 85 C8 67 4C 00 mov ebp,dword ptr [eax*4+4C67C8h]
00404551 E8 3A CF 03 00 call 00441490
00404556 8B 8E 40 02 00 00 mov ecx,dword ptr [esi+240h]
0040455C 83 C4 04 add esp,4
0040455F 83 F9 0C cmp ecx,0Ch
00404562 75 2C jne 00404590
*/
DWORD eax = *(WORD*)(esi+0x20), edx = eax+(eax*3*5*4);
DWORD ecx = *(DWORD*)(esi+0x68), edi = edx*8+0x4DA1C8;
eax = *(WORD*)(edi);
DWORD ebp = *(DWORD*)(eax*4+0x4C67C8);
DWORD before = *(DWORD*)(esi+0x240);
((VOID (__cdecl*)(DWORD))0x441490)(ecx);
DWORD after = *(DWORD*)(esi+0x240);
if(after==0) //cmp ecx,0Ch
{
/*
00404564 33 D2 xor edx,edx
00404566 8A 95 89 00 00 00 mov dl,byte ptr [ebp+89h]
0040456C 3B D0 cmp edx,eax
0040456E 7F 20 jg 00404590
00404570 33 C9 xor ecx,ecx
00404572 8A 8D 8A 00 00 00 mov cl,byte ptr [ebp+8Ah]
00404578 3B C1 cmp eax,ecx
0040457A 7F 14 jg 00404590
0040457C 33 D2 xor edx,edx
0040457E 8A 97 46 01 00 00 mov dl,byte ptr [edi+146h]
00404584 89 54 24 28 mov dword ptr [esp+28h],edx
00404588 DB 44 24 28 fild dword ptr [esp+28h]
0040458C D9 5C 24 10 fstp dword ptr [esp+10h]
*/
edx = *(BYTE*)(ebp+0x89);
if(edx<=eax) //cmp edx,eax
{
ecx = *(BYTE*)(ebp+0x8A);
if(eax<=ecx) //cmp eax,ecx
{
edx = *(BYTE*)(edi+0x146);
mystery = edx; assert(0); //???
}
}
}
}
/*
00404590 8B 44 24 30 mov eax,dword ptr [esp+30h]
00404594 8B 6C 24 2C mov ebp,dword ptr [esp+2Ch]
00404598 C7 00 00 00 00 00 mov dword ptr [eax],0
*/
DWORD ebp = dst; *out = 0;
for(esi=0;esi<8;esi++,ebp+=2)
{
/*
0040459E 33 F6 xor esi,esi
004045A0 33 C0 xor eax,eax
004045A2 8A 44 33 04 mov al,byte ptr [ebx+esi+4]
004045A6 84 C0 test al,al
004045A8 74 77 je 00404621
004045AA 0F BF 4D 00 movsx ecx,word ptr [ebp]
004045AE 25 FF 00 00 00 and eax,0FFh
004045B3 83 FE 03 cmp esi,3
004045B6 89 44 24 28 mov dword ptr [esp+28h],eax
004045BA DB 44 24 28 fild dword ptr [esp+28h]
004045BE 89 4C 24 28 mov dword ptr [esp+28h],ecx
004045C2 DB 44 24 28 fild dword ptr [esp+28h]
004045C6 D8 44 24 10 fadd dword ptr [esp+10h]
004045CA D9 5C 24 28 fstp dword ptr [esp+28h]
*/
float rating = *(BYTE*)(ebx+esi+4); if(!rating) continue;
//mystery: unsure what else fadd could be doing
float offset = *(SHORT*)(ebp); offset+=mystery;
/*
004045CE 7D 0E jge 004045DE
004045D0 D8 44 24 14 fadd dword ptr [esp+14h]
004045D4 D9 44 24 28 fld dword ptr [esp+28h]
004045D8 D8 44 24 1C fadd dword ptr [esp+1Ch]
004045DC EB 0C jmp 004045EA
004045DE D8 44 24 18 fadd dword ptr [esp+18h]
004045E2 D9 44 24 28 fld dword ptr [esp+28h]
004045E6 D8 44 24 20 fadd dword ptr [esp+20h]
*/
rating+=srcBase[esi>=3]; offset+=dstBase[esi>=3];
/*
004045EA D9 C1 fld st(1)
004045EC D8 D9 fcomp st(1)
004045EE DF E0 fnstsw ax
004045F0 F6 C4 41 test ah,41h
004045F3 75 0D jne 00404602
004045F5 D9 C1 fld st(1)
004045F7 D8 E1 fsub st,st(1)
004045F9 E8 3A B3 04 00 call 0044F938
004045FE 8B F8 mov edi,eax
00404600 EB 02 jmp 00404604
00404602 33 FF xor edi,edi
*/
LONG edi = rating-offset;
/*
00404604 D9 C1 fld st(1)
00404606 D8 CA fmul st,st(2)
00404608 D9 C9 fxch st(1)
0040460A DC C0 fadd st(0),st
0040460C DE F9 fdivp st(1),st
//not sure what this does but INF becomes 0//
0040460E E8 25 B3 04 00 call 0044F938
00404613 DD D8 fstp st(0)
00404615 03 F8 add edi,eax
*/
rating*=rating; offset+=offset;
if(offset) edi+=rating/offset;
/*
00404617 85 FF test edi,edi
00404619 7E 06 jle 00404621
0040461B 8B 44 24 30 mov eax,dword ptr [esp+30h]
0040461F 01 38 add dword ptr [eax],edi
00404621 46 inc esi
00404622 83 C5 02 add ebp,2
00404625 83 FE 08 cmp esi,8
00404628 0F 8C 72 FF FF FF jl 004045A0
*/
*out+=edi;
}
/*
0040462E 8B 43 14 mov eax,dword ptr [ebx+14h]
00404631 BF 18 1A 9C 01 mov edi,19C1A18h
00404636 3B C7 cmp eax,edi
00404638 75 1B jne 00404655
*/
DWORD edi = 0x19C1A18;
if(*(DWORD*)(ebx+0x14)==edi) //0x19C1A18
{
//player power gauge
/*
0040463A 8B 4C 24 30 mov ecx,dword ptr [esp+30h]
0040463E 33 D2 xor edx,edx
00404640 66 8B 53 0E mov dx,word ptr [ebx+0Eh]
00404644 B8 59 17 B7 D1 mov eax,0D1B71759h
00404649 0F AF 11 imul edx,dword ptr [ecx]
0040464C F7 E2 mul eax,edx
0040464E C1 EA 0C shr edx,0Ch
00404651 89 11 mov dword ptr [ecx],edx
00404653 EB 04 jmp 00404659
*/
LONG edx = *out**(WORD*)(ebx+0xE);
edx = (0xD1B71759ULL*edx)>>32; //mul edx
*out = edx>>0xC;
}
/*
00404655 8B 4C 24 30 mov ecx,dword ptr [esp+30h]
00404659 83 39 00 cmp dword ptr [ecx],0
0040465C 75 06 jne 00404664
0040465E C7 01 01 00 00 00 mov dword ptr [ecx],1
*/
if(*out==0) *out = 1;