Info
a.- What I'm trying to do is call this function apparently equal to "loadSprite" from delphi made dll, but I have didn't found the parameters of this function properly.
b.- All things here I did are based on tibia client V. 8.5.
c.- You are free to ask, specially if you want to know what are the addresses in other versions of tibia.
(5/1/2011)
Hello, i've found a function that equals to loadsprite function, it has arguments but i did found nothing, in ollydbg it shows, the address of the function is $004A6E20 (8.5), can be handled from delphi as:
[code=delphi]
type
_loadsprite = procedure; cdecl;
const
loadsprite: _loadsprite = ptr($004A6E20);
[/code]
i used cdecl because when this procedure is called by tibia, the stack isn't touched!
looking into this function i found it takes pointer to free memory for writing sprite data (rgb 24 bit) and sprite number as defined in tibia.spr, i assumed surface is not required for loading sprites :P
when i breakpoint the function beforecall the top of stack says:
Code:
REGISTERS:
EAX 08E10E30 -> same as dword ptr ds:[0012DCB8]
ECX 09F7A820 -> pointer of sprite data
EDX 000039C6 -> ?
EBX 08E2DC60 -> ????
ESP 0012DCB4 -> stack
EBP 0012DF30 -> ??
ESI 00000B8E -> same as dword ptr ds:[12DCBC] at this moment
EDI 000000FF -> itemid, this is replaced by dword ptr ds:[eax+8]
EIP 005AF930 labtibia.005AF930
STACK:
0012DCB4 000000FF -> itemid
0012DCB8 09F7A820 -> pointer where sprite data will be written
0012DCBC 00000B8E -> ?
0012DCC0 000000FF -> itemid (?), yes, it repeats for each id
0012DCC4 09344530 -> unknown pointer
0012DCC8 00000502 -> ?
0012DCCC 00000000 -> nothing?
0012DCD0 7C96F8CC RETURN to ntdll.7C96F8CC from ntdll.7C90E906
(7/1/2011)
I found yesterday the address of spriteCount (total number of sprites) and pointer to transparentcolor (this is a variable that stores some rgb data of the transparent color assuming this is 24 bit nor 32, so there can't be an alpha channel with value 0), well, spriteCount is a global variable into tibia in dword ptr ds:[0063D164], and transparentcolor can be obtained from a pointer variable, after the function is called the pointer is found in dword ptr ds:[esp-40]
Extrainfo: Trasparent color isn't constant!!, I've found cases when it is rgb($F8,$F8,$F0) and other times it is rgb($00,$00,$FF) D:
[code=delphi]
type
pixel24 = record
r,g,b: byte; //red green blue, 3 bytes per pixel
end;
pspritedata = ^spritedata;
spritedata = array [0..32*32-1] of pixel24;
PLongword = ^longword;
PtColor = ^TtColor;
TtColor = record //type transparent color
unknownpointer: pointer; //i didn't remove this because can be useful
r,g,b: longword; // yes, these are longword xD
end;
const
spriteCount: PLongword = ptr($0063D164); //this is not what i'm looking for, but it is useful too
[/code]
What I did was put a jmp to some monitor code created in blank memory of code section and scanning results from delphi...
If someone wants a tutorial of how monitor and get resulting parametersi can do one
Code:
005AF930 /> \E8 EB74EFFF CALL labtibia.004A6E20 : call internal function of tibia
005AF935 |. 60 PUSHAD : save the registers x_x
005AF936 |. 833D 0CB07A00>CMP DWORD PTR DS:[7AB00C],0 : cmp ptr where is address of some function in my dll, i added a new section into tibia to store these addresses
005AF93D |. 74 06 JE SHORT labtibia.005AF945 : jump if ptr is nil
005AF93F |. FF15 0CB07A00 CALL NEAR DWORD PTR DS:[7AB00C] : call it
005AF945 |> 61 POPAD : restore the registers : )
005AF946 \.^ E9 B395EFFF JMP labtibia.004A8EFE : goto opcode next to original place of CALL labtibia.004A6E20
now, 7AB00C has the pointer of a procedure in my dll.
the procedure is:
[code=delphi]
procedure onSpriteLoad(sprite: pspritedata; id: plongword; tc: ptColor); stdcall; //using stdcall to avoid touch of stack
var
x: longword;
begin
//you can change spritedata and transparent color but not loaded item id..
//for example, make all the sprite black
for x := 0 to length(sprite^) do //or use fillchar or what you want!
begin
//if not((sprite^[x].r = tc^.r)and(sprite^[x].g = tc^.g)and(sprite^[x].b = tc^.b)) then begin //or only the non transparent part : )
sprite^[x].r := 0;
sprite^[x].g := 0;
sprite^[x].b := 0;
//end;
end;
end;
procedure loadsprite; stdcall;//dword ptr ds: [7AB00C] == @loadsprite
var
sprdata: pspritedata;
sprid: plongword;
transcolor: ptcolor;
begin
asm
push ecx
mov ecx, esp
sub ecx, 8
mov ecx, [ecx]
mov transcolor, ecx
mov ecx, esp
add ecx, $3C
mov eax, [ecx]
mov sprdata, eax
sub ecx, $4
mov sprid, ecx
pop ecx
end;
onSpriteLoad(sprdata, sprid, transcolor); //this is more secure than pushing things in stack...
end;
[/code]
I will continue updating this post for advances, if you want to explore more of this on others clients, ask me for the addresses.
sorry for my bad english hehe
greetings.