Initialization Via GetPrivateProfile*...

SephirothSephiroth Fayetteville, NC, USA
OK, my customizable controls works great, but now I need to store this configuration and retrieve it. Long ago I learned of "WritePrivateProfileString" and the other function to read in the file. However, something is NOT working and my array of char's are staying NULL. Here's my source.
[code]
...
char keys[256], ctrls[4];
...
void SaveConfig()
{
WritePrivateProfileString("Controls", "Forward", &ctrls[0], "Config.CTL");
WritePrivateProfileString("Controls", "Backward", &ctrls[1], "Config.CTL");
WritePrivateProfileString("Controls", "S_Left", &ctrls[2], "Config.CTL");
WritePrivateProfileString("Controls", "S_Right", &ctrls[3], "Config.CTL");

return;
}

void LoadConfig()
{
GetPrivateProfileString("Controls", "Forward", "W", &ctrls[0], sizeof(char), "Config.CTL");
GetPrivateProfileString("Controls", "Backward", 'S', &ctrls[1], sizeof(char), "Config.CTL");
GetPrivateProfileString("Controls", "S_Left", 'A', &ctrls[2], sizeof(char), "Config.CTL");
GetPrivateProfileString("Controls", "S_Right", 'D', &ctrls[3], sizeof(char), "Config.CTL");

return;
}
[/code]
Now if I manually set a variable in ctrls like "ctrls[0] = 'A';" it works fine and when I view the file it has Forward=A in it. However when it reads the file in as the app starts, it sets ctrls[0] to NULL, and saves NULL at exit. How should I properly read this initialization file to setup my control array?

-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Comments

  • Sorry, but why don't you write a simple binary file and handle it with fwrite and fread, or with an fstream?

    An other way to do it is writing the keys in the register (as suggested by MSDN: GetPrivateProfileString "is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry.").

    Personally I found the first to be the best choice.

    nICO

  • SephirothSephiroth Fayetteville, NC, USA
    : Sorry, but why don't you write a simple binary file and handle it with fwrite and fread, or with an fstream?
    :
    : An other way to do it is writing the keys in the register (as suggested by MSDN: GetPrivateProfileString "is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry.").
    :
    : Personally I found the first to be the best choice.
    :
    : nICO
    :
    :
    I guess you don't game much :p! All of the popular online games store virtually everything (net config, key bindings, video mode, audio prefs, etc) in an INI file. If you have Half-Life, check out "config.cfg" in notepad. I think it is in "Half-Life/valve". If you have Unreal Tournament or Unreal/Unreal Gold, check out "UnrealTournament.ini" in "UT/System" or "Unreal.ini" in "Unreal/System". These ini files may be an obsolete way of writing for a Windows application, but if I want to tweak out my game I can use plain old Notepad and edit anything I want. In fact, due to the huge amount of changes that Valve made to Half-Life, sometimes the only way to find new variables is to open your config file and see what is there thatw asn't in a previous version. This is why I need to use an INI file structure for the game configuration. I want the people who play the game to be able to easily tweak the game to run on almost any hardware config.

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • Ok, that's a good point!
    Pheraphs GetPrivateProfileString gives you the opportunity to write and read in a particular section of the file, and this can be good, but I think doing something like this will be the same:

    FILE *fp;
    if(!fp=fopen("game.cfg", "w"))
    {
    // Error
    }
    else
    {
    //fwrite what you need to write
    }

    fclose(fp);

    I usually do in this way, when writing a .cfg file.

    PS: this is only my opinion, but I think it's better to write a little program that gives the user the opportunity to change the configuration (which will br written in binary), rather then letting the user change the ini file manually.
    You're right when you say that many games have .ini files, but I can reply saying that often you find useless (for you) info in ini...; For example I'm looking at the .ini file of NeverwinterNights: there's a lot of stuff about my system (processor, RAM, OS etc.), which I won't ever have the need to change...
    Clearly if the ini file is particulary big, and new options are often added it can be boresome to update the config program... it's your choice!

    bye
    nICO
  • SephirothSephiroth Fayetteville, NC, USA
    The NWN file you were looking at had that info for a reason. Unlike most games which are optimized for Intel, NWN has a seperate library that is optimized for AMD. So let's say you change your processor. You can now update your config and get the most out of it whilst playing. We use INI files for a reason. Heck in some cases there are things that can only be modified by the config file. If the config is binary (like in Daggerfall or Arena) you must use a Binary/Hex editor and be VERY familiar with the file format to tweak it out. I am, and I now set my view distance to the max the Daggerfall Engine supports by hex-editing the config file. In-game only allows you to go to half of this. The reason was that at the time of the release of Daggerfall, most systems couldn't dream of seeing that far and running smoothly. There are many more things in there I am now toying with, but if it was plain text, it'd be a billion times easier.

    I can get the app to write whatever I manually set each key to, but how do I read just the one character back into the array at startup?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • [b][red]This message was edited by chick80 at 2002-9-2 1:34:53[/red][/b][hr]
    : I can get the app to write whatever I manually set each key to, but how do I read just the one character back into the array at startup?

    Sorry, I don't understand... what do you mean with "read just the one character back"???

    Anyway try something like this (I tried with GetPrivateProfile, but I can't make it work):

    [code]
    #include
    #include

    using namespace std;

    void main()
    {
    int i;
    char keys[4], *name[4];
    fstream cfgfile;

    for (i=0; i<4; i++)
    name[i] = (char*) calloc(sizeof(char), 10);

    strcpy(name[0], "Fwd");
    strcpy(name[1], "Back");
    strcpy(name[2], "Left");
    strcpy(name[3], "Right");

    for (i=0; i<4; i++)
    {
    cout << "Insert key for " << name[i] << " : ";
    cin >> keys[i];
    }

    cfgfile.open("keys.cfg", ios_base::out);

    for (i=0; i<4; i++)
    cfgfile << name[i] << "=" << keys[i] << endl;
    cfgfile.close();

    // Now read what we wrote

    cfgfile.open("keys.cfg", ios_base::in);
    for (i=0; i<4; i++)
    {
    // Read until a = is reached
    cfgfile.get(name[i], 10, '=');
    // Goes 1 char forward (skips the '=')
    cfgfile.seekg(1, ios_base::cur);
    cfgfile >> keys[i];

    cout << name[i] << " = " << keys[i] << endl;
    }
    }
    [/code]

    PS: you make me curious... ;-) what kind of game are you programming?
    bye
    nICO



  • Hi,

    I think you will jave to provide NULL terminated strings as input parms for WritePrivateProfileString and then it should work
  • : Hi,
    :
    : I think you will jave to provide NULL terminated strings as input parms for WritePrivateProfileString and then it should work
    :
    [blue]He's right, you know...

    You declare:

    char ctrl [4];

    so, if you address it like:

    &char [0]

    that is one symbol, and INI file requires a string, which means it needs a symbol at the end. Better way will be:

    char dirkeys [5];

    strcpy (dirkeys, "WSAD");
    WritePrivateProfileString ("Keys", "Direction", dirkeys, "File.Ini");[/blue]
  • SephirothSephiroth Fayetteville, NC, USA
    : [blue]He's right, you know...
    :
    : You declare:
    :
    : char ctrl [4];
    :
    : so, if you address it like:
    :
    : &char [0]
    :
    : that is one symbol, and INI file requires a string, which means it needs a symbol at the end. Better way will be:
    :
    : char dirkeys [5];
    :
    : strcpy (dirkeys, "WSAD");
    : WritePrivateProfileString ("Keys", "Direction", dirkeys, "File.Ini");[/blue]
    :
    It isn't the writing part that is my problem. I have seen the INI file and it has stored the variables properly, but reading them back in ALWAYS returns nothing, and the default parameter isn't even used. It's easy as heck to write the file though.

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • : : [blue]He's right, you know...
    : :
    : : You declare:
    : :
    : : char ctrl [4];
    : :
    : : so, if you address it like:
    : :
    : : &char [0]
    : :
    : : that is one symbol, and INI file requires a string, which means it needs a symbol at the end. Better way will be:
    : :
    : : char dirkeys [5];
    : :
    : : strcpy (dirkeys, "WSAD");
    : : WritePrivateProfileString ("Keys", "Direction", dirkeys, "File.Ini");[/blue]
    : :
    : It isn't the writing part that is my problem. I have seen the INI file and it has stored the variables properly, but reading them back in ALWAYS returns nothing, and the default parameter isn't even used. It's easy as heck to write the file though.
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
    :
    :
    [blue]Again... you saving/loading chars, but API doing it with strings. Your problem is "sizeof(char)" - you have 1 char to save "W" - and "W" takes 2 chars to store 'W' and ''. That is why you get only '' back. If you use all 4 in one string - you read/write them faster and less code - best for everyone!

    Cheers![/blue]
  • SephirothSephiroth Fayetteville, NC, USA
    [b][red]This message was edited by Sephiroth at 2002-9-4 18:36:19[/red][/b][hr]
    Ah I see what you're saying now. So for the four keys to be done individually, I'd need ctrls[8]. Then I would only reference odd numbers since all the even ones would be . I'll try it out. Thanks again ASM. You know if you were paid every time you helpd somebody get an app working right you'd be well off, and if I paid you every time you'd probably give Billy-Bob Gates a run for his money, haha!

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

    Had to make a note. The keys would be EVEN and the 's would be ODD :p!

  • SephirothSephiroth Fayetteville, NC, USA
    : [blue]Again... you saving/loading chars, but API doing it with strings. Your problem is "sizeof(char)" - you have 1 char to save "W" - and "W" takes 2 chars to store 'W' and ''. That is why you get only '' back. If you use all 4 in one string - you read/write them faster and less code - best for everyone!
    :
    : Cheers![/blue]
    :
    ASDF!@# I just tried it and though it now PROPERLY write the file (ie: Forward=W Backward=S etc etc instead of Forward=WSZCAD Backward=SZCAD etc etc) it STILL won't read it back in! Here's the source.
    [code]
    char ctrls[12];
    ...
    void SaveConfig()
    {
    WritePrivateProfileString("Controls", "Forward", &ctrls[0], "Config.CTL");
    WritePrivateProfileString("Controls", "Backward", &ctrls[2], "Config.CTL");
    WritePrivateProfileString("Controls", "T_Left", &ctrls[4], "Config.CTL");
    WritePrivateProfileString("Controls", "T_Right", &ctrls[6], "Config.CTL");
    WritePrivateProfileString("Controls", "S_Left", &ctrls[8], "Config.CTL");
    WritePrivateProfileString("Controls", "S_Right", &ctrls[10], "Config.CTL");

    return;
    }

    void LoadConfig()
    {
    GetPrivateProfileString("Controls", "Forward", "W", &ctrls[0], sizeof(char), "Config.CTL");
    GetPrivateProfileString("Controls", "Backward", "S", &ctrls[2], sizeof(char), "Config.CTL");
    GetPrivateProfileString("Controls", "T_Left", "Z", &ctrls[4], sizeof(char), "Config.CTL");
    GetPrivateProfileString("Controls", "T_Right", "C", &ctrls[6], sizeof(char), "Config.CTL");
    GetPrivateProfileString("Controls", "S_Left", "A", &ctrls[8], sizeof(char), "Config.CTL");
    GetPrivateProfileString("Controls", "S_Right", "D", &ctrls[10], sizeof(char), "Config.CTL");

    /* ctrls[0] = 'W';
    ctrls[1] = '';
    ctrls[2] = 'S';
    ctrls[3] = '';
    ctrls[4] = 'Z';
    ctrls[5] = '';
    ctrls[6] = 'C';
    ctrls[7] = '';
    ctrls[8] = 'A';
    ctrls[9] = '';
    ctrls[10] = 'D';
    ctrls[11] = '';*/

    return;
    }
    [/code]
    Now that commented code was used to generate the file, which it did properly. I then commented that manual assigning and recompiled. It loaded and all the characters were blank, and when it saved, it saved nothing for all keys. What am I missing here? It's about to drive me up a wall!

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • Your code seams to grow and grow...
    Would not be easier to write your own file parsing routine?
    Like: WriteToINI("Left","A"); or WriteToINI(); //writes out all
    and ReadFromINI("Left"); ????

    All you need inside, is search for text Left, than read/write the string between the '=' and the 0D0Ah (EOF,NL).
    And Your ini/cfg/i dont know can look like this:

    Left=A
    Right=S
    Up=K
    Down=M

    This way, your ini files are readable, and editable by the user, and you can update it from your program, simply using the ReadFromINI();WriteToINI(); functions.

    So, basically The user uses regular text editor, you are using simple functions in your game, and those functions use binary file handling...
    Everyone is happy.

    What you have to watch for:In the write function, when some variables are modified, create/rewrite the whole file from those variables. This way, you don't have to bother with insertion routines (when the new string is longer than the old was, so you need to move the rest of the file contents./
    In my opinion, this is the fastest way to do it, since when you play around with the windows function you mentioned above, it does the same, probably in the more un-efficient way.
    And use:CreateFile(),ReadFile(),WriteFile(),CloseHandle();
    Your write function should be like this:
    WriteToINI()
    {
    CreateFile(); //use CREATE_ALWAYS, and set file pointer to 0 SetFilePointer();
    Start:
    Write out Wariable name
    Write out "="
    Write out wariable
    Write out 0D0Ah //new line
    all the variables are written?
    no -> goto Start
    CloseHandle()
    }

    And ReadFromINI(); can read the whole thing back the same way, or ReadFromINI("Left"); can read in just 1 wariable, like this: Ctrl[0] = ReadFromINI("Left");
    Anyway, this is higlhly customizabe, you can even put some text upfront, and you can have your variables in any order, and even the user modifying it, it will still work.
    It is realy not a difficult, or long code, if you want it, i can put it together for you some day...

    Edocecrous
    (your friend in trouble)
  • : : [blue]Again... you saving/loading chars, but API doing it with strings. Your problem is "sizeof(char)" - you have 1 char to save "W" - and "W" takes 2 chars to store 'W' and ''. That is why you get only '' back. If you use all 4 in one string - you read/write them faster and less code - best for everyone!
    : :
    : : Cheers![/blue]
    : :
    : ASDF!@# I just tried it and though it now PROPERLY write the file (ie: Forward=W Backward=S etc etc instead of Forward=WSZCAD Backward=SZCAD etc etc) it STILL won't read it back in! Here's the source.
    : [code]
    : char ctrls[12];
    : ...
    : void SaveConfig()
    : {
    : WritePrivateProfileString("Controls", "Forward", &ctrls[0], "Config.CTL");
    : WritePrivateProfileString("Controls", "Backward", &ctrls[2], "Config.CTL");
    : WritePrivateProfileString("Controls", "T_Left", &ctrls[4], "Config.CTL");
    : WritePrivateProfileString("Controls", "T_Right", &ctrls[6], "Config.CTL");
    : WritePrivateProfileString("Controls", "S_Left", &ctrls[8], "Config.CTL");
    : WritePrivateProfileString("Controls", "S_Right", &ctrls[10], "Config.CTL");
    :
    : return;
    : }
    :
    : void LoadConfig()
    : {
    : GetPrivateProfileString("Controls", "Forward", "W", &ctrls[0], [red]sizeof(char)[/red], "Config.CTL");
    : GetPrivateProfileString("Controls", "Backward", "S", &ctrls[2], [red]sizeof(char)[/red], "Config.CTL");
    : GetPrivateProfileString("Controls", "T_Left", "Z", &ctrls[4], [red]sizeof(char)[/red], "Config.CTL");
    : GetPrivateProfileString("Controls", "T_Right", "C", &ctrls[6], [red]sizeof(char)[/red], "Config.CTL");
    : GetPrivateProfileString("Controls", "S_Left", "A", &ctrls[8], [red]sizeof(char)[/red], "Config.CTL");
    : GetPrivateProfileString("Controls", "S_Right", "D", &ctrls[10], [red]sizeof(char)[/red], "Config.CTL");
    :
    : /* ctrls[0] = 'W';
    : ctrls[1] = '';
    : ctrls[2] = 'S';
    : ctrls[3] = '';
    : ctrls[4] = 'Z';
    : ctrls[5] = '';
    : ctrls[6] = 'C';
    : ctrls[7] = '';
    : ctrls[8] = 'A';
    : ctrls[9] = '';
    : ctrls[10] = 'D';
    : ctrls[11] = '';*/
    :
    : return;
    : }
    : [/code]
    : Now that commented code was used to generate the file, which it did properly. I then commented that manual assigning and recompiled. It loaded and all the characters were blank, and when it saved, it saved nothing for all keys. What am I missing here? It's about to drive me up a wall!
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
    :
    :

  • SephirothSephiroth Fayetteville, NC, USA
    OK I feel dumb now. I forgot to change it to sizeof(char[2]). Now that I have, it works fine. I guess I was in a hurry last night and didn't pay attention to the code :p! Thanks ASM.

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories