mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-23 07:15:35 +08:00
Add 32 and 64 bit FSUIPC library projects
Summary: So far we were linking against the prebuilt FSUIPC user library, compiled with VS2010 many years ago. The source of this user library is part of the FSUIPC SDK, so we can benefit from modern compilers and include it into our source tree. This version contains some very small wide char fixes compared to the official FSUIPC SDK source. It also includes the new 64 bit version. Reviewers: #swift_pilot_client, msutcliffe Reviewed By: #swift_pilot_client, msutcliffe Differential Revision: https://dev.swift-project.org/D29
This commit is contained in:
Submodule externals updated: 02df5fe088...73be1b8c37
@@ -8,10 +8,7 @@ TEMPLATE = lib
|
||||
CONFIG += plugin shared
|
||||
CONFIG += blackmisc blackcore
|
||||
|
||||
LIBS += -lsimulatorfscommon -lFSUIPC_User -luuid
|
||||
|
||||
# required for FSUIPC
|
||||
win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib
|
||||
LIBS += -lsimulatorfscommon -lfsuipc -luuid
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
@@ -14,12 +14,14 @@ INCLUDEPATH += . $$SourceRoot/src
|
||||
SOURCES += *.cpp
|
||||
HEADERS += *.h
|
||||
|
||||
contains(BLACK_CONFIG, FSUIPC): DEFINES += SWIFT_USING_FSUIPC
|
||||
|
||||
LIBS += -lFSUIPC_User
|
||||
|
||||
# required for FSUIPC
|
||||
win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib
|
||||
contains(BLACK_CONFIG, FSUIPC) {
|
||||
equals(WORD_SIZE,32) {
|
||||
DEFINES += SWIFT_USING_FSUIPC32
|
||||
}
|
||||
equals(WORD_SIZE,64) {
|
||||
DEFINES += SWIFT_USING_FSUIPC64
|
||||
}
|
||||
}
|
||||
|
||||
DESTDIR = $$DestRoot/lib
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SWIFT_USING_FSUIPC
|
||||
#if !defined(SWIFT_USING_FSUIPC32) && !defined(SWIFT_USING_FSUIPC64)
|
||||
|
||||
#include "fsuipc.h"
|
||||
|
||||
@@ -75,4 +75,4 @@ namespace BlackSimPlugin
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif //SWIFT_USING_FSUIPC
|
||||
#endif // !defined(SWIFT_USING_FSUIPC32) && !defined(SWIFT_USING_FSUIPC64)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifdef SWIFT_USING_FSUIPC
|
||||
#if defined(SWIFT_USING_FSUIPC32) || defined(SWIFT_USING_FSUIPC64)
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
@@ -16,8 +16,16 @@
|
||||
#include "fsuipc.h"
|
||||
#include <windows.h>
|
||||
// bug in FSUIPC_User.h, windows.h not included, so we have to import it first
|
||||
#include "FSUIPC/FSUIPC_User.h"
|
||||
#include "FSUIPC/NewWeather.h"
|
||||
|
||||
#ifdef SWIFT_USING_FSUIPC32
|
||||
#include "../fsuipc32/FSUIPC_User.h"
|
||||
#include "../fsuipc32/NewWeather.h"
|
||||
#endif
|
||||
|
||||
#ifdef SWIFT_USING_FSUIPC64
|
||||
#include "../fsuipc64/FSUIPC_User64.h"
|
||||
#include "../fsuipc64/NewWeather.h"
|
||||
#endif
|
||||
|
||||
#include "blackmisc/simulation/fscommon/bcdconversions.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
@@ -500,4 +508,4 @@ namespace BlackSimPlugin
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif //SWIFT_USING_FSUIPC
|
||||
#endif // defined(SWIFT_USING_FSUIPC32) || defined(SWIFT_USING_FSUIPC64)
|
||||
|
||||
60
src/plugins/simulator/fsuipc32/FSUIPC_User.h
Normal file
60
src/plugins/simulator/fsuipc32/FSUIPC_User.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef _FSUIPC_H_
|
||||
#define _FSUIPC_H_
|
||||
|
||||
// Supported Sims
|
||||
#define SIM_ANY 0
|
||||
#define SIM_FS98 1
|
||||
#define SIM_FS2K 2
|
||||
#define SIM_CFS2 3
|
||||
#define SIM_CFS1 4
|
||||
#define SIM_FLY 5
|
||||
#define SIM_FS2K2 6
|
||||
#define SIM_FS2K4 7
|
||||
#define SIM_FSX 8
|
||||
#define SIM_ESP 9
|
||||
#define SIM_P3D 10
|
||||
|
||||
// Error numbers
|
||||
#define FSUIPC_ERR_OK 0
|
||||
#define FSUIPC_ERR_OPEN 1 // Attempt to Open when already Open
|
||||
#define FSUIPC_ERR_NOFS 2 // Cannot link to FSUIPC or WideClient
|
||||
#define FSUIPC_ERR_REGMSG 3 // Failed to Register common message with Windows
|
||||
#define FSUIPC_ERR_ATOM 4 // Failed to create Atom for mapping filename
|
||||
#define FSUIPC_ERR_MAP 5 // Failed to create a file mapping object
|
||||
#define FSUIPC_ERR_VIEW 6 // Failed to open a view to the file map
|
||||
#define FSUIPC_ERR_VERSION 7 // Incorrect version of FSUIPC, or not FSUIPC
|
||||
#define FSUIPC_ERR_WRONGFS 8 // Sim is not version requested
|
||||
#define FSUIPC_ERR_NOTOPEN 9 // Call cannot execute, link not Open
|
||||
#define FSUIPC_ERR_NODATA 10 // Call cannot execute: no requests accumulated
|
||||
#define FSUIPC_ERR_TIMEOUT 11 // IPC timed out all retries
|
||||
#define FSUIPC_ERR_SENDMSG 12 // IPC sendmessage failed all retries
|
||||
#define FSUIPC_ERR_DATA 13 // IPC request contains bad data
|
||||
#define FSUIPC_ERR_RUNNING 14 // Maybe running on WideClient, but FS not running on Server, or wrong FSUIPC
|
||||
#define FSUIPC_ERR_SIZE 15 // Read or Write request cannot be added, memory for Process is full
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Globals accessible from main code
|
||||
extern DWORD FSUIPC_Version; // HIWORD is 1000 x Version Number, minimum 1998
|
||||
// LOWORD is build letter, with a = 1 etc. For 1998 this must be at least 5 (1998e)
|
||||
extern DWORD FSUIPC_FS_Version;
|
||||
// FS98=1, FS2k=2, CFS2=3. See above.
|
||||
extern DWORD FSUIPC_Lib_Version;
|
||||
// HIWORD is 1000 x version, LOWORD is build letter, a = 1 etc.
|
||||
|
||||
// Library routines
|
||||
extern BOOL FSUIPC_Open(DWORD dwFSReq, DWORD *pdwResult); // For use externally (IPCuser.lib)
|
||||
extern BOOL FSUIPC_Open2(DWORD dwFSReq, DWORD *pdwResult, BYTE *pMem, DWORD dwSize); // For use internally (ModuleUser.lib)
|
||||
extern void FSUIPC_Close(void);
|
||||
extern BOOL FSUIPC_Read(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_ReadSpecial(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_Write(DWORD dwOffset, DWORD dwSize, void *pSrce, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_Process(DWORD *pdwResult);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _FSUIPC_H_
|
||||
338
src/plugins/simulator/fsuipc32/IPCuser.c
Normal file
338
src/plugins/simulator/fsuipc32/IPCuser.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/* IPCUSER.C User interface library for FSUIPC
|
||||
*******************************************************************************
|
||||
|
||||
Started: 28th November 2000
|
||||
|
||||
With acknowledgements to Adam Szofran (author of original FS6IPC).
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#define LIB_VERSION 2002 // 2.002
|
||||
#define MAX_SIZE 0x7F00 // Largest data (kept below 32k to avoid
|
||||
// any possible 16-bit sign problems)
|
||||
|
||||
#include "IPCuser.h"
|
||||
|
||||
/******************************************************************************
|
||||
IPC client stuff
|
||||
******************************************************************************/
|
||||
|
||||
DWORD FSUIPC_Version = 0;
|
||||
DWORD FSUIPC_FS_Version = 0;
|
||||
DWORD FSUIPC_Lib_Version = LIB_VERSION;
|
||||
|
||||
static HWND m_hWnd = 0; // FS6 window handle
|
||||
static UINT m_msg = 0; // id of registered window message
|
||||
static ATOM m_atom = 0; // global atom containing name of file-mapping object
|
||||
static HANDLE m_hMap = 0; // handle of file-mapping object
|
||||
static BYTE* m_pView = 0; // pointer to view of file-mapping object
|
||||
static BYTE* m_pNext = 0;
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Close
|
||||
******************************************************************************/
|
||||
|
||||
// Stop the client
|
||||
void FSUIPC_Close(void)
|
||||
{ m_hWnd = 0;
|
||||
m_msg = 0;
|
||||
|
||||
if (m_atom)
|
||||
{ GlobalDeleteAtom(m_atom);
|
||||
m_atom = 0;
|
||||
}
|
||||
|
||||
if (m_pView)
|
||||
{ UnmapViewOfFile((LPVOID)m_pView);
|
||||
m_pView = 0;
|
||||
}
|
||||
|
||||
if (m_hMap)
|
||||
{ CloseHandle(m_hMap);
|
||||
m_hMap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Open
|
||||
******************************************************************************/
|
||||
|
||||
// Start the client
|
||||
// return: TRUE if successful, FALSE otherwise
|
||||
BOOL FSUIPC_Open(DWORD dwFSReq, DWORD *pdwResult)
|
||||
{ wchar_t szName[MAX_PATH];
|
||||
static int nTry = 0;
|
||||
BOOL fWideFS = FALSE;
|
||||
int i = 0;
|
||||
|
||||
// abort if already started
|
||||
if (m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_OPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear version information, so know when connected
|
||||
FSUIPC_Version = FSUIPC_FS_Version = 0;
|
||||
|
||||
// Connect via FSUIPC, which is known to be FSUIPC's own
|
||||
// and isn't subject to user modificiation
|
||||
m_hWnd = FindWindowEx(NULL, NULL, L"UIPCMAIN", NULL);
|
||||
if (!m_hWnd)
|
||||
{ // If there's no UIPCMAIN, we may be using WideClient
|
||||
// which only simulates FS98
|
||||
m_hWnd = FindWindowEx(NULL, NULL, L"FS98MAIN", NULL);
|
||||
fWideFS = TRUE;
|
||||
if (!m_hWnd)
|
||||
{ *pdwResult = FSUIPC_ERR_NOFS;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// register the window message
|
||||
m_msg = RegisterWindowMessage(FS6IPC_MSGNAME1);
|
||||
if (m_msg == 0)
|
||||
{ *pdwResult = FSUIPC_ERR_REGMSG;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create the name of our file-mapping object
|
||||
nTry++; // Ensures a unique string is used in case user closes and reopens
|
||||
wsprintf(szName, FS6IPC_MSGNAME1 ":%X:%X", GetCurrentProcessId(), nTry);
|
||||
|
||||
// stuff the name into a global atom
|
||||
m_atom = GlobalAddAtom(szName);
|
||||
if (m_atom == 0)
|
||||
{ *pdwResult = FSUIPC_ERR_ATOM;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create the file-mapping object
|
||||
m_hMap = CreateFileMapping(
|
||||
(HANDLE)0xFFFFFFFF, // use system paging file
|
||||
NULL, // security
|
||||
PAGE_READWRITE, // protection
|
||||
0, MAX_SIZE+256, // size
|
||||
szName); // name
|
||||
|
||||
if ((m_hMap == 0) || (GetLastError() == ERROR_ALREADY_EXISTS))
|
||||
{ *pdwResult = FSUIPC_ERR_MAP;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// get a view of the file-mapping object
|
||||
m_pView = (BYTE*)MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if (m_pView == NULL)
|
||||
{ *pdwResult = FSUIPC_ERR_VIEW;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Okay, now determine FSUIPC version AND FS type
|
||||
m_pNext = m_pView;
|
||||
|
||||
// Try up to 5 times with a 100mSec rest between each
|
||||
// Note that WideClient returns zeroes initially, whilst waiting
|
||||
// for the Server to get the data
|
||||
while ((i++ < 5) && ((FSUIPC_Version == 0) || (FSUIPC_FS_Version == 0)))
|
||||
{ // Read FSUIPC version
|
||||
if (!FSUIPC_Read(0x3304, 4, &FSUIPC_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// and FS version and validity check pattern
|
||||
if (!FSUIPC_Read(0x3308, 4, &FSUIPC_FS_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Write our Library version number to a special read-only offset
|
||||
// This is to assist diagnosis from FSUIPC logging
|
||||
// But only do this on first try
|
||||
if ((i < 2) && !FSUIPC_Write(0x330a, 2, &FSUIPC_Lib_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Actually send the requests and get the responses ("process")
|
||||
if (!FSUIPC_Process(pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Maybe running on WideClient, and need another try
|
||||
Sleep(100); // Give it a chance
|
||||
}
|
||||
|
||||
// Only allow running on FSUIPC 1.998e or later
|
||||
// with correct check pattern 0xFADE
|
||||
if ((FSUIPC_Version < 0x19980005) || ((FSUIPC_FS_Version & 0xFFFF0000L) != 0xFADE0000))
|
||||
{ *pdwResult = fWideFS ? FSUIPC_ERR_RUNNING : FSUIPC_ERR_VERSION;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FSUIPC_FS_Version &= 0xffff; // Isolates the FS version number
|
||||
if (dwFSReq && (dwFSReq != FSUIPC_FS_Version)) // Optional user specific FS request
|
||||
{ *pdwResult = FSUIPC_ERR_WRONGFS;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Process
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Process(DWORD *pdwResult)
|
||||
{ DWORD dwError;
|
||||
DWORD *pdw;
|
||||
FS6IPC_READSTATEDATA_HDR *pHdrR;
|
||||
FS6IPC_WRITESTATEDATA_HDR *pHdrW;
|
||||
int i = 0;
|
||||
|
||||
if (!m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_pView == m_pNext)
|
||||
{ *pdwResult = FSUIPC_ERR_NODATA;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(m_pNext, 4); // Terminator
|
||||
m_pNext = m_pView;
|
||||
|
||||
// send the request (allow up to 9 tries)
|
||||
while ((++i < 10) && !SendMessageTimeout(
|
||||
m_hWnd, // FS6 window handle
|
||||
m_msg, // our registered message id
|
||||
m_atom, // wParam: name of file-mapping object
|
||||
0, // lParam: offset of request into file-mapping obj
|
||||
SMTO_BLOCK, // halt this thread until we get a response
|
||||
2000, // time out interval
|
||||
&dwError)) // return value
|
||||
{ Sleep(100); // Allow for things to happen
|
||||
}
|
||||
|
||||
if (i >= 10) // Failed all tries?
|
||||
{ *pdwResult = GetLastError() == 0 ? FSUIPC_ERR_TIMEOUT : FSUIPC_ERR_SENDMSG;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dwError != FS6IPC_MESSAGE_SUCCESS)
|
||||
{ *pdwResult = FSUIPC_ERR_DATA; // FSUIPC didn't like something in the data!
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Decode and store results of Read requests
|
||||
pdw = (DWORD *) m_pView;
|
||||
|
||||
while (*pdw)
|
||||
{ switch (*pdw)
|
||||
{ case FS6IPC_READSTATEDATA_ID:
|
||||
pHdrR = (FS6IPC_READSTATEDATA_HDR *) pdw;
|
||||
m_pNext += sizeof(FS6IPC_READSTATEDATA_HDR);
|
||||
if (pHdrR->pDest && pHdrR->nBytes)
|
||||
CopyMemory(pHdrR->pDest, m_pNext, pHdrR->nBytes);
|
||||
m_pNext += pHdrR->nBytes;
|
||||
break;
|
||||
|
||||
case FS6IPC_WRITESTATEDATA_ID:
|
||||
// This is a write, so there's no returned data to store
|
||||
pHdrW = (FS6IPC_WRITESTATEDATA_HDR *) pdw;
|
||||
m_pNext += sizeof(FS6IPC_WRITESTATEDATA_HDR) + pHdrW->nBytes;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Error! So terminate the scan
|
||||
*pdw = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pdw = (DWORD *) m_pNext;
|
||||
}
|
||||
|
||||
m_pNext = m_pView;
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Read
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Read(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pdwResult)
|
||||
{ FS6IPC_READSTATEDATA_HDR *pHdr = (FS6IPC_READSTATEDATA_HDR *) m_pNext;
|
||||
|
||||
// Check link is open
|
||||
if (!m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check have space for this request (including terminator)
|
||||
if (((m_pNext - m_pView) + 4 + (dwSize + sizeof(FS6IPC_READSTATEDATA_HDR))) > MAX_SIZE)
|
||||
{ *pdwResult = FSUIPC_ERR_SIZE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Initialise header for read request
|
||||
pHdr->dwId = FS6IPC_READSTATEDATA_ID;
|
||||
pHdr->dwOffset = dwOffset;
|
||||
pHdr->nBytes = dwSize;
|
||||
pHdr->pDest = (BYTE *) pDest;
|
||||
|
||||
// Zero the reception area, so rubbish won't be returned
|
||||
if (dwSize) ZeroMemory(&m_pNext[sizeof(FS6IPC_READSTATEDATA_HDR)], dwSize);
|
||||
|
||||
// Update the pointer ready for more data
|
||||
m_pNext += sizeof(FS6IPC_READSTATEDATA_HDR) + dwSize;
|
||||
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Write
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Write(DWORD dwOffset, DWORD dwSize, void *pSrce, DWORD *pdwResult)
|
||||
{ FS6IPC_WRITESTATEDATA_HDR *pHdr = (FS6IPC_WRITESTATEDATA_HDR *) m_pNext;
|
||||
|
||||
// check link is open
|
||||
if (!m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check have spce for this request (including terminator)
|
||||
if (((m_pNext - m_pView) + 4 + (dwSize + sizeof(FS6IPC_WRITESTATEDATA_HDR))) > MAX_SIZE)
|
||||
{ *pdwResult = FSUIPC_ERR_SIZE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Initialise header for write request
|
||||
pHdr->dwId = FS6IPC_WRITESTATEDATA_ID;
|
||||
pHdr->dwOffset = dwOffset;
|
||||
pHdr->nBytes = dwSize;
|
||||
|
||||
// Copy in the data to be written
|
||||
if (dwSize) CopyMemory(&m_pNext[sizeof(FS6IPC_WRITESTATEDATA_HDR)], pSrce, dwSize);
|
||||
|
||||
// Update the pointer ready for more data
|
||||
m_pNext += sizeof(FS6IPC_WRITESTATEDATA_HDR) + dwSize;
|
||||
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
End of IPCuser module
|
||||
******************************************************************************/
|
||||
29
src/plugins/simulator/fsuipc32/IPCuser.h
Normal file
29
src/plugins/simulator/fsuipc32/IPCuser.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "FSUIPC_User.h"
|
||||
|
||||
#define FS6IPC_MSGNAME1 L"FsasmLib:IPC"
|
||||
|
||||
#define FS6IPC_MESSAGE_SUCCESS 1
|
||||
#define FS6IPC_MESSAGE_FAILURE 0
|
||||
|
||||
// IPC message types
|
||||
#define FS6IPC_READSTATEDATA_ID 1
|
||||
#define FS6IPC_WRITESTATEDATA_ID 2
|
||||
|
||||
// read request structure
|
||||
typedef struct tagFS6IPC_READSTATEDATA_HDR
|
||||
{
|
||||
DWORD dwId; // FS6IPC_READSTATEDATA_ID
|
||||
DWORD dwOffset; // state table offset
|
||||
DWORD nBytes; // number of bytes of state data to read
|
||||
void* pDest; // destination buffer for data (client use only)
|
||||
} FS6IPC_READSTATEDATA_HDR;
|
||||
|
||||
// write request structure
|
||||
typedef struct tagFS6IPC_WRITESTATEDATA_HDR
|
||||
{
|
||||
DWORD dwId; // FS6IPC_WRITESTATEDATA_ID
|
||||
DWORD dwOffset; // state table offset
|
||||
DWORD nBytes; // number of bytes of state data to write
|
||||
} FS6IPC_WRITESTATEDATA_HDR;
|
||||
120
src/plugins/simulator/fsuipc32/NewWeather.h
Normal file
120
src/plugins/simulator/fsuipc32/NewWeather.h
Normal file
@@ -0,0 +1,120 @@
|
||||
// Wind structure (size 16 bytes)
|
||||
typedef struct _NewWind
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
unsigned short Speed; // Knots
|
||||
unsigned short Gust; // Max gust speed difference, knots
|
||||
unsigned short Direction; // usual 65536 = 360 units
|
||||
unsigned char Turbulence; // 0-4
|
||||
unsigned char Shear; // 0-3
|
||||
unsigned short Variance; // direction variability, same units as Direction
|
||||
unsigned short SpeedFract; // 1/65536ths of Knots, for more accurate vector calcs
|
||||
unsigned short GapAbove; // Metres
|
||||
// This is the gap from the top of surface altitude to first layer's base
|
||||
// GapAbove is ignored in layers other than the surface layer, and needs
|
||||
// FSUIC 4.748 or 3.998k minimum.
|
||||
} NewWind;
|
||||
|
||||
// Visibility structure (size 8 bytes)
|
||||
typedef struct _NewVis
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
signed short LowerAlt; // Metres
|
||||
unsigned short Range; // in 1/100ths sm
|
||||
unsigned short Spare;
|
||||
} NewVis;
|
||||
|
||||
// Cloud structure (size 16 bytes)
|
||||
typedef struct _NewCloud
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
unsigned short LowerAlt; // Metres
|
||||
unsigned short Deviation; // Metres
|
||||
unsigned char Coverage; // Octas, 0-8
|
||||
unsigned char Type; // 1-10
|
||||
unsigned char Turbulence; // 0-4
|
||||
unsigned char Icing; // 0-4
|
||||
signed short PrecipBase; // Metres
|
||||
unsigned char PrecipType; // 0-2
|
||||
unsigned char PrecipRate; // 0-5
|
||||
unsigned char TopShape; // ?
|
||||
unsigned char Spare;
|
||||
} NewCloud;
|
||||
|
||||
// Temperature structure (size 8 bytes)
|
||||
typedef struct _NewTemp
|
||||
{ unsigned short Alt; // Metres
|
||||
short Day; // Degrees C
|
||||
short DayNightVar; // Degrees C
|
||||
short DewPoint; // Degrees C
|
||||
} NewTemp;
|
||||
|
||||
// Pressure structure (size 4 bytes)
|
||||
typedef struct _NewPress
|
||||
{ unsigned short Pressure; // 16 x mb
|
||||
short Drift; // ? Maybe
|
||||
} NewPress;
|
||||
|
||||
// Structure mapped to FSUIPC offsets
|
||||
// C000, C400, C800 and CC00
|
||||
typedef struct _NewWeather
|
||||
{ unsigned short uCommand; // C000 C400 C800 CC00
|
||||
unsigned short uFlags; // C002 C402 C802 CC02 // Not used until FSX - see below
|
||||
unsigned int ulSignature; // C004 C404 C804 CC04
|
||||
char chICAO[4]; // C008 C408 C808 CC08
|
||||
unsigned short uDynamics; // C00C C40C C80C CC0C // 0=none, 4=extreme
|
||||
unsigned short uSeconds; // C00E C40E C80E CC0E // FSX only -- see below
|
||||
double dLatitude; // C010 C410 C810 CC10 // LLA zero for GLOB or unknown ICAO
|
||||
double dLongitude; // C018 C418 C818 CC18
|
||||
int nElevation; // C020 C420 C820 CC20 // metres * 65536
|
||||
unsigned int ulTimeStamp; // C024 C424 C824 CC24 // mSecs since start of session
|
||||
NewPress Press; // C028 C428 C828 CC28
|
||||
NewVis Vis; // C02C C42C C82C CC2C // Base Vis -- for upper Vis layers see
|
||||
int nTempCtr; // C034 C434 C834 CC34 // Number of temperature layers
|
||||
NewTemp Temp[24]; // C038 C438 C838 CC38
|
||||
int nWindsCtr; // C0F8 C4F8 C8F8 CCF8 // Number of wind layers
|
||||
NewWind Wind[24]; // C0FC C4FC C8FC CCFC
|
||||
int nCloudsCtr; // C27C C67C CA7C CE7C // Number of Cloud layers (max 16 in FSX, was 24
|
||||
NewCloud Cloud[16]; // C280 C680 CA80 CE80
|
||||
char chUTCstamp[6]; // C380 C780 CB80 CF80 // UTC time stamp on METAR (internal use)
|
||||
unsigned short fWriteback; // C386 C786 CB86 CF86 // Flags for writing back to FSX (internal use only)
|
||||
unsigned long ulSettingTimeStamp; // C388 c788 CB88 CF88 // Timestamp METAR sent (internal use)
|
||||
int nUpperVisCtr; // C38C C78C CB8C CF8C // Number of upper Vis layer (new in FSX)
|
||||
NewVis UpperVis[12]; // C390 C790 CB90 CF90
|
||||
unsigned short uSpare[8]; // C3F0 C7F0 CBF0 CFF0
|
||||
} NewWeather;
|
||||
|
||||
#define MAXVISLAYERS 12
|
||||
#define MAXTEMPLAYERS 24
|
||||
#define MAXWINDLAYERS 24
|
||||
#define MAXCLOUDLAYERS 16
|
||||
|
||||
// Commands (for set weather area only)
|
||||
#define NW_SET 1 // Set weather via FSUIPC user filters
|
||||
#define NW_SETEXACT 2 // Set weather bypassing user filters
|
||||
#define NW_CLEAR 3 // Clear all weather, but leave dynamic setting alone
|
||||
#define NW_DYNAMICS 4 // Set weather dynamics (from uDynamics value)
|
||||
#define NW_GLOBAL 5 // (FSX) Put FS into Global weather mode
|
||||
// You sohuld write only 'GLOB' weather after this, which will be applied everywhere.
|
||||
|
||||
#define NW_METAR 128 // DON'T USE! (Internal setting when weather written via string at B000. (FSX))
|
||||
|
||||
#define NW_SET_PENDING 257 // Set weather using filters, but don't activate in FS yet
|
||||
#define NW_SETEXACT_PENDING 258 // Set weather bypassing filters, but don't activate in FS yet
|
||||
|
||||
#define NW_ACTIVATE 256 // Activate pending weather settings
|
||||
|
||||
// Flags for FSX weather setting
|
||||
#define NWF_SECONDS 1
|
||||
/* Set this flag if "Seconds" value is to be used in setting weather in FSX
|
||||
This applies to weather set via NWI values or via the NEXT Metar string
|
||||
written to B000. It's a "one shot" flag, cleared after use.
|
||||
|
||||
The Seconds value determines whether the weather change is effective
|
||||
immediately or after a delay, gradually "blending" into the existing
|
||||
weather.
|
||||
*/
|
||||
|
||||
// The 4 distinct areas are used as follows:
|
||||
// C000 - read only, maintains current interpolated weather at aircraft
|
||||
// C400 - read only, maintains last written global weather values
|
||||
// C800 - write area to set weather according to Command, flags, etc etc.
|
||||
// CC00 - selected read (via signature + ICAO), reads weather at weather station or GLOB
|
||||
|
||||
20
src/plugins/simulator/fsuipc32/fsuipc32.pro
Normal file
20
src/plugins/simulator/fsuipc32/fsuipc32.pro
Normal file
@@ -0,0 +1,20 @@
|
||||
load(common_pre)
|
||||
|
||||
requires(equals(WORD_SIZE,32))
|
||||
|
||||
QT += core dbus xml network
|
||||
|
||||
TARGET = fsuipc
|
||||
TEMPLATE = lib
|
||||
|
||||
CONFIG += staticlib
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
HEADERS += *.h
|
||||
SOURCES += *.c
|
||||
|
||||
DESTDIR = $$DestRoot/lib
|
||||
|
||||
load(common_post)
|
||||
62
src/plugins/simulator/fsuipc64/FSUIPC_User64.h
Normal file
62
src/plugins/simulator/fsuipc64/FSUIPC_User64.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef _FSUIPC_H_
|
||||
#define _FSUIPC_H_
|
||||
|
||||
// Supported Sims
|
||||
#define SIM_ANY 0
|
||||
#define SIM_FS98 1
|
||||
#define SIM_FS2K 2
|
||||
#define SIM_CFS2 3
|
||||
#define SIM_CFS1 4
|
||||
#define SIM_FLY 5
|
||||
#define SIM_FS2K2 6
|
||||
#define SIM_FS2K4 7
|
||||
#define SIM_FSX 8
|
||||
#define SIM_ESP 9
|
||||
#define SIM_P3D 10
|
||||
#define SIM_FSX64 11
|
||||
#define SIM_P3D64 12
|
||||
|
||||
// Error numbers
|
||||
#define FSUIPC_ERR_OK 0
|
||||
#define FSUIPC_ERR_OPEN 1 // Attempt to Open when already Open
|
||||
#define FSUIPC_ERR_NOFS 2 // Cannot link to FSUIPC or WideClient
|
||||
#define FSUIPC_ERR_REGMSG 3 // Failed to Register common message with Windows
|
||||
#define FSUIPC_ERR_ATOM 4 // Failed to create Atom for mapping filename
|
||||
#define FSUIPC_ERR_MAP 5 // Failed to create a file mapping object
|
||||
#define FSUIPC_ERR_VIEW 6 // Failed to open a view to the file map
|
||||
#define FSUIPC_ERR_VERSION 7 // Incorrect version of FSUIPC, or not FSUIPC
|
||||
#define FSUIPC_ERR_WRONGFS 8 // Sim is not version requested
|
||||
#define FSUIPC_ERR_NOTOPEN 9 // Call cannot execute, link not Open
|
||||
#define FSUIPC_ERR_NODATA 10 // Call cannot execute: no requests accumulated
|
||||
#define FSUIPC_ERR_TIMEOUT 11 // IPC timed out all retries
|
||||
#define FSUIPC_ERR_SENDMSG 12 // IPC sendmessage failed all retries
|
||||
#define FSUIPC_ERR_DATA 13 // IPC request contains bad data
|
||||
#define FSUIPC_ERR_RUNNING 14 // Maybe running on WideClient, but FS not running on Server, or wrong FSUIPC
|
||||
#define FSUIPC_ERR_SIZE 15 // Read or Write request cannot be added, memory for Process is full
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Globals accessible from main code
|
||||
extern DWORD FSUIPC_Version; // HIWORD is 1000 x Version Number, minimum 1998
|
||||
// LOWORD is build letter, with a = 1 etc. For 1998 this must be at least 5 (1998e)
|
||||
extern DWORD FSUIPC_FS_Version;
|
||||
// FS98=1, FS2k=2, CFS2=3. See above.
|
||||
extern DWORD FSUIPC_Lib_Version;
|
||||
// HIWORD is 1000 x version, LOWORD is build letter, a = 1 etc.
|
||||
|
||||
// Library routines
|
||||
extern BOOL FSUIPC_Open(DWORD dwFSReq, DWORD *pdwResult); // For use externally (IPCuser.lib)
|
||||
extern BOOL FSUIPC_Open2(DWORD dwFSReq, DWORD *pdwResult, BYTE *pMem, DWORD dwSize); // For use internally (ModuleUser.lib)
|
||||
extern void FSUIPC_Close(void);
|
||||
extern BOOL FSUIPC_Read(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_ReadSpecial(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_Write(DWORD dwOffset, DWORD dwSize, void *pSrce, DWORD *pdwResult);
|
||||
extern BOOL FSUIPC_Process(DWORD *pdwResult);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // _FSUIPC_H_
|
||||
347
src/plugins/simulator/fsuipc64/IPCuser64.c
Normal file
347
src/plugins/simulator/fsuipc64/IPCuser64.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/* IPCUSER64.C User interface library for FSUIPC
|
||||
*******************************************************************************
|
||||
|
||||
Started: 28th November 2000
|
||||
|
||||
With acknowledgements to Adam Szofran (author of original FS6IPC).
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#define LIB_VERSION 2002 // 2.002
|
||||
#define MAX_SIZE 0x7F00 // Largest data (kept below 32k to avoid
|
||||
// any possible 16-bit sign problems)
|
||||
|
||||
#include "IPCuser64.h"
|
||||
#include "FSUIPC_User64.h"
|
||||
|
||||
#define FS6IPC_MSGNAME1 L"FsasmLib:IPC"
|
||||
|
||||
/******************************************************************************
|
||||
IPC client stuff
|
||||
******************************************************************************/
|
||||
|
||||
DWORD FSUIPC_Version = 0;
|
||||
DWORD FSUIPC_FS_Version = 0;
|
||||
DWORD FSUIPC_Lib_Version = LIB_VERSION;
|
||||
|
||||
static HWND m_hWnd = 0; // FS6 window handle
|
||||
static UINT m_msg = 0; // id of registered window message
|
||||
static ATOM m_atom = 0; // global atom containing name of file-mapping object
|
||||
static HANDLE m_hMap = 0; // handle of file-mapping object
|
||||
static BYTE* m_pView = 0; // pointer to view of file-mapping object
|
||||
static BYTE* m_pNext = 0;
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Close
|
||||
******************************************************************************/
|
||||
|
||||
// Stop the client
|
||||
void FSUIPC_Close(void)
|
||||
{ m_hWnd = 0;
|
||||
m_msg = 0;
|
||||
|
||||
if (m_atom)
|
||||
{ GlobalDeleteAtom(m_atom);
|
||||
m_atom = 0;
|
||||
}
|
||||
|
||||
if (m_pView)
|
||||
{ UnmapViewOfFile((LPVOID)m_pView);
|
||||
m_pView = 0;
|
||||
}
|
||||
|
||||
if (m_hMap)
|
||||
{ CloseHandle(m_hMap);
|
||||
m_hMap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Open
|
||||
******************************************************************************/
|
||||
|
||||
// Start the client
|
||||
// return: TRUE if successful, FALSE otherwise
|
||||
BOOL FSUIPC_Open(DWORD dwFSReq, DWORD *pdwResult)
|
||||
{ wchar_t szName[MAX_PATH];
|
||||
static int nTry = 0;
|
||||
int i = 0;
|
||||
|
||||
// abort if already started
|
||||
if (m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_OPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Clear version information, so know when connected
|
||||
FSUIPC_Version = FSUIPC_FS_Version = 0;
|
||||
|
||||
// Connect via FSUIPC, which is known to be FSUIPC's own
|
||||
// and isn't subject to user modificiation
|
||||
m_hWnd = FindWindowEx(NULL, NULL, L"UIPCMAIN", NULL);
|
||||
if (!m_hWnd)
|
||||
{ *pdwResult = FSUIPC_ERR_NOFS;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// register the window message
|
||||
m_msg = RegisterWindowMessage(FS6IPC_MSGNAME1);
|
||||
if (m_msg == 0)
|
||||
{ *pdwResult = FSUIPC_ERR_REGMSG;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create the name of our file-mapping object
|
||||
nTry++; // Ensures a unique string is used in case user closes and reopens
|
||||
wsprintf(szName, FS6IPC_MSGNAME1 ":%X:%X", GetCurrentProcessId(), nTry);
|
||||
|
||||
// stuff the name into a global atom
|
||||
m_atom = GlobalAddAtom(szName);
|
||||
if (m_atom == 0)
|
||||
{ *pdwResult = FSUIPC_ERR_ATOM;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create the file-mapping object
|
||||
m_hMap = CreateFileMapping(
|
||||
INVALID_HANDLE_VALUE, // use system paging file
|
||||
NULL, // security
|
||||
PAGE_READWRITE, // protection
|
||||
0, MAX_SIZE+256, // size
|
||||
szName); // name
|
||||
|
||||
if ((m_hMap == 0) || (GetLastError() == ERROR_ALREADY_EXISTS))
|
||||
{ *pdwResult = FSUIPC_ERR_MAP;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// get a view of the file-mapping object
|
||||
m_pView = (BYTE*)MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if (m_pView == NULL)
|
||||
{ *pdwResult = FSUIPC_ERR_VIEW;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Okay, now determine FSUIPC version AND FS type
|
||||
m_pNext = m_pView;
|
||||
|
||||
// Try up to 5 times with a 100mSec rest between each
|
||||
while ((i++ < 5) && ((FSUIPC_Version == 0) || (FSUIPC_FS_Version == 0)))
|
||||
{ // Read FSUIPC version
|
||||
if (!FSUIPC_Read(0x3304, 4, &FSUIPC_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// and FS version and validity check pattern
|
||||
if (!FSUIPC_Read(0x3308, 4, &FSUIPC_FS_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Write our Library version number to a special read-only offset
|
||||
// This is to assist diagnosis from FSUIPC logging
|
||||
// But only do this on first try
|
||||
if ((i < 2) && !FSUIPC_Write(0x330a, 2, &FSUIPC_Lib_Version, pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Actually send the requests and get the responses ("process")
|
||||
if (!FSUIPC_Process(pdwResult))
|
||||
{ FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Maybe running on WideClient, and need another try
|
||||
Sleep(100); // Give it a chance
|
||||
}
|
||||
|
||||
// Only allow running on FSUIPC 1.998e or later
|
||||
// with correct check pattern 0xFADE
|
||||
if ((FSUIPC_Version < 0x19980005) || ((FSUIPC_FS_Version & 0xFFFF0000L) != 0xFADE0000))
|
||||
{ *pdwResult = FSUIPC_ERR_VERSION;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FSUIPC_FS_Version &= 0xffff; // Isolates the FS version number
|
||||
if (dwFSReq && (dwFSReq != FSUIPC_FS_Version)) // Optional user specific FS request
|
||||
{ *pdwResult = FSUIPC_ERR_WRONGFS;
|
||||
FSUIPC_Close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Process
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Process(DWORD *pdwResult)
|
||||
{ DWORD_PTR dwError;
|
||||
DWORD *pdw;
|
||||
F64IPC_READSTATEDATA_HDR *pHdrR;
|
||||
FS6IPC_WRITESTATEDATA_HDR *pHdrW;
|
||||
int i = 0;
|
||||
|
||||
if (!m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_pView == m_pNext)
|
||||
{ *pdwResult = FSUIPC_ERR_NODATA;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(m_pNext, 4); // Terminator
|
||||
m_pNext = m_pView;
|
||||
|
||||
// send the request (allow up to 9 tries)
|
||||
while ((++i < 10) && !SendMessageTimeout(
|
||||
m_hWnd, // FS6 window handle
|
||||
m_msg, // our registered message id
|
||||
m_atom, // wParam: name of file-mapping object
|
||||
0, // lParam: offset of request into file-mapping obj
|
||||
SMTO_BLOCK, // halt this thread until we get a response
|
||||
2000, // time out interval
|
||||
&dwError)) // return value
|
||||
{ Sleep(100); // Allow for things to happen
|
||||
}
|
||||
|
||||
if (i >= 10) // Failed all tries?
|
||||
{ *pdwResult = GetLastError() == 0 ? FSUIPC_ERR_TIMEOUT : FSUIPC_ERR_SENDMSG;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dwError != FS6IPC_MESSAGE_SUCCESS)
|
||||
{ *pdwResult = FSUIPC_ERR_DATA; // FSUIPC didn't like something in the data!
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Decode and store results of Read requests
|
||||
pdw = (DWORD *) m_pView;
|
||||
|
||||
while (*pdw)
|
||||
{ switch (*pdw)
|
||||
{ case F64IPC_READSTATEDATA_ID:
|
||||
pHdrR = (F64IPC_READSTATEDATA_HDR *) pdw;
|
||||
m_pNext += sizeof(F64IPC_READSTATEDATA_HDR);
|
||||
if (pHdrR->pDest && pHdrR->nBytes)
|
||||
CopyMemory(pHdrR->pDest, m_pNext, pHdrR->nBytes);
|
||||
m_pNext += pHdrR->nBytes;
|
||||
break;
|
||||
|
||||
case FS6IPC_WRITESTATEDATA_ID:
|
||||
// This is a write, so there's no returned data to store
|
||||
pHdrW = (FS6IPC_WRITESTATEDATA_HDR *) pdw;
|
||||
m_pNext += sizeof(FS6IPC_WRITESTATEDATA_HDR) + pHdrW->nBytes;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Error! So terminate the scan
|
||||
*pdw = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pdw = (DWORD *) m_pNext;
|
||||
}
|
||||
|
||||
m_pNext = m_pView;
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_ReadCommon
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_ReadCommon(BOOL fSpecial, DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pResult)
|
||||
{ F64IPC_READSTATEDATA_HDR *pHdr = (F64IPC_READSTATEDATA_HDR *) m_pNext;
|
||||
|
||||
if (!m_pView)
|
||||
{ *pResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (((m_pNext - m_pView) + (dwSize + sizeof(F64IPC_READSTATEDATA_HDR))) > MAX_SIZE)
|
||||
{ *pResult = FSUIPC_ERR_SIZE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pHdr->dwId = F64IPC_READSTATEDATA_ID;
|
||||
pHdr->dwOffset = dwOffset;
|
||||
pHdr->nBytes = dwSize;
|
||||
pHdr->pDest = (BYTE *) pDest;
|
||||
|
||||
// Initialise the reception area, so rubbish won't be returned
|
||||
if (dwSize)
|
||||
{ if (fSpecial) CopyMemory(&m_pNext[sizeof(F64IPC_READSTATEDATA_HDR)], pDest, dwSize);
|
||||
else ZeroMemory(&m_pNext[sizeof(F64IPC_READSTATEDATA_HDR)], dwSize);
|
||||
}
|
||||
|
||||
m_pNext += sizeof(F64IPC_READSTATEDATA_HDR) + dwSize;
|
||||
|
||||
*pResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Read
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Read(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pResult)
|
||||
{ return FSUIPC_ReadCommon(FALSE, dwOffset, dwSize, pDest, pResult);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_ReadSpecial
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_ReadSpecial(DWORD dwOffset, DWORD dwSize, void *pDest, DWORD *pResult)
|
||||
{ return FSUIPC_ReadCommon(TRUE, dwOffset, dwSize, pDest, pResult);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
FSUIPC_Write
|
||||
******************************************************************************/
|
||||
|
||||
BOOL FSUIPC_Write(DWORD dwOffset, DWORD dwSize, void *pSrce, DWORD *pdwResult)
|
||||
{ FS6IPC_WRITESTATEDATA_HDR *pHdr = (FS6IPC_WRITESTATEDATA_HDR *) m_pNext;
|
||||
|
||||
// check link is open
|
||||
if (!m_pView)
|
||||
{ *pdwResult = FSUIPC_ERR_NOTOPEN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check have spce for this request (including terminator)
|
||||
if (((m_pNext - m_pView) + 4 + (dwSize + sizeof(FS6IPC_WRITESTATEDATA_HDR))) > MAX_SIZE)
|
||||
{ *pdwResult = FSUIPC_ERR_SIZE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Initialise header for write request
|
||||
pHdr->dwId = FS6IPC_WRITESTATEDATA_ID;
|
||||
pHdr->dwOffset = dwOffset;
|
||||
pHdr->nBytes = dwSize;
|
||||
|
||||
// Copy in the data to be written
|
||||
if (dwSize) CopyMemory(&m_pNext[sizeof(FS6IPC_WRITESTATEDATA_HDR)], pSrce, dwSize);
|
||||
|
||||
// Update the pointer ready for more data
|
||||
m_pNext += sizeof(FS6IPC_WRITESTATEDATA_HDR) + dwSize;
|
||||
|
||||
*pdwResult = FSUIPC_ERR_OK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
End of IPCuser64 module
|
||||
******************************************************************************/
|
||||
32
src/plugins/simulator/fsuipc64/IPCuser64.h
Normal file
32
src/plugins/simulator/fsuipc64/IPCuser64.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "FSUIPC_User64.h"
|
||||
|
||||
#define FS6IPC_MESSAGE_SUCCESS 1
|
||||
#define FS6IPC_MESSAGE_FAILURE 0
|
||||
|
||||
// IPC message types
|
||||
#define F64IPC_READSTATEDATA_ID 4
|
||||
#define FS6IPC_WRITESTATEDATA_ID 2
|
||||
|
||||
#pragma pack (push, r1, 1)
|
||||
|
||||
// read request structure
|
||||
typedef struct tagF64IPC_READSTATEDATA_HDR
|
||||
{
|
||||
DWORD dwId; // F64IPC_READSTATEDATA_ID
|
||||
DWORD dwOffset; // state table offset
|
||||
DWORD nBytes; // number of bytes of state data to read
|
||||
void* pDest; // destination buffer for data (client use only)
|
||||
} F64IPC_READSTATEDATA_HDR;
|
||||
|
||||
// write request structure
|
||||
typedef struct tagFS6IPC_WRITESTATEDATA_HDR
|
||||
{
|
||||
DWORD dwId; // FS6IPC_WRITESTATEDATA_ID
|
||||
DWORD dwOffset; // state table offset
|
||||
DWORD nBytes; // number of bytes of state data to write
|
||||
} FS6IPC_WRITESTATEDATA_HDR;
|
||||
|
||||
#pragma pack (pop, r1)
|
||||
|
||||
120
src/plugins/simulator/fsuipc64/NewWeather.h
Normal file
120
src/plugins/simulator/fsuipc64/NewWeather.h
Normal file
@@ -0,0 +1,120 @@
|
||||
// Wind structure (size 16 bytes)
|
||||
typedef struct _NewWind
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
unsigned short Speed; // Knots
|
||||
unsigned short Gust; // Max gust speed difference, knots
|
||||
unsigned short Direction; // usual 65536 = 360 units
|
||||
unsigned char Turbulence; // 0-4
|
||||
unsigned char Shear; // 0-3
|
||||
unsigned short Variance; // direction variability, same units as Direction
|
||||
unsigned short SpeedFract; // 1/65536ths of Knots, for more accurate vector calcs
|
||||
unsigned short GapAbove; // Metres
|
||||
// This is the gap from the top of surface altitude to first layer's base
|
||||
// GapAbove is ignored in layers other than the surface layer, and needs
|
||||
// FSUIC 4.748 or 3.998k minimum.
|
||||
} NewWind;
|
||||
|
||||
// Visibility structure (size 8 bytes)
|
||||
typedef struct _NewVis
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
signed short LowerAlt; // Metres
|
||||
unsigned short Range; // in 1/100ths sm
|
||||
unsigned short Spare;
|
||||
} NewVis;
|
||||
|
||||
// Cloud structure (size 16 bytes)
|
||||
typedef struct _NewCloud
|
||||
{ unsigned short UpperAlt; // Metres
|
||||
unsigned short LowerAlt; // Metres
|
||||
unsigned short Deviation; // Metres
|
||||
unsigned char Coverage; // Octas, 0-8
|
||||
unsigned char Type; // 1-10
|
||||
unsigned char Turbulence; // 0-4
|
||||
unsigned char Icing; // 0-4
|
||||
signed short PrecipBase; // Metres
|
||||
unsigned char PrecipType; // 0-2
|
||||
unsigned char PrecipRate; // 0-5
|
||||
unsigned char TopShape; // ?
|
||||
unsigned char Spare;
|
||||
} NewCloud;
|
||||
|
||||
// Temperature structure (size 8 bytes)
|
||||
typedef struct _NewTemp
|
||||
{ unsigned short Alt; // Metres
|
||||
short Day; // Degrees C
|
||||
short DayNightVar; // Degrees C
|
||||
short DewPoint; // Degrees C
|
||||
} NewTemp;
|
||||
|
||||
// Pressure structure (size 4 bytes)
|
||||
typedef struct _NewPress
|
||||
{ unsigned short Pressure; // 16 x mb
|
||||
short Drift; // ? Maybe
|
||||
} NewPress;
|
||||
|
||||
// Structure mapped to FSUIPC offsets
|
||||
// C000, C400, C800 and CC00
|
||||
typedef struct _NewWeather
|
||||
{ unsigned short uCommand; // C000 C400 C800 CC00
|
||||
unsigned short uFlags; // C002 C402 C802 CC02 // Not used until FSX - see below
|
||||
unsigned int ulSignature; // C004 C404 C804 CC04
|
||||
char chICAO[4]; // C008 C408 C808 CC08
|
||||
unsigned short uDynamics; // C00C C40C C80C CC0C // 0=none, 4=extreme
|
||||
unsigned short uSeconds; // C00E C40E C80E CC0E // FSX only -- see below
|
||||
double dLatitude; // C010 C410 C810 CC10 // LLA zero for GLOB or unknown ICAO
|
||||
double dLongitude; // C018 C418 C818 CC18
|
||||
int nElevation; // C020 C420 C820 CC20 // metres * 65536
|
||||
unsigned int ulTimeStamp; // C024 C424 C824 CC24 // mSecs since start of session
|
||||
NewPress Press; // C028 C428 C828 CC28
|
||||
NewVis Vis; // C02C C42C C82C CC2C // Base Vis -- for upper Vis layers see
|
||||
int nTempCtr; // C034 C434 C834 CC34 // Number of temperature layers
|
||||
NewTemp Temp[24]; // C038 C438 C838 CC38
|
||||
int nWindsCtr; // C0F8 C4F8 C8F8 CCF8 // Number of wind layers
|
||||
NewWind Wind[24]; // C0FC C4FC C8FC CCFC
|
||||
int nCloudsCtr; // C27C C67C CA7C CE7C // Number of Cloud layers (max 16 in FSX, was 24
|
||||
NewCloud Cloud[16]; // C280 C680 CA80 CE80
|
||||
char chUTCstamp[6]; // C380 C780 CB80 CF80 // UTC time stamp on METAR (internal use)
|
||||
unsigned short fWriteback; // C386 C786 CB86 CF86 // Flags for writing back to FSX (internal use only)
|
||||
unsigned long ulSettingTimeStamp; // C388 c788 CB88 CF88 // Timestamp METAR sent (internal use)
|
||||
int nUpperVisCtr; // C38C C78C CB8C CF8C // Number of upper Vis layer (new in FSX)
|
||||
NewVis UpperVis[12]; // C390 C790 CB90 CF90
|
||||
unsigned short uSpare[8]; // C3F0 C7F0 CBF0 CFF0
|
||||
} NewWeather;
|
||||
|
||||
#define MAXVISLAYERS 12
|
||||
#define MAXTEMPLAYERS 24
|
||||
#define MAXWINDLAYERS 24
|
||||
#define MAXCLOUDLAYERS 16
|
||||
|
||||
// Commands (for set weather area only)
|
||||
#define NW_SET 1 // Set weather via FSUIPC user filters
|
||||
#define NW_SETEXACT 2 // Set weather bypassing user filters
|
||||
#define NW_CLEAR 3 // Clear all weather, but leave dynamic setting alone
|
||||
#define NW_DYNAMICS 4 // Set weather dynamics (from uDynamics value)
|
||||
#define NW_GLOBAL 5 // (FSX) Put FS into Global weather mode
|
||||
// You sohuld write only 'GLOB' weather after this, which will be applied everywhere.
|
||||
|
||||
#define NW_METAR 128 // DON'T USE! (Internal setting when weather written via string at B000. (FSX))
|
||||
|
||||
#define NW_SET_PENDING 257 // Set weather using filters, but don't activate in FS yet
|
||||
#define NW_SETEXACT_PENDING 258 // Set weather bypassing filters, but don't activate in FS yet
|
||||
|
||||
#define NW_ACTIVATE 256 // Activate pending weather settings
|
||||
|
||||
// Flags for FSX weather setting
|
||||
#define NWF_SECONDS 1
|
||||
/* Set this flag if "Seconds" value is to be used in setting weather in FSX
|
||||
This applies to weather set via NWI values or via the NEXT Metar string
|
||||
written to B000. It's a "one shot" flag, cleared after use.
|
||||
|
||||
The Seconds value determines whether the weather change is effective
|
||||
immediately or after a delay, gradually "blending" into the existing
|
||||
weather.
|
||||
*/
|
||||
|
||||
// The 4 distinct areas are used as follows:
|
||||
// C000 - read only, maintains current interpolated weather at aircraft
|
||||
// C400 - read only, maintains last written global weather values
|
||||
// C800 - write area to set weather according to Command, flags, etc etc.
|
||||
// CC00 - selected read (via signature + ICAO), reads weather at weather station or GLOB
|
||||
|
||||
20
src/plugins/simulator/fsuipc64/fsuipc64.pro
Normal file
20
src/plugins/simulator/fsuipc64/fsuipc64.pro
Normal file
@@ -0,0 +1,20 @@
|
||||
load(common_pre)
|
||||
|
||||
requires(equals(WORD_SIZE,64))
|
||||
|
||||
QT += core dbus xml network
|
||||
|
||||
TARGET = fsuipc
|
||||
TEMPLATE = lib
|
||||
|
||||
CONFIG += staticlib
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
HEADERS += *.h
|
||||
SOURCES += *.c
|
||||
|
||||
DESTDIR = $$DestRoot/lib
|
||||
|
||||
load(common_post)
|
||||
@@ -10,10 +10,7 @@ TEMPLATE = lib
|
||||
CONFIG += plugin shared
|
||||
CONFIG += blackmisc blackcore
|
||||
|
||||
LIBS += -lsimulatorfscommon -lsimulatorfsxcommon -lSimConnect -lFSUIPC_User
|
||||
|
||||
# required for FSUIPC
|
||||
win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib
|
||||
LIBS += -lsimulatorfscommon -lsimulatorfsxcommon -lfsuipc -lSimConnect
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
@@ -8,11 +8,6 @@ TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
CONFIG += blackmisc blackcore blackgui
|
||||
|
||||
LIBS += -lsimulatorfscommon -lSimConnect -lFSUIPC_User
|
||||
|
||||
# required for FSUIPC
|
||||
win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
|
||||
@@ -10,10 +10,7 @@ TEMPLATE = lib
|
||||
CONFIG += plugin shared
|
||||
CONFIG += blackmisc blackcore
|
||||
|
||||
LIBS += -lsimulatorfscommon -lsimulatorfsxcommon -lSimConnect -lFSUIPC_User
|
||||
|
||||
# required for FSUIPC
|
||||
win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib
|
||||
LIBS += -lsimulatorfscommon -lsimulatorfsxcommon -lfsuipc -lSimConnect
|
||||
|
||||
DEPENDPATH += . $$SourceRoot/src
|
||||
INCLUDEPATH += . $$SourceRoot/src
|
||||
|
||||
@@ -4,6 +4,8 @@ TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
contains(BLACK_CONFIG,FSX|FS9|P3D) {
|
||||
SUBDIRS += fsuipc32
|
||||
SUBDIRS += fsuipc64
|
||||
SUBDIRS += fscommon
|
||||
}
|
||||
contains(BLACK_CONFIG,FSX|P3D) {
|
||||
@@ -17,7 +19,7 @@ contains(BLACK_CONFIG,FSX) {
|
||||
SUBDIRS += fsx
|
||||
SUBDIRS += fsxconfig
|
||||
}
|
||||
contains(BLACK_CONFIG,FS9) {
|
||||
contains(BLACK_CONFIG,FS9):contains(BLACK_CONFIG,FSUIPC) {
|
||||
SUBDIRS += fs9
|
||||
}
|
||||
contains(BLACK_CONFIG,XPlane) {
|
||||
|
||||
Reference in New Issue
Block a user