diff --git a/TQInterface/TQInterface.cpp b/TQInterface/TQInterface.cpp index d73905e..c9af578 100644 --- a/TQInterface/TQInterface.cpp +++ b/TQInterface/TQInterface.cpp @@ -1,11 +1,313 @@ -// TQInterface.cpp : Defines the entry point for the console application. -// +// Aircraft data and mode mapping via config file in aircraft folder #include "stdafx.h" +// Things for execution +bool quit = 0; +HANDLE hSimConnect = NULL; +char *throttleQuadrantCFG; +initialization init; +uint8_t numEngines = 0; -int main() +// Event to catch beginning +static enum EVENT_ID { + EVENT_SIM_START, + REQUEST_SYSTEM_STATE, +}; + +// Definitions for levers, dynamically added to SimConnect +static enum DATA_DEFINE_ID { + DEFINITION_AC_DATA, + DEFINITION_LEVER_ONE, + DEFINITION_LEVER_TWO, + DEFINITION_LEVER_THREE, + DEFINITION_LEVER_FOUR, +}; + +// Request ID +static enum REQUEST_ID { + AC_DATA_REQUEST, +}; + +// Struct for ac data +struct aircraftData { + double numEngines; + double lowerThrottleLimit; +}; + +// Structs for levers +struct engineJustThrottle { + double throttlePercent; +}; + +struct engineThrottleAndPropeller { + double throttlePercent; + double propellerPercent; +}; + +struct engineThrottleAndMixture { + double throttlePercent; + double mixturePercent; +}; + +struct engineAll { + double throttlePercent; + double propellerPrecent; + double mixturePercent; +}; + +//TESTING PURPOSE +engineJustThrottle tc; + +char *trimwhitespace(char *str) { - return 0; + char *end; + + // Trim leading space + while (isspace((unsigned char)*str)) str++; + + if (*str == 0) // All spaces? + return str; + + // Trim trailing space + end = str + strlen(str) - 1; + while (end > str && isspace((unsigned char)*end)) end--; + + // Write new null terminator + *(end + 1) = 0; + + return str; } +char *readLine(FILE *file) { + + if (file == NULL) { + printf("\nError: file pointer is null."); + exit(1); + } + + int maximumLineLength = 128; + char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength); + + if (lineBuffer == NULL) { + printf("\nError allocating memory for line buffer."); + exit(1); + } + + char ch = getc(file); + int count = 0; + + while ((ch != '\n') && (ch != EOF)) { + if (count == maximumLineLength) { + maximumLineLength += 128; + lineBuffer = (char *)realloc(lineBuffer, maximumLineLength); + if (lineBuffer == NULL) { + printf("\nError reallocating space for line buffer."); + exit(1); + } + } + lineBuffer[count] = ch; + count++; + + ch = getc(file); + } + + lineBuffer[count] = '\0'; + if (count > 0) + return lineBuffer; + else + return NULL ; +} + +void setupDefinitions() { + printf("\nSetting up..."); + HRESULT hr; + hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_ONE); + hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_TWO); + hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_THREE); + hr = SimConnect_ClearDataDefinition(hSimConnect, DEFINITION_LEVER_FOUR); + FILE *fp = fopen(throttleQuadrantCFG, "r"); + char * line = NULL; + uint8_t numEngines = 0; + bool hasPropeller = false; + bool hasMixture = false; + + if (fp == NULL) { + printf("\nThe application cannot run without a valid tq.cfg."); + exit(EXIT_FAILURE); + } + + while ((line = readLine(fp)) != NULL) { + // Parse + char *assign = strstr(line, "="); + char *id = (char *)calloc(13, 1); + memcpy(id, line, ((long)assign - (long)line)); + + if (strcmp(trimwhitespace(id), "numModes") == 0) + init.numModes = atoi(assign + 1); + else if (strcmp(trimwhitespace(id), "hasPropeller") == 0) + hasPropeller = atoi(assign + 1); + else if (strcmp(trimwhitespace(id), "hasMixture") == 0) + hasMixture = atoi(assign + 1); + else if (strcmp(trimwhitespace(id), "mode1") == 0) + strcpy(init.modes[0], strrev(assign + 1)); + else if (strcmp(trimwhitespace(id), "mode2") == 0) + strcpy(init.modes[1], strrev(assign + 1)); + else if (strcmp(trimwhitespace(id), "mode3") == 0) + strcpy(init.modes[2], strrev(assign + 1)); + + free(line); + free(id); + } + + fclose(fp); + fp = fopen("dump.hex", "wb"); + /*DEBUG*/fwrite(&init, 1, sizeof(initialization), fp); + fclose(fp); + + // Setup Data definitions + if (!hasPropeller && !hasMixture) + { + switch (numEngines) { + case 1: + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); + break; + case 2: + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); + break; + case 3: + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:3", "percent"); + break; + case 4: + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:1", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:2", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:3", "percent"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_LEVER_ONE, "GENERAL ENG THROTTLE LEVER POSITION:4", "percent"); + break; + default: + break; + } + } +} + +// SimConnect callback +void CALLBACK MyDispatchProcTC(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext) +{ + HRESULT hr; + + switch (pData->dwID) + { + + case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: { + SIMCONNECT_RECV_SIMOBJECT_DATA *data = (SIMCONNECT_RECV_SIMOBJECT_DATA *)pData; + + switch (data->dwRequestID) { + case AC_DATA_REQUEST: + { + printf("\Aircraft data retrieved"); + init.maxRev = (int8_t)((aircraftData *)&data->dwData)->lowerThrottleLimit; + numEngines = (uint8_t)((aircraftData *)&data->dwData)->numEngines; + setupDefinitions(); + break; + } + + default: + break; + } + + break; + } + + case SIMCONNECT_RECV_ID_SYSTEM_STATE: + { + SIMCONNECT_RECV_SYSTEM_STATE *state = (SIMCONNECT_RECV_SYSTEM_STATE *)pData; + + switch (state->dwRequestID) + { + // Receive loaded aircraft name, set path to tq.cfg + case REQUEST_SYSTEM_STATE: + { + char *path = strrev(strstr(strrev(state->szString), "\\")); + throttleQuadrantCFG = (char *)calloc(strlen(path) + 6, 1); + strcpy(throttleQuadrantCFG, path); + strcat(throttleQuadrantCFG, "tq.cfg"); + printf("\n%s loaded.", throttleQuadrantCFG); + printf("\nRetrieving aicraft data..."); + hr = SimConnect_RequestDataOnSimObject(hSimConnect, AC_DATA_REQUEST, DEFINITION_AC_DATA, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_ONCE); + break; + } + default: + break; + } + break; + } + + case SIMCONNECT_RECV_ID_EVENT: + { + SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT *)pData; + + switch (evt->uEventID) + { + + case EVENT_SIM_START: + { + // Send this request to get the user aircraft id + printf("\n\nRequesting loaded AC path..."); + hr = SimConnect_RequestSystemState(hSimConnect, REQUEST_SYSTEM_STATE, "AircraftLoaded"); + } + break; + + default: + break; + } + break; + } + + case SIMCONNECT_RECV_ID_QUIT: + { + quit = 1; + break; + } + + default: + break; + } +} + +void testThrottleControl() +{ + HRESULT hr; + + if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Throttle Control", NULL, 0, 0, 0))) + { + printf("\nConnected to Flight Simulator!"); + + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AC_DATA, "NUMBER OF ENGINES", "number"); + hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AC_DATA, "THROTTLE LOWER LIMIT", "percent"); + + // Set up a data definition for the throttle control + + //hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_LEVER_ONE, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(tc), &tc); + + // Request a simulation started event + hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart"); + + while (0 == quit) + { + SimConnect_CallDispatch(hSimConnect, MyDispatchProcTC, NULL); + Sleep(1); + } + + hr = SimConnect_Close(hSimConnect); + } +} + +int __cdecl _tmain(int argc, _TCHAR* argv[]) +{ + testThrottleControl(); + + return 0; +} diff --git a/TQInterface/TQInterface.vcxproj b/TQInterface/TQInterface.vcxproj index 229b74b..9b6262a 100644 --- a/TQInterface/TQInterface.vcxproj +++ b/TQInterface/TQInterface.vcxproj @@ -88,10 +88,12 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + C:\Program Files %28x86%29\Microsoft Games\Microsoft Flight Simulator X SDK\SDK\Core Utilities Kit\SimConnect SDK\inc;%(AdditionalIncludeDirectories) Console true + C:\Program Files %28x86%29\Microsoft Games\Microsoft Flight Simulator X SDK\SDK\Core Utilities Kit\SimConnect SDK\lib;%(AdditionalLibraryDirectories) @@ -116,12 +118,14 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + C:\Program Files %28x86%29\Microsoft Games\Microsoft Flight Simulator X SDK\SDK\Core Utilities Kit\SimConnect SDK\inc;%(AdditionalIncludeDirectories) Console true true true + C:\Program Files %28x86%29\Microsoft Games\Microsoft Flight Simulator X SDK\SDK\Core Utilities Kit\SimConnect SDK\lib;%(AdditionalLibraryDirectories) diff --git a/TQInterface/stdafx.h b/TQInterface/stdafx.h index b005a83..d067b78 100644 --- a/TQInterface/stdafx.h +++ b/TQInterface/stdafx.h @@ -7,9 +7,25 @@ #include "targetver.h" -#include +#include #include +#include +#include +#include +#include +#include "SimConnect.h" +#pragma comment(lib, "SimConnect.lib") + +typedef struct initialization { + uint8_t numModes; + int8_t maxRev; + char modes[3][5]; +} initialization; + +typedef struct values { + uint8_t mode; + int8_t leverValuesInPercent[4]; +} values; -// TODO: reference additional headers your program requires here