The online racing simulator
Searching in All forums
(976 results)
MadCatX
S3 licensed
You're making it next to impossible to help you. When you tell us stuff like "I don't know what's wrong with this" or "Not working" nobody can even guess what could be wrong. What do you expect your program to do and what actually happens?
MadCatX
S3 licensed
I used to drive a BA Protegé a while back and as far as I remember from others' experience the MAF sensor could occasionally fail and cause all sorts of weird behavior. One of suggested diagnostic tricks was to disconnect the MAF altogeher. The ECU would then switch to some fallback maps which should work better than when the ECU is fed with bogus data from the faulty MAF.

EDIT:
I did some Googling on the issue and I came up with two articles on the topic, especially the second one seems interesting. The upshot from the articles is that a vaccuum leak is probably the cause since the car is having problem at idle and not at higher revs.

http://www.obd-codes.com/faq/fuel-trims.php
http://wiki.ross-tech.com/wiki/index.php/Fuel_Trim_Info
Last edited by MadCatX, .
MadCatX
S3 licensed
A new hardware survey is a good idea, but the options you put to the poll are somewhat odd. If I may suggest a few improvements, I'd go with:

GPU:
Option A: Radeon R7/R9, nVidia 800/900 series or equivalent
Option B: Radeon HD7000/8000, nVidia 600/700 series or equivalent
Option C: Any older AMD or nVidia dedicated GPU
Option D: Integrated GPU
The amount of VRAM or supported DirectX version say next to nothing about the card's actual performace. Moreover Mac or Linux users can't get such information without looking up the card's specs.

CPU:
Option A: Two cores or less (excluding HT)
Option B: Four cores (excluding HT)
Option C: Six or more cores (excluding HT)

The OS poll absolutely needs Windows XP option.
MadCatX
S3 licensed
There are obviously multiple solutions to this problem, some of them are better, some other are worse. Worse solutions will be more error-prone and you'll have to write more plumbing code to keep things working. I would've probably done something like this. It's probably not the best solution possible because I came up with it in like 5 minutes. It's just supposed to show that UCID and PLID handling is quite easy if you design the application neatly.



using LFS_Connection = System.Collections.Generic.List<byte>;

class LFS_Player {
byte PLID;
byte UCID;
bool inPits;

class GameData; // Something specific to your game

LFS_Player(byte PLID, byte UCID) {
this.PLID = PLID;
this.UCID = UCID;
}

void takenOver(const byte UCID) {
this.UCID = UCID;
}

void enteredPits() {
inPits = true;
}

void leftPits() {
inPits = false;
}

...
}

Dictionary<byte, LFS_Player> activePlayers;
Dictionary<byte, LFS_Connection> activeConnections;

void on_IS_NCN(ncn) {
if (activeConnections.ContainsKey(ncn.UCID)) {
// This connection is already registered, this should not happen. Throw an error
}

activeConnections[ncn.UCID] = new LFS_Connection();
}

void on_IS_NPL(npl) {
// If the PLID is already registered, player left pits
if (activePlayers.ContainsKey(npl.PLID)) {
activePlayers[npl.PLID].leftPits();
return;
}

// Register new player within the players' list
AddNewPlayer(npl.PLID, npl.UCID);

// Add PLID of the new player to the list of PLIDs belonging to the respective UCID
if (!activeConnections.ContainsKey(npl.UCID)) {
// UCID of this player is not registered. Throw an error as this cannot happen
}
activeConnections[npl.UCID].Add(npl.PLID);
}

void on_IS_PLL(pll) {
if (!activePlayers.ContainsKey(pll.PLID)) {
// Throw an error, this cannot happed
}
const byte UCID = activePlayers[pll.PLID].UCID;
RemovePlayer(pll.PLID);
RemovePLIDfromConnection(pll.PLID, UCID);
}

void on_IS_TOC(toc) {
RemovePLIDfromConnection(toc.PLID, toc.OldUCID);

if (!activePlayers.ContainsKey(toc.PLID)) {
// This should never happen, throw an error
}
activePlayers[toc.PLID].TakenOver(toc.NewUCID);

if (!activeConnections.ContainsKey(toc.NewUCID)) {
// This should never happen, throw an error
}
activeConnections[toc.NewUCID].Add(toc.PLID);
}

void on_IS_CNL(cnl) {
if (!activeConnections.ContainsKey(cnl.UCID)) {
// This should never happen, throw an error
}
const LFS_Connection c = activeConnections[cnl.UCID];

// Make sure that we do not have any players stored for this connections
foreach (byte PLID in c) {
if (activePlayers.ContainsKey(PLID)) {
// Throw a warning, all players for this connection should have been removed already
RemovePlayer(PLID);
}
}

activeConnections.Remove(cnl.UCID);
}

void AddNewPlayer(const byte PLID, const byte UCID) {
if (activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}
activePlayers[PLID] = new LFS_Player(PLID, UCID);

...
}

void RemovePlayer(byte PLID) {
if (!activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}

...

activePlayers.Remove(PLID);
}

void RemovePLIDfromConnection(byte PLID, byte UCID) {
if (!activeConnections.ContainsKey(UCID)) {
// This UCID should be registered, throw an error
}

activeConnections[UCID].Remove(PLID);
}


MadCatX
S3 licensed
Saving the IS_NPL packet (or any other InSim packet) is even more wrong that the previous solution. InSim packets are meant only to deliver information to or from LFS. You are not supposed to store them for later use. The right thing to do is to copy the information you need from the packet to your own data structures and throw the packet away.

Why can't you try out what I suggested and keep a "conversion maps" for UCIDs and PLIDs? That should be reasonably easy to manage and use.
MadCatX
S3 licensed
Quote from Zazcoisa :Thank you, but i have the connections list as a List<clsConnection>:
List<clsConnection> Connections = new List<clsConnection>();

and it contains:
public byte UniqueID;
public byte PlayerID;


Is this something you just copied from somebody else's code, because this is a rather poor design. If you change the type of Connections to Dictionary<byte, byte> and use PLID as a key, you can remove the whole PLID lookup loop and do just "byte UCID = Connections[PLID]" to get the UCID. You will still need the UCID lookup loop which should return a list of all PLIDs behind one UCID instead of just the first entry in the list. It could then look like this


List<byte> GetPLIDsByUCID(const byte UCID) {
List<byte> PLIDs = new List<byte>();

foreach (KeyValuePair<byte, byte> e in Connections) {
if (e.Value == UCID) {
PLIDs.Add(e.Key);
}
}

return PLIDs;
}

MadCatX
S3 licensed
Quote from Zazcoisa :Thanks for the reply

1) I have one list, and it holds 2 bytes (UCID and PLID) and i have two methods to get the index of a player in the list for each one:

int GetIDbyUCID(int UCID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].UniqueID == UCID) return i;
}
return 0;
}

int GetIDbyPLID(int PLID)
{
for (int i = 0; i < Connections.Count; i++)
{
if (Connections[i].PlayerID == PLID) return i;
}
return 0;
}

and this is where the index is being searched for:

var Conn = Connections[GetIDbyPLID(PLL.PLID)];
----------------------------------------------
var Conn = Connections[GetIDbyPLID(PLP.PLID)];


This is, unfortunately, an incorrect design.

There can be multiple PLIDs per one UCID and PLIDs can jump between UCIDs - read the excerpt from InSim.txt MariusMM quoted. A possible (but not the best) solution to the problem is this:



Dictionary<byte, List<byte>> UCID_to_PLIDs_List;
Dictionary<byte, byte> PLID_to_UCID_List;

byte GetUCIDforPLID(const byte PLID) {
if (!PLID_to_UCID_List.ContainsKey(PLID)) /
// Throw an exception because this PLID is not known
}

return PLID_to_UCID_List[PLID];
}

List<byte> GetPLIDsOfUCID(const byte UCID) {
if (!UCID_to_PLIDs_List.ContainsKey(UCID)) {
// Throw an exception because this UCID is not known
}

return new List<byte>(UCID_to_PLIDs_List[UCID]);
}


MadCatX
S3 licensed
2) There are no nodes in open configurations, hence the node number stays at zero.

3) I think the problem is pretty self-explanatory. Send() throws an exception when you try to send a packet without being connected to InSim. You have to decide how to handle this.

1) My guess would be that you are mixing up PLID and UCID somewhere but there is no way to tell what's happening when we cannot see the code.

0) Please... Use the term "InSim" correctly. What you have in not an InSim. InSim is an interface, not some general name for programs that use it... For some reason it annoys me to no end having to read this nonsense over and over....
MadCatX
S3 licensed
Did you check the contents of the modified cfg.txt to see what's changed? Some settings related to graphics only take effect after you restart LFS. There is also "card_cfg.txt" file. Do you have to delete that one as well to get LFS to start properly again? Does its content change?

Another thing is that LFS relies on the latest revision of DirectX 9 which you might not have so reinstalling DX9 as Sinanju suggested is a good idea. What GPU do you have and how old are its drivers?
MadCatX
S3 licensed
The step 3 either returns the "fake" DirectInputDevice object created by the proxy DLL or returns a "normal" DirectInputDevice object. Only calls made upon the "fake" object (such as SetCooperativeLevel() ) will be intercepted by the proxy DLL. The logic boils down to this:


HRESULT myIDirectInput8::CreateDevice(REFGUID a, LPDIRECTINPUTDEVICE8W *b, LPUNKNOWN c)
{
if (WantToIntercept(a)) {
LPDIRECTINPUTDEVICE8W fake;
HRESULT res = CreateFakeDIObject(&fake); // my own function
gl_myFakeObjectsStorage[FreeSlot] = fake;
*b = fake;
return hres;
}
return CreateDevice(a, b, c); // DirectInput internal function
}

MadCatX
S3 licensed
Setting both EXCLUSIVE and BACKGROUND flags for keyboard or mouse is invalid and DInput will throw an error when you try that. You might therefore want to check that you're trying to modify the cooperative level only on the device you want to use. The handling of these invalid flags is perhaps different on WinXP which is why LFS crashed for you. If it's any help, I did it like this when I wanted to check for a Logitech G27 in my proxied dinput8.dll. BTW, I found out that calling Beep() from a proxy DLL is a crude but effective way to check that the code reaches a certain place Smile

1) An application has to enumerate the devices first so let's take advantage of that and enumerate them along with it

HRESULT myIDirectInput8::EnumDevices(DWORD a, LPDIENUMDEVICESCALLBACKW b, LPVOID c, DWORD d)
{
m_pIDirectInput8->EnumDevices(a, MyDevEnumCallBack, c, d);
return m_pIDirectInput8->EnumDevices(a, b, c, d);
}

2) Get some interesting info about a device during the enumeration

BOOL CALLBACK myIDirectInput8::MyDevEnumCallBack(const DIDEVICEINSTANCE* inst, VOID* context)
{
UNREFERENCED_PARAMETER(context);

/* Here is where we store the GUIDs of devices that we want to manipulate with later */
extern std::vector<GUID> gl_myG27Instance;

/* Check the device's identity */
if ((inst->guidProduct.Data1 == G27ID) /* || (inst->guidProduct.Data1 == DFPID) */) {
/* Check if we already have this device added */
if (gl_myG27Instance.size() > 20)
return DIENUM_CONTINUE;

for (std::vector<GUID>::const_iterator cit = gl_myG27Instance.begin(); cit != gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(inst->guidProduct, *cit))
return DIENUM_CONTINUE;
}

gl_myG27Instance.push_back(inst->guidInstance);
}

return DIENUM_CONTINUE;
}

3) OK, now we know the GUIDs that reference the devices we're interested in so let's intercept only those devices */

HRESULT myIDirectInput8::CreateDevice(REFGUID a, LPDIRECTINPUTDEVICE8W *b, LPUNKNOWN c)
{
extern std::vector<GUID> gl_myG27Instance;
std::vector<GUID>::const_iterator cit;
for (cit = gl_myG27Instance.begin(); cit < gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(a, *cit)) {
/* A G27 (or DFP) found, take control over this device */
// global var
extern myIDirectInputDevice8* gl_pmyIDirectInputDevice8Array[];

LogMessage(L"DI::CreateDevice> Creating DIDevice");

// we intercept this call and provide our own "fake" Device Object
HRESULT hres = m_pIDirectInput8->CreateDevice(a,b,c);

/*
* Check for error
*/

// find free Device slot
int i;
for (i=0; i<MAXNUMBER_DEVICES; i++)
if (gl_pmyIDirectInputDevice8Array[i] == NULL) break;

/*
* Should return an error if i == MAXNUMBER_DEVICES
*/

// Create our own Device object and store it in global pointer
// note: the object will delete itself once Ref count is zero (similar to COM objects)
gl_pmyIDirectInputDevice8Array[i] = new myIDirectInputDevice8(*b, i, *cit);

// store our pointer (the fake one) for returning it to the calling progam
*b = gl_pmyIDirectInputDevice8Array[i];

LPOLESTR guidHash;
HRESULT guidHRes = StringFromCLSID(a, &guidHash);
if (guidHRes == S_OK) {
std::wostringstream oss;
oss << L"DI::CreateDevice> Creating DIDevice, GUID " << guidHash;
LogMessage(oss.str().c_str());
CoTaskMemFree(guidHash);
} else
LogMessage(L"(WARN)DI::CreateDevice> Unable to convert GUID to string.");

if (hres == S_OK)
LogMessage(L"DI::CreateDevice> Device sucessfully created.");
else
LogMessage(L"(WARN)DI::CreateDevice> Unable to create device.");

return(hres);
}
}

/* Not a G27 (or DFP), don't touch this device */
LogMessage(L"DI::CreateDevice> Not a G27, ignoring.");
return m_pIDirectInput8->CreateDevice(a, b, c);
}

The code above is far from brilliant but it seems to have solved the problem in my G27 LEDs hack.
Last edited by MadCatX, . Reason : Pointed out two obvious issues in the code of step 3
MadCatX
S3 licensed
If you'll be passing the steering commands through emulated joystick device then maybe you can intercept the SetCooperativeLevel DInput call and replace the flags with DISCL_BACKGROUND | DISCL_EXCLUSIVE. IIRC something similar worked for me in another project. You can get a dinput8.dll proxy template from here: http://mikoweb.eu/index.php?node=28
MadCatX
S3 licensed
What exactly are you trying to do? I can't think of anything that'd require you to need to know the actual dimensions of LFS window. One thing that might be of concern is the camera FOV but that would matter only if you were trying to do some "pseudo-3D" buttons etc.
MadCatX
S3 licensed
Position of buttons is always relative to LFS window. You can check if LFS is running in fullscreen or not with ISS_WINDOWED flag in IS_STA packet but it won't work for remote hosts.
MadCatX
S3 licensed
You just need d3dx9_43.dll and D3DCompiler_43.dll to get 0.6G to work under WINE.
MadCatX
S3 licensed
The kernel in stock Ubuntu 14.04 is 3.13 which is unfortunately one version too old to detect your revision of the G27 correctly. You can use LTWC just to switch the wheel to its native mode and set the range via sysfs. All "smarter" Logitech wheels show themselves as "Logitech Driving Force" (046D:C294) at first and have to be switched to their "native" modes by the driver. The driver in kernel 3.13 doesn't recognize your G27 correctly and leaves it in the compatibility mode, therefore you cannot change the range.
MadCatX
S3 licensed
If the other players can get events such as you pitting or sending a chat message, your ISP might be blocking UDP packets from you to the host. LFS cannot work around this, you should talk to your ISP.
MadCatX
S3 licensed
What kernel version are you running? Support for this revision of G27 has been available since 3.14. It won't explain the other issues but I can't think of anything that would except that you might be using /dev/input/js instead of /dev/input/event device in games which might give you some unwanted deadzones.
MadCatX
S3 licensed
The ID doesn't appear to be among those recognized by the current kernel driver. You should be able to use LTWC to switch the wheel to the native mode though until a proper fix is in place.
MadCatX
S3 licensed
Can you post output of

lsusb -sX:Y -vvv | grep bcdDevice

where X and Y is the bus and device ID your wheel is attached to? If you got your wheel recently you might have a newer revision of the wheel that is not recognized by the driver. If that's the case I'll try to nudge the guy who wrote a patch set that is supposed to resolve this once and for all to get it mainlined.
MadCatX
S3 licensed
Even if they did use any sounds from LFS (which I doubt) they have probably converted them into some compressed audio format and perhaps run them through some filters, therefore it'll be next to impossible to prove that these files really come from LFS.
MadCatX
S3 licensed
You can back the .ply files up yourself if you need to. You really cannot expect any program to function correctly when you run it on a broken system.
MadCatX
S3 licensed
LFS probably updates the profile files upon exit. If Windows crashes shortly after LFS exits, the profile might not be synced to the hard drive properly yet which is why it gets corrupted.
MadCatX
S3 licensed
Quote from mr_spoon :The chmodding + range need to be set every time the system is rebooted or the wheel is unplugged, but I can live with that for now.

Slackware must be missing some udev rules that'd otherwise set that up automatically. It shouldn't be a problem to write your own though...
MadCatX
S3 licensed

echo xxx > /sys/module/hid_logitech/drivers/hid:logitech/*:*/range

where "xxx" is the desired range.
FGED GREDG RDFGDR GSFDG