View Full Version : Display messages via SimConnect?
ziporama
11 Nov 2006, 19:03
Has anyone figured out the trick to send message strings to FSX via SimConnect or the C++ gauges?
This used to be the old adventure message string, but it's not documented anywhere I've been able to find.
One way is to draw a window on the screen with a transparent background but I was hoping to use the "normal" way...
Cheers,
Etienne
You can do it with FSUIPC. But I don't know how Pete implemented this, via simconnect or by visiting the good ol' FS internals ;)
ziporama
13 Nov 2006, 18:51
I've done it in FSUIPC, but was hoping that SimConnect would support it. Perhaps the next SDK version...
Cheers,
Etienne
You can do it from inside FSX and relay to the functions via simconnect client data areas and client events
Attached file is an example of how to do this. See Send Event A,B,C of SDK Samples. Maybe not the best way since I've not used simconnect client data so much. Very dirty too ;)
1369
Very dirty too ;)
Ok, dirty, but.... it works :D
Thank you,
Javier
ziporama
16 Nov 2006, 19:30
Very, very sneaky, dirty and smart... Thanks so much for the tip, un tres grand merci :)
Etienne
RobertFly
17 Nov 2006, 15:01
Is it possible to do the same for other dialogs like the ones on the missions or the flying tips?
By the way, how do you found that (char *) 24?????? :confused: :confused:
Best Regards
I looked at the import/export tables of FSX dll modules. But it was purely luck I found the right function at the second try ;)
I have absolutely no knowledge of FS internals or assembly. I doubt accessing other UI related functions will be so easy.
ziporama
18 Nov 2006, 08:57
Dependency walker (http://www.dependencywalker.com/) does a very nice job at finding the various entry points in dlls.
Etienne
RobertFly
18 Nov 2006, 14:28
Dependency walker (http://www.dependencywalker.com/) does a very nice job at finding the various entry points in dlls.
Aha, very interesting tool. But it seems I'm handicaped understanding at low level. I haven't been able to find anything around this. Even the famous (char*)24 is missing to me :(
I quit. I'll wait for the experts to have some light in this issue :cool:
Robert
FSX DLL don't export function names, you have to give the ordinal instead. The cast is just here to prove we can do elegant polymorphism in C :D
Manuel Ambulo
01 Dec 2006, 12:38
But, lc0277, how did you figured out the arguments or parameters that it was needed to pass to the procedure exported in the WINDOW.DLL?...because the dependency walker..just displays the ordinal, and entry point of the procedures, but...how did you know how many and what types of arguments (char msg[256], int style, int delay, int cleanup) <--- how did you figured out them??...
Best Regards,
Manuel Ambulo
virtuali
05 Dec 2006, 15:43
Luckyly enough, they are exactly the same as FS9, just the function ordinal has changed.
Now, you might say "how did you figured out in FS9"... :)
Manuel Ambulo
05 Dec 2006, 16:16
:confused: Luckyly enough, they are exactly the same as FS9, just the function ordinal has changed.
Now, you might say "how did you figured out in FS9"... :)
Lol, yeah...."how did you figured out in FS9".....because, in FS9 for access WINDOW.DLL....there is the linkage system, and i think that for access to the exported functions list, i need to specify the MODULE ID of the WINDOW.DLL module, then a pointer which will be filled with the pointer that points to the list of functions exported by the WINDOW.DLL, the problem (for me)..is to know HOW MANY and WHAT TYPES of arguments need each one......i think (or i believe..that you may need some assembler knowledge to get that information...lol...:confused:)....i know that they are not exported with the names of the functions, so then i may guess you ran all pointers (which in some cases if you try to run the functions from your module (without passing any arguments to it...)..FS will crash...thats why i guessing how you did it....??? :confused:...)....lol :o
Best Regards,
Manuel Ambulo
jcboliveira
05 Dec 2006, 18:03
Really but really dirty it will be to intercept DirectX device pointer.
http://www.codeguru.com/cpp/g-m/directx/directx8/article.php/c11453/
José
virtuali
05 Dec 2006, 18:38
Using the linkage system it's not the only way of calling an FS function. Once you find the correct prototype, you simply declare a "pointer to function " variable, assign its address with GetProcAddress(), and you call the routine normally.
assuming you found in the module "XXX.DLL", the function with ordinal 10 takes two doubles in input and returns an int, with the "standard" calling conventio, the prototype will be, in your .H
typedef int (__stdcall *MyNewfoundFunctionFunc) ( const double, const double );
in your .CPP file, you declare and init a variable of this new type:
MyNewfoundFunctionFunc MyNewfoundFunction = 0;
at start of your program, you do something like this:
HMODULE hMod = GetModuleHandleA( "XXX.DLL" );
if( hMod )
{
MyNewfoundFunction = (MyNewfoundFunctionFunc)GetProcAddress(hMod, MAKEINTRESOURCEA( 10 ) ); // assuming the ordinal it's 10, for example
}
from now on, in your program, you can call the function as if it were a regular function according to its prototype, like this:
int result = MyNewfoundFunction( 3.0, 4.3 );
Of course, to figure out the parameters types, a disassember AND some asm knowledge it's helpful, and of course the use of a debugger with breakpoints. Also, using the wrong calling convention, as well the wrong parameter types, will usually make FS crash, so yes, some care is needed.
Usually, it's much easier to figure out parameters if the function name is "decorated", you'll recognize the names with those funny "@!""3213£@##!" characters appended. In that case, the parameters are encoded in the name itself, so a good disassembler should be able to decode them and give you some basic prototype (of course, no disassembler will be able to tell you what the parameters DO, even if they are correct and not crashing FS, their actual meaning can't be figure out without following the actual assembler code to see what they are really doing ).
Yes, it's a long a tedious work, not really my idea of having fun. I think we should lobby Microsoft into convincing them to extend Simconnect to officially support these kind of things as well...
If the function is simple (or expected to be) using a debugger is generaly enough. Just put a breakpoint and watch the values on the top of the stack at each call.
With some habits and knowledge about your adress space, differents data types can be easily distinguished :
code pointers (meaning function pointers or return address, thus the begin or end of arguments),
heap pointers (allocated data, mainly big control structures),
stack pointers (temp data, format strings, ...).
integers or floating point numbers (formatting random bits to a float has very little chance to give a number between -100. and +100.).
VC++ Express has a good debugger which can format data on the fly to quickly find strings or numbers.
After that you had to guess or experiment.
But if the function is more complex, eg if it takes structures or pointers to structures which are not documented (ie we don't have the corresponding header file), this process is nearly impossible. :confused:
C++ function calls are even worst, since you have to provide a pointer to this in registers, not on the stack.
I agree with virtuali, this process is not funny and is clearly not what add-on developers are expected to do. Simconnect has changed the way we can communicate with FS, and we should really try to convince MS to make it more feature-rich.
Manuel Ambulo
06 Dec 2006, 07:52
Really but really dirty it will be to intercept DirectX device pointer.
http://www.codeguru.com/cpp/g-m/directx/directx8/article.php/c11453/
José
Thanks, jcboliveira, i didnt knew that it was possible to intercept calls made to a DLL. When you posted it, i went searching in internet and found some interesting documents that explains how to intercept API calls made to DLLs like (user32.dll).:eek:
Usually, it's much easier to figure out parameters if the function name is "decorated", you'll recognize the names with those funny "@!""3213£@##!" characters appended. In that case, the parameters are encoded in the name itself, so a good disassembler should be able to decode them and give you some basic prototype (of course, no disassembler will be able to tell you what the parameters DO, even if they are correct and not crashing FS, their actual meaning can't be figure out without following the actual assembler code to see what they are really doing ).
Yep, it is much easier, because Dependency Walker has an option that can "undecorate" the "decorated" functions (as far as i remmember, is the version 2, of Dependency Walker..).
If the function is simple (or expected to be) using a debugger is generaly enough. Just put a breakpoint and watch the values on the top of the stack at each call.
With some habits and knowledge about your adress space, differents data types can be easily distinguished :
code pointers (meaning function pointers or return address, thus the begin or end of arguments),
heap pointers (allocated data, mainly big control structures),
stack pointers (temp data, format strings, ...).
integers or floating point numbers (formatting random bits to a float has very little chance to give a number between -100. and +100.).
VC++ Express has a good debugger which can format data on the fly to quickly find strings or numbers.
After that you had to guess or experiment.
But if the function is more complex, eg if it takes structures or pointers to structures which are not documented (ie we don't have the corresponding header file), this process is nearly impossible.
C++ function calls are even worst, since you have to provide a pointer to this in registers, not on the stack.
I agree with virtuali, this process is not funny and is clearly not what add-on developers are expected to do. Simconnect has changed the way we can communicate with FS, and we should really try to convince MS to make it more feature-rich.
Yesterday, during my search in internet, i also found a tool called OlllyDbg v1.1, which can open DLLs, and see it in assembler, the good thing is that the program has an analyzer that tells me how many calls are made, and where are there come from. Analyzing the FSX's DLLs is a bit much easier, because i can see the exported functions (just the module name and ordinal, example: "util.#28", which means that a function exported in util.dll, with ordinal 28) of other FSX modules, there in the code, but openning the FS9 modules, its a bit more different (and complex for me) because of the linkage system (i think), i cannt see the exported functions directly....and yeah, as virtuali said, is really a pain trying to figured out arguments...:banghead: :(
Best Regards....:coffee:,
Manuel Ambulo
RobertFly
07 Dec 2006, 14:55
Really but really dirty it will be to intercept DirectX device pointer.
http://www.codeguru.com/cpp/g-m/directx/directx8/article.php/c11453/
José
José, this is incredible. It is openning a lot of possibilities. But is it possible to use it from a C# program? How?
Sorry but I'm not familiar at all with C++
Regards
Manuel Ambulo
09 Dec 2006, 17:27
A BIG THANKS!!....JCBOLIVEIRA, LC0277 AND VIRTUALI..... because,....i learnned a LOT!, since you guys posted those posts above, i investigated in internet about how is the ASSEMBLY language and the method to intercept API calls, i found some interesting documents, and since that day i had been playing around with my old FS9's modules and i had discovered how to figure out how many parameters that some functions needs to run (exported functions bettween FS9's modules), however..i still dont know the type or size of each parameter and as LC0277 said it is really hard if they are pointers to structures (or pointers to pointers)....and also, during my playing time with FS9 modules, i found where it is located the AdvBar function that LC0277 found in the WINDOW.DLL of FSX,......yes...it is the same function but it has different ordinal (located inside of the LINKAGE of the WINDOW.DLL of FS9)..REALLY COOL ...so thanks JCBOLIVEIRA, LC0277 AND VIRTUALI..... i do really found many cool stuff....in FS9's MODULES (and in FSX MODULES), the problem, of course, is to figure out what each function do...(which is REALLY HARD)...:)...
José, this is incredible. It is openning a lot of possibilities. But is it possible to use it from a C# program? How?
Sorry but I'm not familiar at all with C++
Yep, it is really incredible :D
Best Regards,
Manuel Ambulo
jcboliveira
10 Dec 2006, 02:05
In managed code I don't think that it's possible to do anything with the pointer. I stumble on this solution when I was looking for a solution for 3d dialog rendering over FS2004 in full screen. It isn't dificult to do that kind of rendering but you need to sync it with the frame otherwise it will flicker. To sync it you need the device pointer.
José
Manuel Ambulo
10 Dec 2006, 16:32
Wow!!, that would be really nice to see, a special renderer for FS, (would look images more realistic...)...but yes...same as amazing, same should be **hard** (i think), getting or intercept the device pointer...and then sync as you said....
Best Regards,
Manuel Ambulo
DocMoriarty
20 Dec 2006, 03:16
Did you ever look at the .spb files in the dialogs subfolder of FSX? I wonder whether this can be used for dialogs. They look like old school resource files for dialogs to me and i'm sure them ACEs have a compiler for that stuff that they don't want to hand out as part of the SDK.
Showing modal dialogs on top of FSX works well with managed simconnect when FSX is in window mode, it would work well too in fullscreen mode if FSX wouldn't automatically minimize then when it's window looses focus (SimConnect.SetSystemState("DialogMode",1,0.0F,"")).
Did you ever look at the .spb files in the dialogs subfolder of FSX? I wonder whether this can be used for dialogs. They look like old school resource files for dialogs to me and i'm sure them ACEs have a compiler for that stuff that they don't want to hand out as part of the SDK.
Compiler is already in the SDK; see Core Utilities/SimProp. For a decompiler, look at spb2xml on avsim.
I think those files are used for localisation, and you cannot bring up a full-featured dialog window just by writing a SPB file and telling FS to read and show it.
If you want FS look-alike windows, you may use ui.dll/fsui.dll. They export some C++ decorated functions (well, 2400 of them). Still less valuable than documented headers, but you can probably build a GUI without the ordinary pain of guessing ordinals,arguments etc. ;)
DocMoriarty
21 Dec 2006, 02:07
Never looked at SimProp so far, but thanks for the hint. I would actually be satisfied if switching to "DialogMode" via SimConnect would allow to pop up own dialogs in full screen mode without FS window minimizing.
I don't think this is DirectX default behaviour like someone mentioned if i remember right from my DirectX experiments and FS does it too with several dialogs (map, aircraft selection etc.). There is also a setting in DirectX that allows to pop up normal windows on top of a directx full screen window, not sure you can change that at runtime (it costs a lot of frames and has some sideeffects).
I think though they should add some simple dialog functions to SimConnect for a number of reasons. First the client is not necessarely on the same machine as FS and second there should be a supported method that doesn't break when a new version comes out. Something like showing the mission descriptions or a ingame dialog like the ATC window with title, text and a number of selections, result sent back to client. I found some dirty stuff to do that but an official way would be appreciated.
Chrisoft-Dev
11 Jan 2007, 15:07
Hello, I used this function PrintMessage.
If I do it :
.
.
.
struct AdvMessage {
char* message;
int style;
int delay;
int cleanup;
};
.
.
.
msg->message="Hello Pilot!";
msg->style=4;msg->delay=100;msg->cleanup=0;
PrintMessage(msg);.
This code works well
but I've some difficult to affect string of characters for msg->message in this code :
TCHAR pszDest[256];
hr=StringCchPrintf(pszDest,256,TEXT("Kohlsmann=%f - Altitude=%f - Latitude=%f - Longitude=%f\0"),pS->kohlsmann,pS->altitude,pS->latitude,pS->longitude);
msg->message=(char *)pszDest;
msg->style=4;msg->delay=100;msg->cleanup=0;
PrintMessage(msg);
This code make an error of FSX :
http://chrisoftdev.free.fr/error_fsx_1.jpg
I tried strcpy(), same error.......
I tried other code :
char* pszDest;
sprintf(pszDest,"TEST! %f",pS->kohlsmann);
msg->message=pszDest;
msg->style=4;msg->delay=100;msg->cleanup=0;
PrintMessage(msg);
It works but It displays bad characters.......
What is the solution ?
Regards,
Chris.
You should not use TCHAR, wchar_t or other multibyte char encodings. I don't know if FSX can handle them everywhere.
The last code snippet has a problem, you didn't allocated memory for pszDest.
Try :
char pszDest[32];
snprintf(pszDest, 32, "TEST! %f",pS->kohlsmann);
msg->message=pszDest;
msg->style=4;msg->delay=100;msg->cleanup=0;
PrintMessage(msg);
Chrisoft-Dev
11 Jan 2007, 19:27
Okay thanks lc0277,
I tried this code.
First, snprintf doesn't know for VC++ 2005 express.
But _snprintf yes, there is.
I tested, it doesn't work :(
Same error.......
Very Surprised.
Anyelse, "TANT PIS" (french words) :D
I'll use only quotes for sometimes.
Regards,
Chris.
Chrisoft-Dev
13 Jan 2007, 10:22
Hello all,
Well, I think to find solution about my problem, it's suitable to do it for example my code :
void PrintMessage(char *msg)
{
.
.
.
if (FsxProc != NULL) FsxProc(msg, 4, 100, 0);
I removed the struct *msg. It could make some bug...
Then I changed it to variable char* msg.
Also, I didn't tried but it could work this :
void PrintMessage(char *msg, int style, int delay, int cleanup)
{
.
.
.
if (FsxProc != NULL) FsxProc(msg, style, delay, cleanup);
Regards,
Chris. :)
ziporama
18 Jan 2007, 19:06
Very nice stuff, thanks all.
Jose, one comment: have you looked into the unsafe keyword in C#? Pointers do work as they do in C/C++ inside an unsafe block, but using the pointer outside the managed environment may be a different issue altogether.
I also ran across an interesting post on CodeProject and associated reference on hosting the CLR from regular c++ (I'm thinkin, FS module :) )
http://www.codeproject.com/csharp/unmanagedtomanaged.asp
Haven't played with it yet - my last attempt with the regular C++ using the /clr switch caused a GPF in FSX with a memory allocation problem (probably the GC at work). This seems to be a completely different approach.
DocMoriarty
19 Jan 2007, 04:00
I made an experiment with a native C(--) wrapper dll around a managed VB8 dll in FSX based on the code project description and a similar MSDN paper.
When the C dll gets the Start/Stop calls i just call matching functions in the managed dll. Basically it works to wrap managed stuff but i had some weird behaviour and decided for the sake of performance and stability not to use managed code inside the FSX process. So i have a C dll for all that inside stuff that offers some functionality to my managed exe's avialable via SimConnect custom data areas and events.
ziporama
19 Jan 2007, 07:48
I made an experiment with a native C(--) wrapper dll around a managed VB8 dll in FSX based on the code project description and a similar MSDN paper.
When the C dll gets the Start/Stop calls i just call matching functions in the managed dll. Basically it works to wrap managed stuff but i had some weird behaviour and decided for the sake of performance and stability not to use managed code inside the FSX process. So i have a C dll for all that inside stuff that offers some functionality to my managed exe's avialable via SimConnect custom data areas and events.
The "weird" behavior is probably the best way to characterize it, definitely very unpredictable. I find the unstable part very odd, as the managed run itself seems quite stable. It's the return to unmanaged code that seems to be a problem with either a lockup or GPF in FS. What I find more interesting is that a regular wrapper (outside of FSX) with similar code seems to work just fine. Oh well.
Etienne
DocMoriarty
20 Jan 2007, 08:50
My suspicion for the weird behaviour is, that the addon dll is started in it's own thread and this thread has no windows message queue associated. So calls that show windows or do something gui related won't work, unless you create and associate a message queue with the current thread. I didn't try that though since as i said above it's currently not the way to go for me.
Could be something else too though, such as that the CLR might not run properly if it doesn't have control of the process main thread.
I know that the simconnect open in my managed dll worked due to the simconnect console output but writing a logfile log or opening a message box didn't.
vBulletin® v3.8.3, Copyright ©2000-2013, Jelsoft Enterprises Ltd.