• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FSX FlightLoaded system event delivers previous flight

Messages
11
Country
germany
Hi all,

I have an issue with flight loading via SimConnect. I have regular SimConnect client build as DLL, handling the SimConnect session and gauges for the aircraft. It's built as singleton (if this is important), so all works just fine except "FlightLoaded" subscription. First at all this event will not be triggered somehow, although my client subscribed to it. To fix this I ended up counting SimStart/SimStop events (to ensure flight is loaded and started) and requesting "FlightLoaded" system state, catching this "system state" event containg reference to loaded flight file (flt). But instead of the loaded flight it gives me the name previous flight (I believe it will be created automatically be the sim on open screen etc.) If I try to load my flight again or just reset the situation, the sim gets my flight file that I expected before. Any ideas what is going wrong (before I start to log any particular package sent to SimConnect)?

FSX + SP2 (but I have a feeling it behaves same in other versions too).

Thank you!
 

DragonflightDesign

Resource contributor
Messages
924
Country
northernireland
You won't trap FlightLoaded as a single event. The sim sends out a FlightLoaded event at 8% scenario loaded when it is actually not loaded at all. The next time it is sent out is at 100% scenario loaded. This is how I do it:
Code:
void OnRecvEvent(SIMCONNECT_RECV_EVENT *pEvent, DWORD cbData)
{
    switch (pEvent->uEventID)
    {
        case CLIENT_6HZ:
        {
            // Flight ready?
            hr = SimConnect_RequestSystemState(hSimConnect, REQUEST_FLIGHT_LOADED, "FlightLoaded");
        }
    }
}

Code:
void OnRecvSystemState(SIMCONNECT_RECV_SYSTEM_STATE *pData)
{
    if (pData->dwRequestID)
    {
        switch (pData->dwRequestID)
        {
            case REQUEST_FLIGHT_LOADED:
                strncpy_s(SC_CURRENT_FLIGHT, MAX_PATH, pData->szString, sizeof(pData->szString));
            break;
        }
    }
}
By the time that the scenario load has reached 100%, SC_CURRENT_FLIGHT correctly contains the name of the current flight. I'll then keep checking SC_FLIGHT_LOADED against SC_PREV_FLIGHT_LOADED to see if there is a change and action the code accordingly.
 
Messages
11
Country
germany
Ok, I use 6Hz event too but wonder how it works for you. Debugging this I found out, that 6Hz event will be hit twice before scenario is completely loaded and of course if load has reach 100% and I'm in cockpit and in both cases I got previous flight. Even worster, all later calls of 6Hz event I still get previous flight :/

Here is my complete OnDispatch method

C++:
void CEnvelope::OnDispatch(SIMCONNECT_RECV* pData, DWORD cbData) {
    switch (pData->dwID) {
        case SIMCONNECT_RECV_ID_SYSTEM_STATE: {
            auto evnt = static_cast<SIMCONNECT_RECV_SYSTEM_STATE*>(pData);
            switch (evnt->dwRequestID) {
                //init paths on situation
                case SYSTEM_EVENT_AIRCRAFT_LOADED:
                    originalAir = pAircraft && pAircraft->LoadAircraft(evnt->szString);
                    break;
                case SYSTEM_EVENT_FLIGHT_LOADED:
                    //if (pAircraft && !pAircraft->Load(evnt->szString))
                        OutputDebugStringA(evnt->szString);
                    break;
            }
            break;
        }
        case SIMCONNECT_RECV_ID_EVENT_FILENAME: {
            //all operations where a file is involved - situation load, situation save, flight plan load
            auto evnt = static_cast<SIMCONNECT_RECV_EVENT_FILENAME*>(pData);
            switch (evnt->uEventID) {
                case SYSTEM_EVENT_FLIGHTPLAN_ACTIVATED:
//                if (pAirplane) pAirplane->Plan();
                    break;
                case SYSTEM_EVENT_FLIGHT_SAVED:
                    if (pAircraft && originalAir)
                        pAircraft->Save(evnt->szFileName);
                    break;
            }
            break;
        }
        case SIMCONNECT_RECV_ID_EVENT_FRAME: {
            break;
        }
        case SIMCONNECT_RECV_ID_EVENT: {
            auto evnt = static_cast<SIMCONNECT_RECV_EVENT*>(pData);
            switch (evnt->uEventID) {
                case SYSTEM_EVENT_1SEC:
//                    if (pAirplane && !frozen)
//                        pAirplane->Update1sec();
                    break;
                case SYSTEM_EVENT_4SEC:
//                    if (pAirplane && !frozen)
//                        pAirplane->Update4sec();
                    break;
            case SYSTEM_EVENT_6HZ:
                  if(SUCCEEDED(SimConnect_RequestSystemState(hSimConnect, SYSTEM_EVENT_FLIGHT_LOADED, "FlightLoaded")))
                      OutputDebugStringA("Load request hit\n");
//                if (pAirplane && !frozen)
//                    pAirplane->Update6Hz();
                break;
            case SYSTEM_EVENT_FLIGHTPLAN_DEACTIVATED:
                break;
            case SYSTEM_EVENT_SIM:
                break;
            case SYSTEM_EVENT_SOUND:
                muted = (evnt->dwData == 0);
                break;
            case SYSTEM_EVENT_PAUSE:
                frozen = (evnt->dwData == 1);
                break;
            case SYSTEM_EVENT_VIEW_CHANGE:
                inCommand = (evnt->dwData == SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D || evnt->dwData == SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL);
                break;
            default:
                //delegate event to airplane for possible further processing
//                if (pAirplane) pAirplane->HandleSituation((AIRCRAFT_SYSTEMS_GROUPS)evnt->uGroupID, (AIRCRAFT_SYSTEMS_STATES_EVENTS)evnt->uEventID, evnt->dwData);
                break;
            }

            break;
        }
        case SIMCONNECT_RECV_ID_EXCEPTION: {
            auto evt = static_cast<SIMCONNECT_RECV_EXCEPTION*>(pData);
            char buf[500];
            sprintf_s(buf, "***** SIMCONNECT EXCEPTION = %d  SendID = %d  Index = %d  cbData = %d \n", evt->dwException, evt->dwSendID, evt->dwIndex, cbData);
            OutputDebugStringA(buf);
            break;
        }
    }
}
 

DragonflightDesign

Resource contributor
Messages
924
Country
northernireland
Any simconnect event is hit at 8% of scenario load and then at 100% of scenario load. Outside those percentages the sim queues any demands and fires them all at 100% scenario load. Use the following code to trap the scenario load complete:
Code:
         MODULE_VAR sblights = { CABIN_SEATBELTS_ALERT_SWITCH };
         static int loadComplete = 0;
         static double startTimer = 0;

        //----

        // Check for startup complete
        if(startTimer != -1)startTimer++;
        if(startTimer == 1)lookup_var(&sblights);
        if (sblights.var_value.n == 0 && startTimer == 9)
        {
            trigger_key_event(KEY_CABIN_SEATBELTS_ALERT_SWITCH_TOGGLE, 0);
            startTimer = 0;
        }
        else if (sblights.var_value.n)
        {
            loadComplete = 1;
            startTimer = -1;
        }
I don't do C++ as I prefer to stick with plain C and know it is cross-sim compatible, but I can't see anything wrong with your code.
 
Messages
11
Country
germany
Thank you, will try this. Until now I just found out, that loading flight from the opening screen causes the issue, where loading from the sim via Flights menu (where I can select the kind of file I want to load, like my own flights, adventure etc ) works just fine. Another question, I subscribe to all needed system events during the session intialisation, e.g. SimConnect_Open and if ok -> subscribe to all the stuff. Could it be "to early" here? Perhaps I could switch to, eg. subscribing to aircraft loading (which works just fine) and subscribing than to the rest of system events if aircraft load occured and catched?
 
Messages
1,962
Country
us-ohio
How can you see the "previous flight" if you're loading from the opening screen? Are you saying that you're seeing "flight loaded" for the default flight before seeing the "flight loaded" for the one you've selected?
 
Messages
11
Country
germany
I start from opening screen, where I have an option to load flight, which I use. Further, as you can see from my code, everytime I request "FlightLoaded" I get "Previous Flight.flt" as file name of loaded file (localised in German, as I have german version) instead of desired one.
 
Messages
1,962
Country
us-ohio
Ok, Previous Flight.flt is from FSUIPC, it is not part of FSX itself. If you are at the opening screen and select a flight, and the first "flight loaded" you see is "Previous Flight.flt", then I suspect FSUIPC is the one making that happen. Try disabling the load of FSUIPC and see if you get the same behavior without it.
 
Messages
11
Country
germany
For half of a second I was very lucky, in the next half I remebered - fresh FSX installation, no FSUIPC, no add ons at all :/
One more strange thing: usually all the FLT files will be stored in user's "documents/fsx files" folder, this previous flight.flt comes always from roaming/microfsoft/fsx folder, where the fsx.cfg is stored.
 
Messages
1,962
Country
us-ohio
There are no ".flt" files in the appdata area. So, I dunno what to tell you regarding that. My FSX install is the FSX:Acceleration install from Microsoft (not a STEAM version).
 
Messages
11
Country
germany
I use the standard edition I bought years before it came all to Steam with SP1 and SP2 on it. And will try to check which process creates and removes these files.
 

DragonflightDesign

Resource contributor
Messages
924
Country
northernireland
Thanks Ed. I don't have fsuipc so I was struggling trying to understand where 'Previous Flight' was coming from.
 
Messages
11
Country
germany
It doesn't look like it comes from FSUIPC, I checked the loading process and found out, that the order of flight files load looks like following (all will be done primarly by fsx.exe)
- Previous flight.flt
- Temporary flight.flt
- [ALL STORED FLIGHT + ALL "INSTALLED" FLIGHT, I mean that came during the installation]
- [DESIRED FLIGHT.flt]
- Previous flight.flt

This last item will be reported by SimConnect as the loaded one. This all applies to loading from opening screen, if you load from the fligt - all this stuff except stored flgiths will be skiped (looks like stored flights will be "scanned") and desired flight file will be loaded directly. No idea why is it so.
I attached the log of Process Monitor for loading from opening screen.
 

Attachments

  • Logfile.zip
    3.2 KB · Views: 53
Messages
1,962
Country
us-ohio
In the "Previous Flight.flt" file, in the [Main] section, what does the description contain?
 
Messages
11
Country
germany
It's German, but let me translate
[Main]
Title=Vorheriger Flug (Previous Flight)
Description=Dieser Flug wurde gespeichert, als Sie das letzte Mal Flight Simulator beendet haben. (This flight was stored as you quit Flight Simulator last time)
AppVersion=10.0.61472
FlightVersion=1

Already checked files in FSX/flights/other - nothing comparable
 
Messages
11
Country
germany
Finaly I decied to create separate thread monitoring access to all the files inside related folder, filtering FLT files and assuming that last one is THE flght file I need. Works, and looks strange I must say. Hooking access to registry or system file read finctonality wasn't really helpful.
As Ed said - weird. But works and will be configurable (for all the lucky people not having this issue).

Additional finding: looks like file load functionality doesn't anything to do with SimConnect as it will be thrown before or simultaneously with SimConnect dll load. Just check the log
Code:
"fsx.exe" (Win32): "C:\Windows\SysWOW64\msvcp140d.dll" geladen.
"fsx.exe" (Win32): "C:\Windows\SysWOW64\msvcp140d.dll" wurde entladen.
"fsx.exe" (Win32): "C:\Windows\WinSxS\x86_microsoft.flightsimulator.simconnect_67c7c14424d61b5b_10.0.61259.0_none_55f5ecdc14f60568\SimConnect.dll" geladen.
"fsx.exe" (Win32): "C:\Windows\SysWOW64\vcruntime140d.dll" geladen.
"fsx.exe" (Win32): "C:\Windows\SysWOW64\ucrtbased.dll" geladen.
"fsx.exe" (Win32): "C:\Windows\SysWOW64\msvcp140d.dll" geladen.
OnFileChange abc.FLT
OnFileChange abc.WX
SIMCONNECT_RECV_ID_OPEN
SIMCONNECT_RECV_ID_EVENT
SIMCONNECT_RECV_ID_EVENT
SIMCONNECT_RECV_ID_EVENT
SIMCONNECT_RECV_ID_SYSTEM_STATE
C:\Users\User\AppData\Roaming\Microsoft\FSX\Vorheriger Flug.FLT
SIMCONNECT_RECV_ID_SYSTEM_STATE
SIMCONNECT_RECV_ID_EVENT
 
Messages
11
Country
germany
So guys, to close this topic, I finally found a method to safely recognize loaded file. I tried before with registry and api hooking (RegOpenKey and ReadFile in kernelbase.dll), catching the flight file load based on last access time attribute (both, direct read the directory and watching directory using winapi) - nothing works. And the reason is simple - the load of flight file is done before SimConnect session is open (I'm talking here about the case where I load the file from opening screen), so all the stuff with registry and file attribute changing done by FSX is already gone before my module is even loaded and SimConnect session open.

So what works for me now is request system state change for flight load as discussed above, first try to load referenced file in regular way and if it fails list all flight files (FLT) in the FSX documents folder, read them one by one until I find file cotaining same values for some sim variables like loaded flight. I chose plane latitude and longitude as other stuff is either not available or not reliable. I hope I'm really the only one with this issue, but if not, here is a piece of code I developed for tracking flight files (where "simdocuments" is the FSX documents folder and "convertStrDMSToDegree" is a regex based function I developed to read string representation of plane position from flight file).

C:
    MODULE_VAR plat = { PLANE_LATITUDE };
    MODULE_VAR plon = { PLANE_LONGITUDE };
    lookup_var(&plat);
    lookup_var(&plon);
    double curlat = plat.var_value.n / 40007000.0 * 360;
    double curlon = plon.var_value.n / 281474976710656.0 * 360;

    WIN32_FIND_DATAA data;
    strncpy_s(buf, simdocuments, sizeof(buf));
    strcat_s(buf, "\\*");
    HANDLE hFind = FindFirstFileA(buf, &data);
    char lvar_external_str[MAX_PATH];
    ZeroMemory(lvar_external_str, sizeof(lvar_external_str));
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (strstr(PathFindExtensionA(data.cFileName), ".FLT") != NULL) {
                //construct file path
                strncpy_s(loadedFile, simdocuments, sizeof(loadedFile));
                strcat_s(loadedFile, "\\");
                strcat_s(loadedFile, data.cFileName);
                //get lan and lon from file
                GetPrivateProfileStringA("SimVars.0", "Latitude", "0", lvar_external_str, MAX_PATH, loadedFile);
                double lat = convertStrDMSToDegree(lvar_external_str);
                if (abs(lat - curlat) > 0.001) continue;
                GetPrivateProfileStringA("SimVars.0", "Longitude", "0", lvar_external_str, MAX_PATH, loadedFile);
                double lon = convertStrDMSToDegree(lvar_external_str);
                if (abs(lon - curlon) < 0.001) break;
            }
        } while (FindNextFileA(hFind, &data));
        FindClose(hFind);
    }

Could be written in more elegant way but wasn't my goal
 

DragonflightDesign

Resource contributor
Messages
924
Country
northernireland
Yes, the SDK example cannot work because FlighLoaded occurs early in the load cycle before SimConnect is established. I documented it (along with what I think is possibly a simpler solution) in sd2gau38 (in the Resources section). There is a second problem if you reload the flight (ctrl+;) in that the SimConnect session stays established, so FlightLoaded occurs when you think it should. Also documented.
 
Last edited:
Messages
11
Country
germany
I read this and I understand where you come from, but I think I have different use case, even with similar reason. I don't use SimConnect in a panel callback, it's running in "parallel" and will be initialised and shut down in module_init/deinit. So I assume they will be called before any panel callbacks (e.g. it will be loaded if you chose aircraft on opening screen), but in this case the flight loading is already done too. I think it could be possible to track using some module, not gauge, similar to what FSUIPC is, what will be loaded if you start simulator. But this would be too much effort with weird outcome :) So I found quick and dirty solution for my case and it works for any possible flight loading situation and has no side effects durin file reloading ;)

By the way, can you tell me if 32 bit Prepar has same behaviour?
 
Top