View previous topic :: View next topic |
Author |
Message |
ups101
Joined: 13 Jan 2005 Posts: 2
|
Posted: Thu Jan 13, 2005 1:16 Post subject: |
|
|
To NWNX developers,
Since you have been talking a bit about assembly code already, I hope you don't mind a couple of fly-by questions:
1. How did you identify the piece of code to look for, for madcodehook (contents of the FindHook method)? I am asking because I would like to replicate your approach to hook other calls.
2. I see you are manipulating the callstack using assembly code. How impossible would you rate the idea of pushing other NWN-function calls onto the stack, before (but similar to) SetLocalStringNextHook? My hope is to be able to invoke an NWNScript function from C using the assembler approach. I realize setting up parameters and handling return values is extremely cumbersome - but, in your opinion, is it doable?
Just to be clear: I only hope for your advice - this is not a "feature wishlist". I am considering the possibility of using NWN as a platform for an AI project.
Many thanks in advance, and kudos for your results so far! |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Thu Jan 13, 2005 9:48 Post subject: |
|
|
Good questions
1) There is no sure way to success, it all depends on what kind of function you want to hook. I generally create a test module that periodically calls the function I want (say SetLocalString) and then run the server in a debugger. Knowing that the game usually runs in a main loop, you can try to find the point where it jumps out of the main loop when the periodic script call happens. It is a lot of trial and error, believe me.
Helpful resource for understanding the virtual machine:
http://www.torlack.com/index.html?topics=nwndata_ncs
2) On an impossibility scale of 1-10 I would give it a 3, meaning it is probably possible . Beeing able to call internal script functions is a bit of a holy grail, because it would open up many new possibilities. I have not heard of anybody who tried it, though. _________________ Papillon |
|
Back to top |
|
|
ups101
Joined: 13 Jan 2005 Posts: 2
|
Posted: Thu Jan 13, 2005 22:20 Post subject: |
|
|
Thanks alot for your replies. I will mess a bit around, using the procedures you have described. In the odd-chance of having any luck, I will report back. |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Sat Jan 15, 2005 22:17 Post subject: |
|
|
another approach to running script that is not in mod. it's only workaround but it's working fine. i've tested it few days ago just as proof of concept. i think small how to will be better than my description (wich could be not well understood thanks to my english level)
1) i've put placeable on mod and created onUsed script. my onUsed script looked like this:
void main()
{string s="aaaaaaaaaaaaaaaaaaaaaa and many more a's";}
and was about 200bytes long (size of compiled file)
2) put my script into module's buffered scripts (it's very important step cause most of scripts are load to memory directly from mod only when they're used)
3) run mod on nwserver and log in
4) using your favourite memory tool find your script (in memory it is exact copy of .ncs file)
5) i've pasted down my other script i've made (i've pasted it in place of old one). very simple one
void main(){ActionSpeakString("something");} let's say it was 100 bytes when compiled. Cause my new script is 100bytes shorter than my previous it's not good idea to run it. now take address of first byte of script (let's say it is 0x080BBD68) and now search ram for integer of value 0x080BBD68 (in other words look for hex 68BD0B08) you will find pointer to script code.
after that i have another pointer (it's pointer to script's name) and in next int there is size of script. i've changed size to 100 (0x64)
6) use placeable. and wheeeeee my placeable talked to me.
the idea is to make placeholder for script (or use delete and new on pointer to script code) and run script xxx (with new code) from the game. cause we don't know the way of signaling something to nwn there's only a method of hearbeat or delayfunction checking if there is script to run. |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Sat Jan 15, 2005 23:35 Post subject: |
|
|
i just thought i know a better way of finding a way to call nwscript code. Make a placeable and onUsed function (put it into buffered). run nwserver in your debugger, find code of that function in memory. find pointer to it. put breakpoint on memory read. go to game and use placeable. debugger should brake somewhere and you should be near nwserver function that calls nwn scripts. good luck |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Sat Jan 15, 2005 23:40 Post subject: |
|
|
isilweo, one of the problems is that we do not how to emulate the calling conventions of functions / scripts of the virtual machine. Refer to Torlacks docs to see what I mean. _________________ Papillon |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Mon Jan 17, 2005 23:59 Post subject: |
|
|
goodevening
I didn't want to call functions of virtual machine but scripts. There must be function wich executes scripts somewhere. Cause before we start interpreatation of scriptcode (and enter virtual machine) there must be piece of code wich starts up vm and runs script. I think i've found something. (of course cause of my weak knowledge of asm it probably only make you laugh). If someone (Papillon?) could check it. Maybe it could be used.
.text:005AF2C0 it's here. it's functions. It takes three arguments. First argument is ScriptName (or pointer to it, i don't remember now), second argument is objectid (the same id you can obtain ie from ObjectToString, or if you know where to search in ram for it) wich is caller of script - it becomes OBJECT_SELF in script. the third argument is always (i think so;) 1.
If you set up breakpoint on that address you can see what i'm talking about. I've setup my bp on 5AF2C8 with condition Dword(EDI) != 0 (i use ida for debugging) condition eliminates breakpointing when scriptname is empty.
The idea is to call this function from dll (is there a way?) and run script. As object ID you can pass 00 - it's id of module object, or 01 - it is id of first area in mod (or it should be).
Now please don't laugh of me and point errors in my thinking.
thank you
isilweo |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Tue Jan 18, 2005 21:34 Post subject: |
|
|
The function you found is probably in the vincinity of the function that the nwnx profiler hooks. As soon as the ODBC2 module works a bit better than right now, I will check this out. _________________ Papillon |
|
Back to top |
|
|
NoMercy
Joined: 03 Jan 2005 Posts: 123 Location: UK
|
Posted: Wed Jan 19, 2005 0:25 Post subject: |
|
|
I'm not sure, but if it was possible to call the dm_runscript command processing function, might provide a simpler interface, might not but a thought if it can be tracked down. |
|
Back to top |
|
|
|