Saving the *contents* of a structure with game_save()...

Posted By: Caermundh

Saving the *contents* of a structure with game_save()... - 03/13/11 17:19

How do I save the contents of a structure with game_save()?

I have the following, which doesnt quite work:
Code:
<headers.h>
typedef struct test_struct
{   var value1;
    var value2;
    STRING* str1;
    STRING* str2;
    STRING* str3;
    struct test_struct* next;
} test_struct;

test_struct* first_struct;
test_struct* curr_struct;

var test;
var test2;

<test.c>
#include <acknex.h>
#include <default.c>
#include "headers.h"

FONT* standard_font = "ackfont.pcx";

PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

TEXT* info_text = 
{   pos_x = 20;
    pos_y = 40;
    flags = SHOW;
    font = standard_font;
    strings = 3;
    string("             ","             ","             ");
}

TEXT* status_text = 
{   pos_x = 20;
    pos_y = 70;
    flags = SHOW;
    font = standard_font;
    strings = 1;
    string("Status: N/A");
}

function save_game()
{   game_save("test",1,SV_VARS+SV_STRUCT); 
    str_cpy((status_text.pstring)[0],"Status: Game Saved.");
}

function load_game()
{   str_remove(first_struct->str1);
    str_remove(first_struct->str2);
    str_remove(first_struct->str3);
    free(first_struct);
    game_load("test",1);
    str_cpy((status_text.pstring)[0],"Status: Game Loaded.");
}

function main()
{   on_f1 = save_game;
    on_f2 = load_game;
    first_struct = (test_struct*)malloc(sizeof(test_struct));
    first_struct->str1 = str_create("This is the first str");
    first_struct->str2 = str_create("This is the second str");
    first_struct->str3 = str_create("This is the third str");
    first_struct->value1 = 5;
    first_struct->value2 = 10;
    first_struct->next = NULL;
    add_struct(first_struct,sizeof(test_struct));
    while(key_esc==0)
    {   test = first_struct->value1;
        test2 = first_struct->value2;
        (info_text.pstring)[0] = first_struct->str1;
        (info_text.pstring)[1] = first_struct->str2;
        (info_text.pstring)[2] = first_struct->str3;
        wait(1);
    }
}


when i do a game_save() with this code, it saves first_struct->value1 & value2, and it saves the *pointers* to str1, str2, and str3, but it does not save the strings themselves. (IE when i load the game first_struct->str1 isnt equal to "This is the first str" - it is equal to whatever garbage happens to be in the memory area that the str pointer is pointing at)
Posted By: Widi

Re: Saving the *contents* of a structure with game_save()... - 03/13/11 21:53

Please edit your post with the [ code ] tag.

[ code ]
...your code
[ /code ]

(without spaces)
It is not so easy to read code if it is not indent!!!
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/20/11 21:06

Anyone? No one has any ideas?
Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/20/11 22:02

Ideas concerning what? That is exactly the intended behaviour. If you don't want this behaviour use handles or texts instead.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/20/11 22:57

Ok..it sounds like im not understanding the concept then. I'm more than ready to admit ignorance on the subject, but what good does it do to save an area of memory without saving the contents of that area of memory? I'm sorry but i just dont get how thats useful or what can be done with that.
Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 00:42

The content of the area of memory is saved. Unfortunately in your case the content is an address. You can of course save the address to a harddisk and load it later on. The big question then is, if that address is still valid, i.e. if the pointer points at a valid address with usefull data in it. The concept nevertheless does a lot of good, because you can save arbitrary data with it - with the exception for pointers, which can be loaded and saved as well, but do not make any sense after loading. Why don't you just use handles instead of the pointers?
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 01:04

You have to create a new object using sys_malloc. Then from the memory it is saved.
Then to call the information back you just recall it back from main and it will reset the info that was saved and populate the members of struct.

Code:
typedef struct PERSO{
	
	int age;
	char* name;
	char* nickname;
	
} PERSO;

PERSO* Person;

PERSO* new_person()
{
	PERSO* new = sys_malloc(sizeof(PERSO));
	memset(new,0,sizeof(PERSO));
	new->nickname = "Toto_2"; // test name
	new->age = 18;	
	
	add_struct(new,sizeof(PERSO));
	return new;
}

void main()
{
Person = new_person(); //
}


Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 01:34

@Uhwerk:

Im not using handles because i guess i didnt know to. As well, a handle points to a global engine object such as a golbal panel, string or bitmap right?

im using structs because im reading all the items for the game from a text file. There is an unknown number of objects, so i use malloc to grab as much memory as i need. If i use global panel and string arrays, i would have these huge arrays that i'd end up only using like half of.

Granted, if the only way i can save a string, panel, or bmap is to make it global and use handles, then i guess ill just have to put up with huge arrays. I would dearly love a more sleek solution, though.

@Paracharlie:

you are using sys_malloc instead of malloc? what exactly is the difference? and what does the call to memset() do? ive never heard of that function.
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 02:00

Memset is C and its allocating a block of memory to the heap.
sys_malloc is a predefine in gamestudio. malloc and new is supposably slower and is to C what sys_malloc is to gamestudio. You can click and read the description in gamestudio. Explains it better then I can.

Basically you are creating a pointer to your struct. Then your allocating a block of dynamic memory to hold the data that is stored in your struct and now that it's safely tucked away in memory you can save it with game_save.

Here is actual code from my game and yes it is this easy.

Code:
typedef struct PLR
{	
   var p_STR;  //Roll 3D6
   var p_CON;  //Roll 3D6
   var p_DEX;  //Roll 3D6
   var p_SIZ;  //Roll 2D6
   var p_INT;  //Roll 2D6 + 6
   var p_POW;  //Roll 3D6
   var p_CHA;  //Roll 3D6
   var p_PHY;  //Roll 3d6
}PLR;
PLR* plr;//create a pointer variable called plr used in game_load() see main.

//make stat struct saveable
function p_save_struct()//create a function that will dynamically hold the contents of PLR struct.
{
	PLR* new = sys_malloc(sizeof(PLR));//create a pointer variable called new(call it whatever you want), get the size of PLR struct and point to it.
	memset(new,0,sizeof(PLR));//allocate memory for it on the heap.  Remember there is stack and heap?	
	add_struct(new,sizeof(PLR));//add the size of the struct PLR to add_struct, making it game_save() saveable.
	return new;//now return the value of new so that p_save_struct is worth something
}

void main()
{
plr = p_save_struct();
}


Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 02:01

memset sets an area of memory to the value specified. In paracharlies example the memory area "new" points to is overwritten with the value "0" at a length of "sizeof(PERSO)" (= 12) bytes. This is a good practice in c to avoid vagabonding pointers.

I didn't know that there is a connection betweeen sys_malloc and game_save. I didn't find any hints in the manual on that topic...

The handle thing is really easy. You can call handle() to get the handle of any engine object, regardless if it is string, a bitmap, or whatever. You can convert that handle to a pointer easily by calling ptr_for_handle(). It works the same as handle(), just the other way around. The advantage is, that handles - unlike pointers - are even valid after a save / load or even after a complete game or computer restart. If you just want to save "pointers" to engine objects like panels, strings and the like a combination of handles and structs could be an elegant solution for you.

EDIT: Charlie was faster... ^^

EDIT2: memset has absolutely nothing to do with memory allocation. See my explanation above... The code above does not really help with the problem as the struct does not contain any pointers...
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 02:11

I think that is what memset does? I dont know I been using C++ and new and havent used that in awhile. I dont even remember now to be honest.

Oh wait I remember, your just setting the size of the memory sys_malloc is allocating sorry for misleading you. I dont retain info for very long lol...
Posted By: MrGuest

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 09:47

memset has nothing to do with setting memory to the heap, as Uhrwerk said it is setting the memory address to the character you specify (usually 0 to clear the previous data)

Example:
Code:
// crt_memset.c
/* This program uses memset to
 * set the first four chars of buffer to "*".
 */

#include <memory.h>
#include <stdio.h>

int main( void )
{
   char buffer[] = "This is a test of the memset function";

   printf( "Before: %s\n", buffer );
   memset( buffer, '*', 4 );
   printf( "After:  %s\n", buffer );
}



Output:
Code:
Before: This is a test of the memset function
After:  **** is a test of the memset function


Resource
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 13:22

void * memset ( void * ptr, int value, size_t num );
It exists on the heap.
as does your memory buffer.
which can be *array or array[0] both the same. Arrays are pointers.
The thing I dont understand though; shouldnt it be '\0' for null character? Instead of 0 and why does that work?
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 13:57

Paracharlie:

I tried using sys_malloc instead of malloc, and the result is the same - the strings were not saved. I think Uhwerk is on the right track - I have to make the strings global, set the struct to store the handle of the global str and do a game_save() with SV_STRINGS.
Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 14:17

@paracharlie memset doesn't give a f*** if the pointer points to the heap or to the stack. MrGuest called it character, although the term byte seems a bit better to me. memset is not limited to writing characters, as the the term "char" might suggest. Technically speaking '\0', NULL, and 0 are the same, i.e. a lot of bits where no bit corresponds to '1'. '\0' can be 8 or 16 bits, NULL is 32 bits as well as 0 as it is by default interpreted as an integer constant.

Caermundh: I already thought that wouldn't work. It would require some magic to work. However: The handle thing is not a more of work for you. You cannot have local strings anyways. A string is always an engine object, so there is no need to make it global in some way.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 14:19

SUCCESS!!!!

The following code works:

Code:
///////////////////////////////////////////////////////////////////
// headers.h - headers file for test

typedef struct test_struct
{   var value1;
    var value2;
    STRING* str1;
    STRING* str2;
    STRING* str3;
    struct test_struct* next;
} test_struct;

typedef struct save_struct
{   var value1;
    var value2;
    var str1;
    var str2;
    var str3;
    struct save_struct* next;
} save_struct;

test_struct* first_struct;
test_struct* curr_struct;

save_struct* first_save;
save_struct* curr_save;

var test;
var test2;


//////////////////////////////////////////////////////////////////////
// test.c

#include <acknex.h>
#include <default.c>
#include "headers.h"

FONT* standard_font = "ackfont.pcx";

PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

TEXT* info_text = 
{   pos_x = 20;
    pos_y = 40;
    flags = SHOW;
    font = standard_font;
    strings = 3;
    string("             ","             ","             ");
}

TEXT* status_text = 
{   pos_x = 20;
    pos_y = 70;
    flags = SHOW;
    font = standard_font;
    strings = 1;
    string("Status: N/A");
}

TEXT* save_text;

function save_game()
{   save_text = txt_create(3,1);
    (save_text.pstring)[0] = str_create(first_struct->str1);
    (save_text.pstring)[1] = str_create(first_struct->str2);
    (save_text.pstring)[2] = str_create(first_struct->str3);
    first_save->value1 = first_struct->value1;
    first_save->value2 = first_struct->value2;
    first_save->str1 = handle((save_text.pstring)[0]);
    first_save->str2 = handle((save_text.pstring)[1]);
    first_save->str3 = handle((save_text.pstring)[2]);
    game_save("test",1,SV_VARS+SV_STRUCT+SV_STRINGS);
    str_cpy((status_text.pstring)[0],"Status: Game Saved.");
}

function mem_clear()
{   first_struct->value1 = 0;
    first_struct->value2 = 0;
    str_remove(first_struct->str1);
    str_remove(first_struct->str2);
    str_remove(first_struct->str3);
    free(first_struct);
    str_cpy((status_text.pstring)[0],"Status: Memory Cleared.");
}

function load_game()
{   game_load("test",1);
    first_struct->value1 = first_save->value1;
    first_struct->value2 = first_save->value2;
    first_struct->str1 = str_create(ptr_for_handle(first_save->str1));
    first_struct->str2 = str_create(ptr_for_handle(first_save->str2));
    first_struct->str3 = str_create(ptr_for_handle(first_save->str3));
    str_cpy((status_text.pstring)[0],"Status: Game Loaded.");
}

function main()
{   STRING* test_str2 = "This is the local str";
    wait(3);
    on_f1 = save_game;
    on_f2 = mem_clear;
    on_f3 = load_game;
    first_struct = (test_struct*)malloc(sizeof(test_struct));
    first_struct->value1 = 5;
    first_struct->value2 = 10;
    first_struct->str1 = str_create("This is the first str");
    first_struct->str2 = str_create("This is the second str");
    first_struct->str3 = str_create("This is the third str");
    first_struct->next = NULL;
    first_save = (save_struct*)malloc(sizeof(save_struct));
    first_save->value1 = 0;
    first_save->value2 = 0;
    first_save->str1 = 0;
    first_save->str2 = 0;
    first_save->str3 = 0;
    first_save->next = NULL;
    add_struct(first_save,sizeof(save_struct));
    while(key_esc==0)
    {   test = first_struct->value1;
        test2 = first_struct->value2;
        (info_text.pstring)[0] = first_struct->str1;
        (info_text.pstring)[1] = first_struct->str2;
        (info_text.pstring)[2] = first_struct->str3;
        wait(1);
    }
}



After doing a game load, the strings were equal to "This is the xxx str" instead of random garbage. Kind of a pain to set up, but at least it works.
Thank you everyone for all your help.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 14:23

@ Uhrwerk:

I can't have local strings? I declare stings inside of functions all the time - like so:

Code:
function my_func()
{   STRING* my_str = "              ";
    str_cpy(my_str,"this is my str");
    return(0);
}



Are you saying that my_str, in this instance, is still global even though I declared it locally?

EDIT: sorry, after re-reading your post, I think I see what your saying. Even my_str or my_struct->str1 is a string that I can feed to handle() and get a handle for it right?


Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 14:46

Right. I don't know how the code you posted here behaves and can only guess here. My guess is, that the 32 bit for the pointer my_str are of course allocated on the stack and the memory required for the string itself is allocated on the heap as if you used "str_create(" ");".
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/21/11 23:45

I'm glad you have it working. I wonder if it's the way that pstring is being handled. I'll definately keep an eye on this. I use local strings for battle text in a text box using a logger script which is local and it saves everything. Kind of annoying actually and took alot of work to clear the text box after clicking load using game_save and game_load. Problem with game_save is it will save everything and anything unless you set it up properly. My problem was that I could never seem to get it set 'properly'
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 00:34

Here is a stand alone example. You should not have to write out every member of a structure or class at any time. Think about it. What if your structure or class were 3,4 or 500 lines easily done in gaming industry. I'm Finding out by using this engine more and more that the norm is not the norm and forget about what you know when you use this engine. Been using another engine in visual c++ and honestly, there is many many easier ways that wont work in gamestudio.

Code:
//test add_struct

///////////////////////////////
#include <acknex.h>
#include <default.c>

///////////////////////////////

typedef struct PERSO{
	
	int age;
	char* name;
	char* nickname;
	
} PERSO;

PERSO* Person;

PERSO* new_person()
{
	PERSO* new = sys_malloc(sizeof(PERSO));
	memset(new,0,sizeof(PERSO));
	new->nickname = "Toto_2"; // test name
	new->age = 18;	
	
	add_struct(new,sizeof(PERSO));
	return new;
}

TEXT* test =
{
	strings = 2;
   pos_x = 10;
   pos_y = 10;
   flags= SHOW;
}


function save()
{
	if(game_save("save",1,SV_ALL) <= 0)
	{
		error("save not found");
	}else{
		error("save success");
	}
}

function load()
{
	if(game_load("save",1) <= 0)
	{
		error("Load save error");
		sys_exit(NULL);
	}else{
		error("loaded save success");
		
	}
}

function quit()
{
	sys_exit(NULL);
}

function send()
{
	Person.nickname = "Toto";		

}

function main()
{

	video_mode = 7;
	video_depth = 32;
	video_screen = 2;
	level_load(NULL);
	
	on_f2 = send ;
	on_f3 = save;
	on_f4 = load;
	on_esc = quit;
	on_close = quit;
	
	Person = new_person();
	
	while(1) {
		str_cpy((test.pstring)[0], _str(Person.nickname));	
					
		wait(1);
	}
}


Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 01:13

Originally Posted By: paracharlie
You should not have to write out every member of a structure or class at any time. Think about it. What if your structure or class were 3,4 or 500 lines easily done in gaming industry.

I don't get your point here. So what if a structure was 500 lines long? Well, you can be pretty sure your design uhm... well ... leaves some space for improvements... but I don't see how this is connected to a saving or loading mechanism. You can either use game_save/game_load to let the engine do all the dirty work for you. Of course this approach cannot be controlled that fine-granular. But on the other hand you can of course use file_open_write and write out exactly what you want and skip any fields you want. You of course then have a lot more work to do, but that is the price you have to pay for more flexibility.
Posted By: paracharlie

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 01:21

Your right. My way is wrong please dont use it. It will lead to problems in gamestudio. Please do exactly what uhrwerk said to do. He is right.
And another thing. That code isn't mine. It was written by a very respected user of this forum.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 14:15

Actually, upon closer examination i have found that this code doesnt work - i made the following change to mem_clear():

Code:
function mem_clear()
{   str_cpy((save_text.pstring)[0],"   ");
    str_cpy((save_text.pstring)[1],"   ");
    str_cpy((save_text.pstring)[2],"   ");
    first_struct->value1 = 0;
    first_struct->value2 = 0;
    str_remove(first_struct->str1);
    str_remove(first_struct->str2);
    str_remove(first_struct->str3);
    free(first_struct);
    str_cpy((status_text.pstring)[0],"Status: Memory Cleared.");
}



I wanted to make sure to clear out *everything* in memory to make sure that strings were being re-loaded from the save file. The reason it looked like it worked before is because the strings were still in memory. Once i clear the save_text.pstrings the strings are still blank after a reload.

dammit - this is really starting to frustrate me.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 14:18

I'm specifically making sure that im saving strings - and making sure that the strings are global. I just dont get why this doesnt work

EDIT: ok i decided to RTFM and i think i found the problem - SV_STRINGS mode in game_save saves all *modified* strings only. Not sure how a string created with str_create *doesn't* count as a modified string, but there you go. I think I have to use SV_ALL.

EDIT2: ok SV_ALL doesnt work either......for crying out loud why is this so difficult?
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 14:49

So i decided to simplify and make sure game_save is working:

Code:
//////////////////////////////////////////////////////////////////////
// test.c

#include <acknex.h>
#include <default.c>
#include "headers.h"

FONT* standard_font = "ackfont.pcx";

PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

TEXT* status_text = 
{   pos_x = 20;
    pos_y = 70;
    flags = SHOW;
    font = standard_font;
    strings = 1;
    string("Status: N/A");
}

TEXT* save_text = 
{   pos_x = 20;
    pos_y = 40;
    flags = SHOW;
    font = standard_font;
    strings = 3;
    string("This is the first string","This is the second string","This is the third string");
}

function save_game()
{   game_save("test",1,SV_ALL);
    str_cpy((status_text.pstring)[0],"Status: Game Saved.");
}

function mem_clear()
{   str_cpy((save_text.pstring)[0],"   ");
    str_cpy((save_text.pstring)[1],"   ");
    str_cpy((save_text.pstring)[2],"   ");
    str_cpy((status_text.pstring)[0],"Status: Memory Cleared.");
}

function load_game()
{   game_load("test",1);
    str_cpy((status_text.pstring)[0],"Status: Game Loaded.");
}

function main()
{   on_f1 = save_game;
    on_f2 = mem_clear;
    on_f3 = load_game;
    while(key_esc==0)
    {   wait(1);
    }
}



To my surprise, this code doesnt work either. After game_load, the pstrings in save_text were still blank. As far as I can tell, game_save is just outright not working. Is it maybe bugged i wonder? Im currently using Gamestudio Pro 7.82 - i know its not the latest and greatest, but upgrading to A8 just causes me all kinds of other problems.

Is this maybe a bug in 7.82?
Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 15:39

No, it's not a bug. It's a feature. ;-)

Originally Posted By: The Almighty Manual
For not unnecessarily inflating the save file, SV_STRINGS only saves modified strings. If you modify a string after game_save, it was not saved, and is consequently not overwritten to its initial content on game_load. So modify all strings that should be saved and loaded before game_save; for instance set them to their initial content.


If you insert
Code:
str_cat((save_text.pstring)[0]," ");
str_cat((save_text.pstring)[1]," ");
str_cat((save_text.pstring)[2]," ");

this into your save function it will work as you would have expected.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 17:43

OK....so the following code really works (I really mean it this time LOL - I tested it three times and it is loading the strings from the save file):

Code:
///////////////////////////////////////////////////////////////////
// headers.h - headers file for test

typedef struct test_struct
{   var value1;
    var value2;
    STRING* str1;
    STRING* str2;
    STRING* str3;
    struct test_struct* next;
} test_struct;

typedef struct save_struct
{   var value1;
    var value2;
    var str1;
    var str2;
    var str3;
    struct save_struct* next;
} save_struct;

test_struct* first_struct;
test_struct* curr_struct;

save_struct* first_save;
save_struct* curr_save;

var test;
var test2;

//////////////////////////////////////////////////////////////////////
// test.c

#include <acknex.h>
#include <default.c>
#include "headers.h"

FONT* standard_font = "ackfont.pcx";

PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

TEXT* info_text = 
{   pos_x = 20;
    pos_y = 40;
    flags = SHOW;
    font = standard_font;
    strings = 3;
    string("             ","             ","             ");
}

TEXT* status_text = 
{   pos_x = 20;
    pos_y = 70;
    flags = SHOW;
    font = standard_font;
    strings = 1;
    string("Status: N/A");
}

function save_game()
{   str_cat(first_struct->str1," ");
    str_cat(first_struct->str2," ");
    str_cat(first_struct->str3," ");
    first_save->value1 = first_struct->value1;
    first_save->value2 = first_struct->value2;
    first_save->str1 = handle(first_struct->str1);
    first_save->str2 = handle(first_struct->str2);
    first_save->str3 = handle(first_struct->str3);
    add_struct(first_save,sizeof(save_struct));
    game_save("test",1,SV_ALL);
    str_cpy((status_text.pstring)[0],"Status: Game Saved.");
}

function mem_clear()
{   first_struct->value1 = 0;
    first_struct->value2 = 0;
    str_cpy(first_struct->str1," ");
    str_cpy(first_struct->str2," ");
    str_cpy(first_struct->str3," ");
    first_save->value1 = 0;
    first_save->value2 = 0;
    first_save->str1 = 0;
    first_save->str2 = 0;
    first_save->str3 = 0;
    str_cpy((status_text.pstring)[0],"Status: Memory Cleared.");
}

function load_game()
{   game_load("test",1);
    first_struct->value1 = first_save->value1;
    first_struct->value2 = first_save->value2;
    first_struct->str1 = ptr_for_handle(first_save->str1);
    first_struct->str2 = ptr_for_handle(first_save->str2);
    first_struct->str3 = ptr_for_handle(first_save->str3);
    str_cpy((status_text.pstring)[0],"Status: Game Loaded.");
}

function main()
{   on_f1 = save_game;
    on_f2 = mem_clear;
    on_f3 = load_game;
    first_struct = (test_struct*)malloc(sizeof(test_struct));
    first_struct->value1 = 5;
    first_struct->value2 = 10;
    first_struct->str1 = str_create("This is the first str");
    first_struct->str2 = str_create("This is the second str");
    first_struct->str3 = str_create("This is the third str");
    first_struct->next = NULL;
    first_save = (save_struct*)malloc(sizeof(save_struct));
    first_save->value1 = 0;
    first_save->value2 = 0;
    first_save->str1 = 0;
    first_save->str2 = 0;
    first_save->str3 = 0;
    first_save->next = NULL;
    while(key_esc==0)
    {   test = first_struct->value1;
        test2 = first_struct->value2;
        (info_text.pstring)[0] = first_struct->str1;
        (info_text.pstring)[1] = first_struct->str2;
        (info_text.pstring)[2] = first_struct->str3;
        wait(1);
    }
}



There were only two problems with the code as I had it before. One was that I was not modifying my strings so they weren't getting saved - just like Uhrwerk pointed out. (nice catch Uhrwerk - that one would have had me going for a year). Two was that I was doing a str_remove in the mem_clear function. Even once i *did* get the code to save strings, there was no string for it to be assigned back to if i do a str_remove.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 18:30

So I wasn't happy with the idea of not being able to remove those strings - (im anal retentive about memory management - if I dont need it i *will* have it released) i came up with the following, which works as well and doesnt leave a bunch of empty strings hanging around in memory:

Code:
///////////////////////////////////////////////////////////////////
// headers.h - headers file for test

typedef struct test_struct
{   var value1;
    var value2;
    STRING* str1;
    STRING* str2;
    STRING* str3;
    struct test_struct* next;
} test_struct;

typedef struct save_struct
{   var value1;
    var value2;
    STRING* str1;
    STRING* str2;
    STRING* str3;
    struct save_struct* next;
} save_struct;

test_struct* first_struct;
test_struct* curr_struct;

save_struct* first_save;
save_struct* curr_save;

var test;
var test2;

//////////////////////////////////////////////////////////////////////
// test.c

#include <acknex.h>
#include <default.c>
#include "headers.h"

FONT* standard_font = "ackfont.pcx";

PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

TEXT* info_text = 
{   pos_x = 20;
    pos_y = 40;
    flags = SHOW;
    font = standard_font;
    strings = 3;
    string("             ","             ","             ");
}

TEXT* status_text = 
{   pos_x = 20;
    pos_y = 70;
    flags = SHOW;
    font = standard_font;
    strings = 1;
    string("Status: N/A");
}

function save_game()
{   file_delete("test1.sav");
    first_save->value1 = first_struct->value1;
    first_save->value2 = first_struct->value2;
    first_save->str1 = str_create(first_struct->str1);
    first_save->str2 = str_create(first_struct->str2);
    first_save->str3 = str_create(first_struct->str3);
    str_cat(first_save->str1," ");
    str_cat(first_save->str2," ");
    str_cat(first_save->str3," ");
    game_save("test",1,SV_ALL);
    str_cpy((status_text.pstring)[0],"Status: Game Saved.");
}

function mem_clear()
{   first_struct->value1 = 0;
    first_struct->value2 = 0;
    str_remove(first_struct->str1);   // <--- notice all strings and even
    str_remove(first_struct->str2);   // first_struct itself are being re-
    str_remove(first_struct->str3);   // leased from memory.
    free(first_struct);
    first_save->value1 = 0;
    first_save->value2 = 0;
    first_save->str1 = NULL;
    first_save->str2 = NULL;
    first_save->str3 = NULL;
    str_cpy((status_text.pstring)[0],"Status: Memory Cleared.");
}

function load_game()
{   game_load("test",1);
    first_struct = (test_struct*)malloc(sizeof(test_struct));
    first_struct->value1 = first_save->value1;
    first_struct->value2 = first_save->value2;
    first_struct->str1 = first_save->str1;
    first_struct->str2 = first_save->str2;
    first_struct->str3 = first_save->str3;
    str_cpy((status_text.pstring)[0],"Status: Game Loaded.");
}

function main()
{   on_f1 = save_game;
    on_f2 = mem_clear;
    on_f3 = load_game;
    first_struct = (test_struct*)malloc(sizeof(test_struct));
    first_struct->value1 = 5;
    first_struct->value2 = 10;
    first_struct->str1 = str_create("This is the first str");
    first_struct->str2 = str_create("This is the second str");
    first_struct->str3 = str_create("This is the third str");
    first_struct->next = NULL;
    first_save = (save_struct*)malloc(sizeof(save_struct));
    first_save->value1 = 0;
    first_save->value2 = 0;
    first_save->str1 = 0;
    first_save->str2 = 0;
    first_save->str3 = 0;
    first_save->next = NULL;
    add_struct(first_save,sizeof(save_struct));
    while(key_esc==0)
    {   test = first_struct->value1;
        test2 = first_struct->value2;
        (info_text.pstring)[0] = first_struct->str1;
        (info_text.pstring)[1] = first_struct->str2;
        (info_text.pstring)[2] = first_struct->str3;
        wait(1);
    }
}


Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 21:38

I don't understand how you jump to the conclusion that there are non-used strings in memory when you use game_save..?
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 22:32

no - its not game_save thats making non-used strings - its my own code. Look at first_struct - in the previous version i was not releasing the strings, merely copying " " to them. I am releasing first struct in mem_clear, then re-allocating it at game_load, so those strings arent used anymore. They should be released. For some reason though, if you did str_remove instead of str_cpy in the previous one, when i did a load game the strings in first_struct would still be blank, even when i did a str-create first to make sure there was a string to be assigned to.
Posted By: Uhrwerk

Re: Saving the *contents* of a structure with game_save()... - 03/22/11 23:05

Ah, now I got it. This a bit strange concept. Under normal circumstances you'd allocate memory for the string when the memory for the struct is allocated as well and you'd release it when the struct memory is released.

The more different parts in your code allocate and release memory on different occasions, the more error prone the code will be concerning memory leaks and or relese of already released memory blocks.
Posted By: Caermundh

Re: Saving the *contents* of a structure with game_save()... - 03/23/11 00:25

well, for first_struct i am doing exactly that - allocating the struct and the strings at the same time and then releasing them at the same time, at least in the second version. Not releasing the strings when i released the struct was what i disliked about the first version. First_save is different though, its supposed to be a permanently allocated area of memory (permanent for the duration of the run-time anyways.) The reason for that is because if I allocate first_save, call add_struct(first_save,sizeof(save_struct)), and then later release first_save ... well i believe that would cause an engine crash when game_save tries to save an invalid area of memory right?
© 2024 lite-C Forums