diff --git a/Include/InternalsPlugin.hpp b/Include/InternalsPlugin.hpp new file mode 100644 index 0000000..0d0b8e4 --- /dev/null +++ b/Include/InternalsPlugin.hpp @@ -0,0 +1,370 @@ +//ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +//Ż Ž +//Ż Module: Header file for internals plugin Ž +//Ż Ž +//Ż Description: Interface declarations for internals plugin Ž +//Ż Ž +//Ż This source code module, and all information, data, and algorithms Ž +//Ż associated with it, are part of isiMotor Technology (tm). Ž +//Ż PROPRIETARY AND CONFIDENTIAL Ž +//Ż Copyright (c) 1996-2007 Image Space Incorporated. All rights reserved. Ž +//Ż Ž +//Ż Change history: Ž +//Ż tag.2005.11.29: created Ž +//Ż Ž +//ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +#ifndef _INTERNALS_PLUGIN_HPP_ +#define _INTERNALS_PLUGIN_HPP_ + +#include "RFPluginObjects.hpp" + +// change this variable whenever a change is made to the plugin interfaces +// use m_uVersion (returned by GetVersion() for version control instead //#define INTERNALS_PLUGIN_VERSION (0.0f) + + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ Structs to retrieve internal information (e.g. telemetry info) ³ +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ + +struct TelemVect3 +{ + float x, y, z; + + void Set( const float a, const float b, const float c ) { x = a; y = b; z = c; } +}; + + +struct TelemWheel +{ + float mRotation; // radians/sec + float mSuspensionDeflection; // meters + float mRideHeight; // meters + float mTireLoad; // Newtons + float mLateralForce; // Newtons + float mGripFract; // an approximation of what fraction of the contact patch is sliding + float mBrakeTemp; // Celsius + float mPressure; // kPa + float mTemperature[3]; // Celsius, left/center/right (not to be confused with inside/center/outside!) +}; + +struct TelemWheelV2 : public TelemWheel +{ + float mWear; // wear (0.0-1.0, fraction of maximum) ... this is not necessarily proportional with grip loss + char mTerrainName[16]; // the material prefixes from the TDF file + unsigned char mSurfaceType; // 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip + bool mFlat; // whether tire is flat + bool mDetached; // whether wheel is detached + + // Future use + unsigned char mExpansion[32]; +}; + + +// Our world coordinate system is left-handed, with +y pointing up. +// The local vehicle coordinate system is as follows: +// +x points out the left side of the car (from the driver's perspective) +// +y points out the roof +// +z points out the back of the car +// Rotations are as follows: +// +x pitches up +// +y yaws to the right +// +z rolls to the right + +struct TelemInfoBase +{ + // Time + float mDeltaTime; // time since last update (seconds) + long mLapNumber; // current lap number + float mLapStartET; // time this lap was started + char mVehicleName[64]; // current vehicle name + char mTrackName[64]; // current track name + + // Position and derivatives + TelemVect3 mPos; // world position in meters + TelemVect3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates + TelemVect3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates + + // Orientation and derivatives + TelemVect3 mOriX; // top row of orientation matrix (also converts local vehicle vectors into world X using dot product) + TelemVect3 mOriY; // mid row of orientation matrix (also converts local vehicle vectors into world Y using dot product) + TelemVect3 mOriZ; // bot row of orientation matrix (also converts local vehicle vectors into world Z using dot product) + TelemVect3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates + TelemVect3 mLocalRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates + + // Vehicle status + long mGear; // -1=reverse, 0=neutral, 1+=forward gears + float mEngineRPM; // engine RPM + float mEngineWaterTemp; // Celsius + float mEngineOilTemp; // Celsius + float mClutchRPM; // clutch RPM + + // Driver input + float mUnfilteredThrottle; // ranges 0.0-1.0 + float mUnfilteredBrake; // ranges 0.0-1.0 + float mUnfilteredSteering; // ranges -1.0-1.0 (left to right) + float mUnfilteredClutch; // ranges 0.0-1.0 + + // Misc + float mSteeringArmForce; // force on steering arms +}; + +struct TelemInfo : public TelemInfoBase // re-arranged for expansion, but backwards-compatible +{ + TelemWheel mWheel[4]; // wheel info (front left, front right, rear left, rear right) +}; + +struct TelemInfoV2 : public TelemInfoBase // for noobs: TelemInfoV2 contains everything in TelemInfoBase, plus the following: +{ + // state/damage info + float mFuel; // amount of fuel (liters) + float mEngineMaxRPM; // rev limit + unsigned char mScheduledStops; // number of scheduled pitstops + bool mOverheating; // whether overheating icon is shown + bool mDetached; // whether any parts (besides wheels) have been detached + unsigned char mDentSeverity[8];// dent severity at 8 locations around the car (0=none, 1=some, 2=more) + float mLastImpactET; // time of last impact + float mLastImpactMagnitude; // magnitude of last impact + TelemVect3 mLastImpactPos; // location of last impact + + // Future use + unsigned char mExpansion[64]; + + // keeping this at the end of the structure to make it easier to replace in future versions + TelemWheelV2 mWheel[4]; // wheel info (front left, front right, rear left, rear right) +}; + + +struct GraphicsInfo // may be expanded in the future to provide interfaces for drawing onscreen +{ + TelemVect3 mCamPos; // camera position + TelemVect3 mCamOri; // camera orientation + HWND mHWND; // app handle +}; + +struct GraphicsInfoV2 : public GraphicsInfo // for noobs: GraphicsInfoV2 contains everything in GraphicsInfo, plus the following: +{ + float mAmbientRed; + float mAmbientGreen; + float mAmbientBlue; +}; + + +struct VehicleScoringInfo +{ + char mDriverName[32]; // driver name + char mVehicleName[64]; // vehicle name + short mTotalLaps; // laps completed + signed char mSector; // 0=sector3, 1=sector1, 2=sector2 (don't ask why) + signed char mFinishStatus; // 0=none, 1=finished, 2=dnf, 3=dq + float mLapDist; // current distance around track + float mPathLateral; // lateral position with respect to *very approximate* "center" path + float mTrackEdge; // track edge (w.r.t. "center" path) on same side of track as vehicle + + float mBestSector1; // best sector 1 + float mBestSector2; // best sector 2 (plus sector 1) + float mBestLapTime; // best lap time + float mLastSector1; // last sector 1 + float mLastSector2; // last sector 2 (plus sector 1) + float mLastLapTime; // last lap time + float mCurSector1; // current sector 1 if valid + float mCurSector2; // current sector 2 (plus sector 1) if valid + // no current laptime because it instantly becomes "last" + + short mNumPitstops; // number of pitstops made + short mNumPenalties; // number of outstanding penalties +}; + + +struct VehicleScoringInfoV2 : public VehicleScoringInfo // for noobs: VehicleScoringInfoV2 contains everything in VehicleScoringInfo, plus the following: +{ + bool mIsPlayer; // is this the player's vehicle + signed char mControl; // who's in control: -1=nobody (shouldn't get this), 0=local player, 1=local AI, 2=remote, 3=replay (shouldn't get this) + bool mInPits; // between pit entrance and pit exit (not always accurate for remote vehicles) + unsigned char mPlace; // 1-based position + char mVehicleClass[32]; // vehicle class + + // Dash Indicators + float mTimeBehindNext; // time behind vehicle in next higher place + long mLapsBehindNext; // laps behind vehicle in next higher place + float mTimeBehindLeader; // time behind leader + long mLapsBehindLeader; // laps behind leader + float mLapStartET; // time this lap was started + + // Position and derivatives + TelemVect3 mPos; // world position in meters + TelemVect3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates + TelemVect3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates + + // Orientation and derivatives + TelemVect3 mOriX; // top row of orientation matrix (also converts local vehicle vectors into world X using dot product) + TelemVect3 mOriY; // mid row of orientation matrix (also converts local vehicle vectors into world Y using dot product) + TelemVect3 mOriZ; // bot row of orientation matrix (also converts local vehicle vectors into world Z using dot product) + TelemVect3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates + TelemVect3 mLocalRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates + + // Future use + unsigned char mExpansion[128]; +}; + + +struct ScoringInfoBase +{ + char mTrackName[64]; // current track name + long mSession; // current session + float mCurrentET; // current time + float mEndET; // ending time + long mMaxLaps; // maximum laps + float mLapDist; // distance around track + char *mResultsStream; // results stream additions since last update (newline-delimited and NULL-terminated) + + long mNumVehicles; // current number of vehicles +}; + +struct ScoringInfo : public ScoringInfoBase // re-arranged for expansion, but backwards-compatible +{ + VehicleScoringInfo *mVehicle; // array of vehicle scoring info's +}; + +struct ScoringInfoV2 : public ScoringInfoBase // for noobs: ScoringInfoV2 contains everything in ScoringInfoBase, plus the following: +{ + // Game phases: + // 0 Before session has begun + // 1 Reconnaissance laps (race only) + // 2 Grid walk-through (race only) + // 3 Formation lap (race only) + // 4 Starting-light countdown has begun (race only) + // 5 Green flag + // 6 Full course yellow / safety car + // 7 Session stopped + // 8 Session over + unsigned char mGamePhase; + + // Yellow flag states (applies to full-course only) + // -1 Invalid + // 0 None + // 1 Pending + // 2 Pits closed + // 3 Pit lead lap + // 4 Pits open + // 5 Last lap + // 6 Resume + // 7 Race halt (not currently used) + signed char mYellowFlagState; + + signed char mSectorFlag[3]; // whether there are any local yellows at the moment in each sector (not sure if sector 0 is first or last, so test) + unsigned char mStartLight; // start light frame (number depends on track) + unsigned char mNumRedLights; // number of red lights in start sequence + bool mInRealtime; // in realtime as opposed to at the monitor + char mPlayerName[32]; // player name (including possible multiplayer override) + char mPlrFileName[64]; // may be encoded to be a legal filename + + // weather + float mDarkCloud; // cloud darkness? 0.0-1.0 + float mRaining; // raining severity 0.0-1.0 + float mAmbientTemp; // temperature (Celsius) + float mTrackTemp; // temperature (Celsius) + TelemVect3 mWind; // wind speed + float mOnPathWetness; // on main path 0.0-1.0 + float mOffPathWetness; // on main path 0.0-1.0 + + // Future use + unsigned char mExpansion[256]; + + // keeping this at the end of the structure to make it easier to replace in future versions + VehicleScoringInfoV2 *mVehicle; // array of vehicle scoring info's +}; + + +struct CommentaryRequestInfo +{ + char mName[32]; // one of the event names in the commentary INI file + double mInput1; // first value to pass in (if any) + double mInput2; // first value to pass in (if any) + double mInput3; // first value to pass in (if any) + bool mSkipChecks; // ignores commentary detail and random probability of event + + // constructor (for noobs, this just helps make sure everything is initialized to something reasonable) + CommentaryRequestInfo() { mName[0] = 0; mInput1 = 0.0; mInput2 = 0.0; mInput3 = 0.0; mSkipChecks = false; } +}; + + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ Plugin classes used to access internals ³ +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ + +// Note: use class InternalsPlugin for GetVersion()==1, or +// use class InternalsPluginV2 for GetVersion()==2, or +// use class InternalsPluginV3 for GetVersion()==3 +class InternalsPlugin : public PluginObject +{ + public: + + // General internals methods + InternalsPlugin() {} + virtual ~InternalsPlugin() {} + + virtual void Startup() {} // game startup + virtual void Shutdown() {} // game shutdown + + virtual void EnterRealtime() {} // entering realtime (where the vehicle can be driven) + virtual void ExitRealtime() {} // exiting realtime + + // GAME OUTPUT + virtual bool WantsTelemetryUpdates() { return( false ); } // whether we want telemetry updates + virtual void UpdateTelemetry( const TelemInfo &info ) {} // update plugin with telemetry info + + virtual bool WantsGraphicsUpdates() { return( false ); } // whether we want graphics updates + virtual void UpdateGraphics( const GraphicsInfo &info ) {} // update plugin with graphics info + + // GAME INPUT + virtual bool HasHardwareInputs() { return( false ); } // whether plugin has hardware plugins + virtual void UpdateHardware( const float fDT ) {} // update the hardware with the time between frames + virtual void EnableHardware() {} // message from game to enable hardware + virtual void DisableHardware() {} // message from game to disable hardware + + // See if the plugin wants to take over a hardware control. If the plugin takes over the + // control, this method returns true and sets the value of the float pointed to by the + // second arg. Otherwise, it returns false and leaves the float unmodified. + virtual bool CheckHWControl( const char * const controlName, float &fRetVal ) { return false; } + + virtual bool ForceFeedback( float &forceValue ) { return( false ); } // alternate force feedback computation - return true if editing the value +}; + + +class InternalsPluginV2 : public InternalsPlugin // for noobs: InternalsPluginV2 contains everything in InternalsPlugin, plus the following: +{ + public: + + // SCORING OUTPUT + virtual bool WantsScoringUpdates() { return( false ); } // whether we want scoring updates + virtual void UpdateScoring( const ScoringInfo &info ) {} // update plugin with scoring info (approximately once per second) +}; + + +class InternalsPluginV3 : public InternalsPluginV2 // for noobs: InternalsPluginV3 contains everything in InternalsPluginV2 (and InternalsPlugin), plus the following: +{ + public: + + // SESSION NOTIFICATIONS + virtual void StartSession() {} // session started + virtual void EndSession() {} // session ended + + // GAME OUTPUT + virtual void UpdateTelemetry( const TelemInfoV2 &info ) {} // update plugin with telemetry info + + // GRAPHICS OUTPUT + virtual void UpdateGraphics( const GraphicsInfoV2 &info ) {} // update plugin with graphics info + + // SCORING OUTPUT + virtual void UpdateScoring( const ScoringInfoV2 &info ) {} // update plugin with scoring info (approximately once per second) + + // COMMENTARY INPUT + virtual bool RequestCommentary( CommentaryRequestInfo &info ) { return( false ); } // to use our commentary event system, fill in data and return true +}; + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ + +#endif // _INTERNALS_PLUGIN_HPP_ + diff --git a/Include/RFPluginObjects.hpp b/Include/RFPluginObjects.hpp new file mode 100644 index 0000000..24854cb --- /dev/null +++ b/Include/RFPluginObjects.hpp @@ -0,0 +1,133 @@ +//ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +//Ż Ž +//Ż Module: Header file for plugin object types Ž +//Ż Ž +//Ż Description: interface declarations for plugin objects Ž +//Ż Ž +//Ż This source code module, and all information, data, and algorithms Ž +//Ż associated with it, are part of isiMotor Technology (tm). Ž +//Ż PROPRIETARY AND CONFIDENTIAL Ž +//Ż Copyright (c) 1996-2007 Image Space Incorporated. All rights reserved. Ž +//Ż Ž +//Ż Change history: Ž +//Ż kc.2004.0?.??: created Ž +//Ż mm.2004.05.25: added this description header Ž +//Ż mm.2004.05.20: splitting this file up so that each type of plugin Ž +//Ż gets its own header file. Ž +//Ż Ž +//ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +#ifndef _PLUGINOBJECT +#define _PLUGINOBJECT + +#include + + +// forward referencing stuff +class PluginObjectInfo; + + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ typedefs for dll functions - easier to use a typedef than to type +//³ out the crazy syntax for declaring and casting function pointers +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +typedef const char* (__cdecl *GETPLUGINNAME)(); +typedef unsigned (__cdecl *GETPLUGINVERSION)(); +typedef unsigned (__cdecl *GETPLUGINOBJECTCOUNT)(); +typedef PluginObjectInfo* (__cdecl *GETPLUGINOBJECTINFO)(const unsigned uIndex); +typedef PluginObjectInfo* (__cdecl *GETPLUGINOBJECTINFO)(const unsigned uIndex); +typedef float (__cdecl *GETPLUGINSYSTEMVERSION) (); + + +//plugin object types +enum PluginObjectType +{ + PO_VIDEO_EXPORT = 0x00000001, + PO_RFMODIFIER = 0x00000002, + PO_HWPLUGIN = 0x00000003, + PO_GAMESTATS = 0x00000004, + PO_NCPLUGIN = 0x00000005, + PO_MOTION = 0x00000006, + PO_IRCPLUGIN = 0x00000007, + PO_IVIBE = 0x00000008, + PO_INTERNALS = 0x00000009, +}; + + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ Plugin Object Property +//³ - can be used to expose pluginobject settings to rFactor. +//³ In practice this feature has gone almost entirely unused +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +enum POPType +{ + POPTYPE_INT, + POPTYPE_FLOAT, + POPTYPE_STRING, +}; + +static char POPTypeNames[3][64] = +{ + "POPTYPE_INT", + "POPTYPE_FLOAT", + "POPTYPE_STRING", +}; + +const unsigned POP_MAXNAME = 32; +const unsigned POP_MAXDESC = 256; + +struct PluginObjectProperty +{ + union + { + int iValue; + float fValue; + char* szValue; + }; + + POPType uPropertyType; + char szName[POP_MAXNAME]; + char szDesc[POP_MAXDESC]; +}; + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ PluginObject +//³ - interface used by plugin classes. +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +class PluginObject +{ +public: + PluginObject() {} + virtual ~PluginObject(){}; + virtual void Destroy()=0; + virtual class PluginObjectInfo* GetInfo()=0; + + virtual unsigned GetPropertyCount() const =0; + virtual PluginObjectProperty* GetProperty(const unsigned uIndex) =0; + virtual PluginObjectProperty* GetProperty(const char* szName) =0; +}; + +//ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +//³ PluginObjectInfo +//³ - interface used by plugin info classes. +//³ the purpose of the plugin info classes is to allow the game to get +//³ information about and instantiate the plugin objects contained in +//³ a dll without needing to know anything about the PO in advance +//ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +class PluginObjectInfo +{ +public: + virtual ~PluginObjectInfo() {}; + virtual const char* GetName() const = 0; + virtual const char* GetFullName() const = 0; + virtual const char* GetDesc() const = 0; + virtual const unsigned GetType() const = 0; + virtual const char* GetSubType() const = 0; + virtual const unsigned GetVersion() const = 0; + virtual void* Create() const = 0; +}; + + + + + +#endif \ No newline at end of file diff --git a/Include/rFactorSharedMemoryMap.hpp b/Include/rFactorSharedMemoryMap.hpp new file mode 100644 index 0000000..18bd6e7 --- /dev/null +++ b/Include/rFactorSharedMemoryMap.hpp @@ -0,0 +1,113 @@ +/* +rfSharedMemoryMap.hpp +by Dan Allongo (daniel.s.allongo@gmail.com) + +This remains largely unchanged from Example.hpp, except for a few additional +private variables to track the current state of the memory map handle and buffer. +*/ + +#pragma once + +#include "InternalsPlugin.hpp" +#include "rfSharedStruct.hpp" +#include + +#define PLUGIN_NAME "rFactorSharedMemoryMap" + +// This is used for app to find out information about the plugin +class InternalsPluginInfo : public PluginObjectInfo +{ + public: + + // Constructor/destructor + InternalsPluginInfo(); + ~InternalsPluginInfo() {} + + // Derived from base class PluginObjectInfo + virtual const char* GetName() const; + virtual const char* GetFullName() const; + virtual const char* GetDesc() const; + virtual const unsigned GetType() const; + virtual const char* GetSubType() const; + virtual const unsigned GetVersion() const; + virtual void* Create() const; + + private: + + char m_szFullName[128]; +}; + + +// This is used for the app to use the plugin for its intended purpose +class SharedMemoryMapPlugin : public InternalsPluginV3 +{ + protected: + + const static char m_szName[]; + const static char m_szSubType[]; + const static unsigned m_uID; + const static unsigned m_uVersion; + + public: + + // Constructor/destructor + SharedMemoryMapPlugin() {} + ~SharedMemoryMapPlugin() {} + + // Called from class InternalsPluginInfo to return specific information about plugin + static const char * GetName() { return m_szName; } + static const unsigned GetType() { return PO_INTERNALS; } + static const char * GetSubType() { return m_szSubType; } + static const unsigned GetVersion() { return m_uVersion; } + + // Derived from base class PluginObject + void Destroy() { Shutdown(); } // poorly named ... doesn't destroy anything + PluginObjectInfo * GetInfo(); + unsigned GetPropertyCount() const { return 0; } + PluginObjectProperty *GetProperty( const char * ) { return 0; } + PluginObjectProperty *GetProperty( const unsigned ) { return 0; } + + // These are the functions derived from base class InternalsPlugin + // that can be implemented. + void Startup(); // game startup + void Shutdown(); // game shutdown + + void EnterRealtime() {} // entering realtime + void ExitRealtime() {} // exiting realtime + + void StartSession() {} // session has started + void EndSession() {} // session has ended + + // GAME OUTPUT + bool WantsTelemetryUpdates() { return( true ); } // CHANGE TO TRUE TO ENABLE TELEMETRY EXAMPLE! + void UpdateTelemetry( const TelemInfoV2 &info ); + + bool WantsGraphicsUpdates() { return( false ); } // CHANGE TO TRUE TO ENABLE GRAPHICS EXAMPLE! + void UpdateGraphics( const GraphicsInfoV2 &info ) {} + + // GAME INPUT + bool HasHardwareInputs() { return( false ); } // CHANGE TO TRUE TO ENABLE HARDWARE EXAMPLE! + void UpdateHardware( const float fDT ) {} // update the hardware with the time between frames + void EnableHardware() {} // message from game to enable hardware + void DisableHardware() {} // message from game to disable hardware + + // See if the plugin wants to take over a hardware control. If the plugin takes over the + // control, this method returns true and sets the value of the float pointed to by the + // second arg. Otherwise, it returns false and leaves the float unmodified. + bool CheckHWControl( const char * const controlName, float &fRetVal ) { return( false ); } + + bool ForceFeedback( float &forceValue ) { return( false ); } // SEE FUNCTION BODY TO ENABLE FORCE EXAMPLE + + // SCORING OUTPUT + bool WantsScoringUpdates() { return( true ); } // CHANGE TO TRUE TO ENABLE SCORING EXAMPLE! + void UpdateScoring( const ScoringInfoV2 &info ); + + // COMMENTARY INPUT + bool RequestCommentary( CommentaryRequestInfo &info ) { return( false ); } // SEE FUNCTION BODY TO ENABLE COMMENTARY EXAMPLE + + private: + + HANDLE hMap; + rfShared* pBuf; + bool mapped; +}; diff --git a/Include/rfSharedStruct.hpp b/Include/rfSharedStruct.hpp new file mode 100644 index 0000000..0cc43ef --- /dev/null +++ b/Include/rfSharedStruct.hpp @@ -0,0 +1,227 @@ +/* +rfSharedStruct.hpp +by Dan Allongo (daniel.s.allongo@gmail.com) + +This is the structure of the shared memory map +It's nearly identical to the original structures specified in InternalsPlugin.hpp, +but with pragma pack 1 specified to get the most compact representation. +This means that you need to watch your types very closely! +*/ + +#pragma once + +#define RF_SHARED_MEMORY_NAME "$rFactorShared$" + +typedef enum { + garage = 0, + warmUp = 1, + gridWalk = 2, + formation = 3, + countdown = 4, + greenFlag = 5, + fullCourseYellow = 6, + sessionStopped = 7, + sessionOver = 8 +} rfGamePhase; + +typedef enum { + invalid = -1, + noFlag = 0, + pending = 1, + pitClosed = 2, + pitLeadLap = 3, + pitOpen = 4, + lastLap = 5, + resume = 6, + raceHalt = 7 +} rfYellowFlagState; + +typedef enum { + dry = 0, + wet = 1, + grass = 2, + dirt = 3, + gravel = 4, + kerb = 5 +} rfSurfaceType; + +typedef enum { + sector3 = 0, + sector1 = 1, + sector2 = 2 +} rfSector; + +typedef enum { + none = 0, + finished = 1, + dnf = 2, + dq = 3 +} rfFinishStatus; + +typedef enum { + nobody = -1, + player = 0, + ai = 1, + remote = 2, + replay = 3 +} rfControl; + +typedef enum { + frontLeft = 0, + frontRight = 1, + rearLeft = 2, + rearRight = 3 +} rfWheelIndex; + +#pragma pack(push, 1) + +// Our world coordinate system is left-handed, with +y pointing up. +// The local vehicle coordinate system is as follows: +// +x points out the left side of the car (from the driver's perspective) +// +y points out the roof +// +z points out the back of the car +// Rotations are as follows: +// +x pitches up +// +y yaws to the right +// +z rolls to the right + +struct rfVec3 { + float x, y, z; +}; + +struct rfWheel { + float rotation; // radians/sec + float suspensionDeflection; // meters + float rideHeight; // meters + float tireLoad; // Newtons + float lateralForce; // Newtons + float gripFract; // an approximation of what fraction of the contact patch is sliding + float brakeTemp; // Celsius + float pressure; // kPa + float temperature[3]; // Celsius, left/center/right (not to be confused with inside/center/outside!) + float wear; // wear (0.0-1.0, fraction of maximum) ... this is not necessarily proportional with grip loss + char terrainName[16]; // the material prefixes from the TDF file + unsigned char surfaceType; // 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip + bool flat; // whether tire is flat + bool detached; // whether wheel is detached +}; + +struct rfVehicleInfo { + char driverName[32]; // driver name + char vehicleName[64]; // vehicle name + short totalLaps; // laps completed + signed char sector; // 0=sector3, 1=sector1, 2=sector2 (don't ask why) + signed char finishStatus; // 0=none, 1=finished, 2=dnf, 3=dq + float lapDist; // current distance around track + float pathLateral; // lateral position with respect to *very approximate* "center" path + float trackEdge; // track edge (w.r.t. "center" path) on same side of track as vehicle + + float bestSector1; // best sector 1 + float bestSector2; // best sector 2 (plus sector 1) + float bestLapTime; // best lap time + float lastSector1; // last sector 1 + float lastSector2; // last sector 2 (plus sector 1) + float lastLapTime; // last lap time + float curSector1; // current sector 1 if valid + float curSector2; // current sector 2 (plus sector 1) if valid + // no current laptime because it instantly becomes "last" + + short numPitstops; // number of pitstops made + short numPenalties; // number of outstanding penalties + bool isPlayer; // is this the player's vehicle + signed char control; // who's in control: -1=nobody (shouldn't get this), 0=local player, 1=local AI, 2=remote, 3=replay (shouldn't get this) + bool inPits; // between pit entrance and pit exit (not always accurate for remote vehicles) + unsigned char place; // 1-based position + char vehicleClass[32]; // vehicle class + + // Dash Indicators + float timeBehindNext; // time behind vehicle in next higher place + long lapsBehindNext; // laps behind vehicle in next higher place + float timeBehindLeader; // time behind leader + long lapsBehindLeader; // laps behind leader + float lapStartET; // time this lap was started + + // Position and derivatives + rfVec3 pos; // world position in meters + float speed; // meters/sec +}; + +struct rfShared { + // Time + float deltaTime; // time since last update (seconds) + long lapNumber; // current lap number + float lapStartET; // time this lap was started + char vehicleName[64]; // current vehicle name + char trackName[64]; // current track name + + // Position and derivatives + rfVec3 pos; // world position in meters + rfVec3 localVel; // velocity (meters/sec) in local vehicle coordinates + rfVec3 localAccel; // acceleration (meters/sec^2) in local vehicle coordinates + + // Orientation and derivatives + rfVec3 oriX; // top row of orientation matrix (also converts local vehicle vectors into world X using dot product) + rfVec3 oriY; // mid row of orientation matrix (also converts local vehicle vectors into world Y using dot product) + rfVec3 oriZ; // bot row of orientation matrix (also converts local vehicle vectors into world Z using dot product) + rfVec3 localRot; // rotation (radians/sec) in local vehicle coordinates + rfVec3 localRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates + + float speed; // meters/sec + + // Vehicle status + long gear; // -1=reverse, 0=neutral, 1+=forward gears + float engineRPM; // engine RPM + float engineWaterTemp; // Celsius + float engineOilTemp; // Celsius + float clutchRPM; // clutch RPM + + // Driver input + float unfilteredThrottle; // ranges 0.0-1.0 + float unfilteredBrake; // ranges 0.0-1.0 + float unfilteredSteering; // ranges -1.0-1.0 (left to right) + float unfilteredClutch; // ranges 0.0-1.0 + + // Misc + float steeringArmForce; // force on steering arms + // state/damage info + float fuel; // amount of fuel (liters) + float engineMaxRPM; // rev limit + unsigned char scheduledStops; // number of scheduled pitstops + bool overheating; // whether overheating icon is shown + bool detached; // whether any parts (besides wheels) have been detached + unsigned char dentSeverity[8];// dent severity at 8 locations around the car (0=none, 1=some, 2=more) + float lastImpactET; // time of last impact + float lastImpactMagnitude; // magnitude of last impact + rfVec3 lastImpactPos; // location of last impact + + rfWheel wheel[4]; // wheel info (front left, front right, rear left, rear right) + + // scoring info + long session; // current session + float currentET; // current time + float endET; // ending time + long maxLaps; // maximum laps + float lapDist; // distance around track + + long numVehicles; // current number of vehicles + + unsigned char gamePhase; + + signed char yellowFlagState; + + signed char sectorFlag[3]; // whether there are any local yellows at the moment in each sector (not sure if sector 0 is first or last, so test) + unsigned char startLight; // start light frame (number depends on track) + unsigned char numRedLights; // number of red lights in start sequence + bool inRealtime; // in realtime as opposed to at the monitor + char playerName[32]; // player name (including possible multiplayer override) + char plrFileName[64]; // may be encoded to be a legal filename + + // weather + float ambientTemp; // temperature (Celsius) + float trackTemp; // temperature (Celsius) + rfVec3 wind; // wind speed + + rfVehicleInfo vehicle[128]; // array of vehicle scoring info's +}; + +#pragma pack(pop) diff --git a/Source/rFactorSharedMemoryMap.cpp b/Source/rFactorSharedMemoryMap.cpp new file mode 100644 index 0000000..6b2fbc0 --- /dev/null +++ b/Source/rFactorSharedMemoryMap.cpp @@ -0,0 +1,241 @@ +/* + rFactorSharedMemoryMap.cpp + by Dan Allongo (daniel.s.allongo@gmail.com) + + Based on the ISI sample code found at http://rfactor.net/web/rf1/devcorner/ + Provides a basic memory map export of the telemetry and scoring data + The export is nearly 1:1 with redundant/gratuitous data removed from the + vehicle info array and the addition of vehicle speed being pre-calculated + since everyone needs that anyway. +*/ + +#include "rFactorSharedMemoryMap.hpp" +#include +#include + + +// plugin information +unsigned g_uPluginID = 0; +char g_szPluginName[] = PLUGIN_NAME; +unsigned g_uPluginVersion = 001; +unsigned g_uPluginObjectCount = 1; +InternalsPluginInfo g_PluginInfo; + +// interface to plugin information +extern "C" __declspec(dllexport) +const char* __cdecl GetPluginName() { return g_szPluginName; } + +extern "C" __declspec(dllexport) +unsigned __cdecl GetPluginVersion() { return g_uPluginVersion; } + +extern "C" __declspec(dllexport) +unsigned __cdecl GetPluginObjectCount() { return g_uPluginObjectCount; } + +// get the plugin-info object used to create the plugin. +extern "C" __declspec(dllexport) +PluginObjectInfo* __cdecl GetPluginObjectInfo( const unsigned uIndex ) { + switch(uIndex) { + case 0: + return &g_PluginInfo; + default: + return 0; + } +} + + +// InternalsPluginInfo class + +InternalsPluginInfo::InternalsPluginInfo() { + // put together a name for this plugin + sprintf( m_szFullName, "%s - %s", g_szPluginName, InternalsPluginInfo::GetName() ); +} + +const char* InternalsPluginInfo::GetName() const { return SharedMemoryMapPlugin::GetName(); } +const char* InternalsPluginInfo::GetFullName() const { return m_szFullName; } +const char* InternalsPluginInfo::GetDesc() const { return g_szPluginName; } +const unsigned InternalsPluginInfo::GetType() const { return SharedMemoryMapPlugin::GetType(); } +const char* InternalsPluginInfo::GetSubType() const { return SharedMemoryMapPlugin::GetSubType(); } +const unsigned InternalsPluginInfo::GetVersion() const { return SharedMemoryMapPlugin::GetVersion(); } +void* InternalsPluginInfo::Create() const { return new SharedMemoryMapPlugin(); } + + +// InternalsPlugin class + +const char SharedMemoryMapPlugin::m_szName[] = PLUGIN_NAME; +const char SharedMemoryMapPlugin::m_szSubType[] = "Internals"; +const unsigned SharedMemoryMapPlugin::m_uID = 1; +const unsigned SharedMemoryMapPlugin::m_uVersion = 3; // set to 3 for InternalsPluginV3 functionality and added graphical and vehicle info + +PluginObjectInfo *SharedMemoryMapPlugin::GetInfo() { + return &g_PluginInfo; +} + +void SharedMemoryMapPlugin::Startup() { + // init handle and try to create, read if existing + hMap = INVALID_HANDLE_VALUE; + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(rfShared), TEXT(RF_SHARED_MEMORY_NAME)); + if (hMap == NULL) { + if (GetLastError() == (DWORD)183) { + hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT(RF_SHARED_MEMORY_NAME)); + if (hMap == NULL) { + // unable to create or read existing + mapped = FALSE; + return; + } + } + } + pBuf = (rfShared*)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(rfShared)); + if (pBuf == NULL) { + // failed to map memory buffer + CloseHandle(hMap); + mapped = FALSE; + return; + } + mapped = TRUE; + return; +} + +void SharedMemoryMapPlugin::Shutdown() { + // release buffer and close handle + if (pBuf) { + UnmapViewOfFile(pBuf); + } + if (hMap) { + CloseHandle(hMap); + } + mapped = FALSE; +} + +void SharedMemoryMapPlugin::UpdateTelemetry( const TelemInfoV2 &info ) { + if (mapped) { + // TelemInfoBase + pBuf->deltaTime = info.mDeltaTime; + pBuf->lapNumber = info.mLapNumber; + pBuf->lapStartET = info.mLapStartET; + strcpy(pBuf->vehicleName, info.mVehicleName); + strcpy(pBuf->trackName, info.mTrackName); + pBuf->pos = { info.mPos.x, info.mPos.y, info.mPos.z }; + pBuf->localVel = { info.mLocalVel.x, info.mLocalVel.y, info.mLocalVel.z }; + pBuf->localAccel = { info.mLocalAccel.x, info.mLocalAccel.y, info.mLocalAccel.z }; + pBuf->oriX = { info.mOriX.x, info.mOriX.y, info.mOriX.z }; + pBuf->oriY = { info.mOriY.x, info.mOriY.y, info.mOriY.z }; + pBuf->oriZ = { info.mOriZ.x, info.mOriZ.y, info.mOriZ.z }; + pBuf->localRot = { info.mLocalRot.x, info.mLocalRot.y, info.mLocalRot.z }; + pBuf->localRotAccel = { info.mLocalRotAccel.x, info.mLocalRotAccel.y, info.mLocalRotAccel.z }; + pBuf->speed = sqrtf((info.mLocalVel.x * info.mLocalVel.x) + + (info.mLocalVel.y * info.mLocalVel.y) + + (info.mLocalVel.z * info.mLocalVel.z)); + pBuf->gear = info.mGear; + pBuf->engineRPM = info.mEngineRPM; + pBuf->engineWaterTemp = info.mEngineWaterTemp; + pBuf->engineOilTemp = info.mEngineOilTemp; + pBuf->clutchRPM = info.mClutchRPM; + pBuf->unfilteredThrottle = info.mUnfilteredThrottle; + pBuf->unfilteredBrake = info.mUnfilteredBrake; + pBuf->unfilteredSteering = info.mUnfilteredSteering; + pBuf->unfilteredClutch = info.mUnfilteredClutch; + pBuf->steeringArmForce = info.mSteeringArmForce; + + // TelemInfoV2 + pBuf->fuel = info.mFuel; + pBuf->engineMaxRPM = info.mEngineMaxRPM; + pBuf->scheduledStops = info.mScheduledStops; + pBuf->overheating = info.mOverheating; + pBuf->detached = info.mDetached; + for (int i = 0; i < 8; i++) { + pBuf->dentSeverity[i] = info.mDentSeverity[i]; + } + pBuf->lastImpactET = info.mLastImpactET; + pBuf->lastImpactMagnitude = info.mLastImpactMagnitude; + pBuf->lastImpactPos = { info.mLastImpactPos.x, info.mLastImpactPos.y, info.mLastImpactPos.z }; + + for (int i = 0; i < 4; i++) { + // TelemWheel + pBuf->wheel[i].rotation = info.mWheel[i].mRotation; + pBuf->wheel[i].suspensionDeflection = info.mWheel[i].mSuspensionDeflection; + pBuf->wheel[i].rideHeight = info.mWheel[i].mRideHeight; + pBuf->wheel[i].tireLoad = info.mWheel[i].mTireLoad; + pBuf->wheel[i].lateralForce = info.mWheel[i].mLateralForce; + pBuf->wheel[i].gripFract = info.mWheel[i].mGripFract; + pBuf->wheel[i].brakeTemp = info.mWheel[i].mBrakeTemp; + pBuf->wheel[i].pressure = info.mWheel[i].mPressure; + for (int j = 0; j < 3; j++) { + pBuf->wheel[i].temperature[j] = info.mWheel[i].mTemperature[j]; + } + + //TelemWheelV2 + pBuf->wheel[i].wear = info.mWheel[i].mWear; + strcpy(pBuf->wheel[i].terrainName, info.mWheel[i].mTerrainName); + pBuf->wheel[i].surfaceType = info.mWheel[i].mSurfaceType; + pBuf->wheel[i].flat = info.mWheel[i].mFlat; + pBuf->wheel[i].detached = info.mWheel[i].mDetached; + } + } +} + +void SharedMemoryMapPlugin::UpdateScoring( const ScoringInfoV2 &info ) { + if (mapped) { + // ScoringInfoBase + pBuf->session = info.mSession; + pBuf->currentET = info.mCurrentET; + pBuf->endET = info.mEndET; + pBuf->maxLaps = info.mMaxLaps; + pBuf->lapDist = info.mLapDist; + pBuf->numVehicles = info.mNumVehicles; + + // ScoringInfoV2 + pBuf->gamePhase = info.mGamePhase; + pBuf->yellowFlagState = info.mYellowFlagState; + for (int i = 0; i < 3; i++) { + pBuf->sectorFlag[i] = info.mSectorFlag[i]; + } + pBuf->startLight = info.mStartLight; + pBuf->numRedLights = info.mNumRedLights; + pBuf->inRealtime = info.mInRealtime; + strcpy(pBuf->playerName, info.mPlayerName); + strcpy(pBuf->plrFileName, info.mPlrFileName); + pBuf->ambientTemp = info.mAmbientTemp; + pBuf->trackTemp = info.mTrackTemp; + pBuf->wind = { info.mWind.x, info.mWind.y, info.mWind.z }; + + pBuf->vehicle[128] = { 0 }; + for (int i = 0; i < info.mNumVehicles; i++) { + // VehicleScoringInfo + strcpy(pBuf->vehicle[i].driverName, info.mVehicle[i].mDriverName); + strcpy(pBuf->vehicle[i].vehicleName, info.mVehicle[i].mVehicleName); + pBuf->vehicle[i].totalLaps = info.mVehicle[i].mTotalLaps; + pBuf->vehicle[i].sector = info.mVehicle[i].mSector; + pBuf->vehicle[i].finishStatus = info.mVehicle[i].mFinishStatus; + pBuf->vehicle[i].lapDist = info.mVehicle[i].mLapDist; + pBuf->vehicle[i].pathLateral = info.mVehicle[i].mPathLateral; + pBuf->vehicle[i].trackEdge = info.mVehicle[i].mTrackEdge; + pBuf->vehicle[i].bestSector1 = info.mVehicle[i].mBestSector1; + pBuf->vehicle[i].bestSector2 = info.mVehicle[i].mBestSector2; + pBuf->vehicle[i].bestLapTime = info.mVehicle[i].mBestLapTime; + pBuf->vehicle[i].lastSector1 = info.mVehicle[i].mLastSector1; + pBuf->vehicle[i].lastSector2 = info.mVehicle[i].mLastSector2; + pBuf->vehicle[i].lastLapTime = info.mVehicle[i].mLastLapTime; + pBuf->vehicle[i].curSector1 = info.mVehicle[i].mCurSector1; + pBuf->vehicle[i].curSector2 = info.mVehicle[i].mCurSector2; + pBuf->vehicle[i].numPitstops = info.mVehicle[i].mNumPitstops; + pBuf->vehicle[i].numPenalties = info.mVehicle[i].mNumPenalties; + + // VehicleScoringInfoV2 + pBuf->vehicle[i].isPlayer = info.mVehicle[i].mIsPlayer; + pBuf->vehicle[i].control = info.mVehicle[i].mControl; + pBuf->vehicle[i].inPits = info.mVehicle[i].mInPits; + pBuf->vehicle[i].place = info.mVehicle[i].mPlace; + strcpy(pBuf->vehicle[i].vehicleClass, info.mVehicle[i].mVehicleClass); + pBuf->vehicle[i].timeBehindNext = info.mVehicle[i].mTimeBehindNext; + pBuf->vehicle[i].lapsBehindNext = info.mVehicle[i].mLapsBehindNext; + pBuf->vehicle[i].timeBehindLeader = info.mVehicle[i].mTimeBehindLeader; + pBuf->vehicle[i].lapsBehindLeader = info.mVehicle[i].mLapsBehindLeader; + pBuf->vehicle[i].lapStartET = info.mVehicle[i].mLapStartET; + pBuf->vehicle[i].pos = { info.mVehicle[i].mPos.x, info.mVehicle[i].mPos.y, info.mVehicle[i].mPos.z }; + pBuf->vehicle[i].speed = sqrtf((info.mVehicle[i].mLocalVel.x * info.mVehicle[i].mLocalVel.x) + + (info.mVehicle[i].mLocalVel.y * info.mVehicle[i].mLocalVel.y) + + (info.mVehicle[i].mLocalVel.z * info.mVehicle[i].mLocalVel.z)); + + } + } +} diff --git a/Win32/rFactorSharedMemoryMap.sln b/Win32/rFactorSharedMemoryMap.sln new file mode 100644 index 0000000..ddcff72 --- /dev/null +++ b/Win32/rFactorSharedMemoryMap.sln @@ -0,0 +1,22 @@ +ļ»æ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rFactorSharedMemoryMap", "rFactorSharedMemoryMap.vcxproj", "{D0C09F9B-E1D6-4A04-B698-190F52BBA156}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|Win32.ActiveCfg = Debug|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|Win32.Build.0 = Debug|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|Win32.ActiveCfg = Release|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Win32/rFactorSharedMemoryMap.vcxproj b/Win32/rFactorSharedMemoryMap.vcxproj new file mode 100644 index 0000000..2a61234 --- /dev/null +++ b/Win32/rFactorSharedMemoryMap.vcxproj @@ -0,0 +1,159 @@ +ļ»æ + + + + Debug + Win32 + + + Release + Win32 + + + + {D0C09F9B-E1D6-4A04-B698-190F52BBA156} + rFactorSharedMemoryMap + + + + DynamicLibrary + v140 + false + MultiByte + + + DynamicLibrary + v140 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25123.0 + + + .\Release\ + .\Release\ + false + + + .\Debug\ + .\Debug\ + true + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/rFactorSharedMemoryMap.tlb + + + + MaxSpeed + OnlyExplicitInline + ..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreaded + 4Bytes + true + .\Release/rFactorSharedMemoryMap.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + FastCall + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\Release/rFactorSharedMemoryMap.dll + true + .\Release/rFactorSharedMemoryMap.lib + MachineX86 + + + true + .\Release/rFactorSharedMemoryMap.bsc + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/rFactorSharedMemoryMap.tlb + + + + Disabled + ..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + 4Bytes + .\Debug/rFactorSharedMemoryMap.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + FastCall + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + .\Debug/rFactorSharedMemoryMap.dll + true + true + .\Debug/rFactorSharedMemoryMap.pdb + .\Debug/rFactorSharedMemoryMap.lib + MachineX86 + + + true + .\Debug/rFactorSharedMemoryMap.bsc + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Win32/rFactorSharedMemoryMap.vcxproj.filters b/Win32/rFactorSharedMemoryMap.vcxproj.filters new file mode 100644 index 0000000..8bf98db --- /dev/null +++ b/Win32/rFactorSharedMemoryMap.vcxproj.filters @@ -0,0 +1,36 @@ +ļ»æ + + + + {525d8b82-064f-44e3-b99e-69bee26097aa} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {bb2387d8-3694-45b8-a6e1-4988539c2279} + h;hpp;hxx;hm;inl + + + {330d6860-fa50-4e92-90ee-df26f5984c63} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/pyRF1.py b/pyRF1.py new file mode 100644 index 0000000..83fd511 --- /dev/null +++ b/pyRF1.py @@ -0,0 +1,209 @@ +""" +pyRF1.py - Defines the shared memory map structures for rFactor + as exported by rFactorSharedMemoryMap.dll +by Dan Allongo (daniel.s.allongo@gmail.com) + +Release History: +2016-05-09: Initial release +""" + +from ctypes import * + +class rfStruct(Structure): + _pack_ = 1 + +class rfGamePhaseEnum(rfStruct): + _fields_ = [('garage', c_int), + ('warmUp', c_int), + ('gridWalk', c_int), + ('formation', c_int), + ('countdown', c_int), + ('greenFlag', c_int), + ('fullCourseYellow', c_int), + ('sessionStopped', c_int), + ('sessionOver', c_int)] +rfGamePhase = rfGamePhaseEnum(0, 1, 2, 3, 4, 5, 6, 7, 8) + +class rfYellowFlagStateEnum(rfStruct): + _fields_ = [('invalid', c_int), + ('noFlag', c_int), + ('pending', c_int), + ('pitClosed', c_int), + ('pitLeadLap', c_int), + ('pitOpen', c_int), + ('lastLap', c_int), + ('resume', c_int), + ('raceHalt', c_int)] +rfYellowFlagState = rfYellowFlagStateEnum(-1, 0, 1, 2, 3, 4, 5, 6, 7) + +class rfSurfaceTypeEnum(rfStruct): + _fields_ = [('dry', c_int), + ('wet', c_int), + ('grass', c_int), + ('dirt', c_int), + ('gravel', c_int), + ('kerb', c_int)] +rfSurfaceType = rfSurfaceTypeEnum(0, 1, 2, 3, 4, 5) + +class rfSectorEnum(rfStruct): + _fields_ = [('sector3', c_int), + ('sector1', c_int), + ('sector2', c_int)] +rfSector = rfSectorEnum(0, 1, 2) + +class rfFinishStatusEnum(rfStruct): + _fields_ = [('none', c_int), + ('finished', c_int), + ('dnf', c_int), + ('dq', c_int)] +rfFinishStatus = rfFinishStatusEnum(0, 1, 2, 3) + +class rfControlEnum(rfStruct): + _fields_ = [('nobody', c_int), + ('player', c_int), + ('ai', c_int), + ('remote', c_int), + ('replay', c_int)] +rfControl = rfControlEnum(-1, 0, 1, 2, 3) + +class rfWheelIndexEnum(rfStruct): + _fields_ = [('frontLeft', c_int), + ('frontRight', c_int), + ('rearLeft', c_int), + ('rearRight', c_int)] +rfWheelIndex = rfWheelIndexEnum(0, 1, 2, 3) + +class rfVec3(rfStruct): + _fields_ = [('x', c_float), + ('y', c_float), + ('z', c_float)] + +class rfWheel(rfStruct): + _fields_ = [('rotation', c_float), + ('suspensionDeflection', c_float), + ('rideHeight', c_float), + ('tireLoad', c_float), + ('lateralForce', c_float), + ('gripFract', c_float), + ('brakeTemp', c_float), + ('pressure', c_float), + ('temperature', c_float*3), + ('wear', c_float), + ('terrainName', c_char*16), + ('surfaceType', c_int8), + ('flat', c_bool), + ('detached', c_bool)] + +class rfVehicleInfo(rfStruct): + _fields_ = [('driverName', c_char*32), + ('vehicleName', c_char*64), + ('totalLaps', c_short), + ('sector', c_int8), + ('finishStatus', c_int8), + ('lapDist', c_float), + ('pathLateral', c_float), + ('trackEdge', c_float), + ('bestSector1', c_float), + ('bestSector2', c_float), + ('bestLapTime', c_float), + ('lastSector1', c_float), + ('lastSector2', c_float), + ('lastLapTime', c_float), + ('curSector1', c_float), + ('curSector2', c_float), + ('numPitstops', c_short), + ('numPenalties', c_short), + ('isPlayer', c_bool), + ('control', c_int8), + ('inPits', c_bool), + ('place', c_int8), + ('vehicleClass', c_char*32), + ('timeBehindNext', c_float), + ('lapsBehindNext', c_long), + ('timeBehindLeader', c_float), + ('lapsBehindLeader', c_long), + ('lapStartET', c_float), + ('pos', rfVec3), + ('speed', c_float)] + +class rfShared(rfStruct): + _fields_ = [('deltaTime', c_float), + ('lapNumber', c_long), + ('lapStartET', c_float), + ('vehicleName', c_char*64), + ('trackName', c_char*64), + ('pos', rfVec3), + ('localVel', rfVec3), + ('localAccel', rfVec3), + ('oriX', rfVec3), + ('oriY', rfVec3), + ('oriZ', rfVec3), + ('localRot', rfVec3), + ('localRotAccel', rfVec3), + ('speed', c_float), + ('gear', c_long), + ('engineRPM', c_float), + ('engineWaterTemp', c_float), + ('engineOilTemp', c_float), + ('clutchRPM', c_float), + ('unfilteredThrottle', c_float), + ('unfilteredBrake', c_float), + ('unfilteredSteering', c_float), + ('unfilteredClutch', c_float), + ('steeringArmForce', c_float), + ('fuel', c_float), + ('engineMaxRPM', c_float), + ('scheduledStops', c_int8), + ('overheating', c_bool), + ('detached', c_bool), + ('dentSeverity', c_int8*8), + ('lastImpactET', c_float), + ('lastImpactMagnitude', c_float), + ('lastImpactPos', rfVec3), + ('wheel', rfWheel*4), + ('session', c_long), + ('currentET', c_float), + ('endET', c_float), + ('maxLaps', c_long), + ('lapDist', c_float), + ('numVehicles', c_long), + ('gamePhase', c_int8), + ('yellowFlagState', c_int8), + ('sectorFlag', c_int8*3), + ('startLight', c_int8), + ('numRedLights', c_int8), + ('inRealtime', c_bool), + ('playerName', c_char*32), + ('plrFileName', c_char*64), + ('ambientTemp', c_float), + ('trackTemp', c_float), + ('wind', rfVec3), + ('vehicle', rfVehicleInfo*128)] + +def mps_to_mph(m): + return (m * 2.23694) + +def mps_to_kph(m): + return (m * 3.6) + +def kpa_to_psi(k): + return (k * 0.145038) + +def c_to_f(c): + return (c * 1.8) + 32 + +def l_to_g(l): + return (l * 0.264172) + +rfMapTag = '$rFactorShared$' +rfMapHandle = None + +if __name__ == '__main__': + from mmap import mmap + + rfMapHandle = mmap(fileno=0, length=sizeof(rfShared), tagname=rfMapTag) + rfMapHandle.seek(0) + smm = rfShared.from_buffer_copy(rfMapHandle) + print "{0}".format(smm.numVehicles) + for d in smm.vehicle: + print d.driverName, d.vehicleName, d.vehicleClass