Can't save pointers - so what techniques?

BlitzMax Forums/BlitzMax Programming/Can't save pointers - so what techniques?

Grey Alien(Posted 2007) [#1]
Hiya, I'm writing some code to save my game mid-level. Ideally BMax would have the ability to write out the fields of all types to a file (think Mark is working on that right?).

Anyway, it occured to me that if you have a type field, or even a global variable, which is a pointer to some object that when you load that data in at a later point, it's basically useless because the pointer was originally pointing to some memory that meant something, and now crap knows what it's pointing to!

So I guess you have to write special post-load code which has a way to locate the type in question and assign the pointer again. This could be achieved with some kind of ID number system in the types in question and storing that as well as the type pointer. (not instead of because, it would be slow in-game to keep looking up an ID instead of using a pointer).

Any other approaches?


Canardian(Posted 2007) [#2]
I think you can use the VarPtr operator to get the memory address of a Type structure. You must know the length of the Type structure, but you can calculate that from the sizes of it's fields. After that you just use the OS's memory handling functions (in Windows: GlobalAlloc(), GlobalLock(), RtlMoveMemory()), and write an DLL in C using fwrite() and fread() to read/write the memory blocks to disk (when reading in, you need to use the "New Type" statement of BM to allocate the memory correctly).

Actually, since this is BlitzMax, are you sure the built-in Stream I/O functions like WriteFloat, WriteByte, ReadFloat, ReadByte, etc.. are not fast enough when you split a Type structure into it's fields? Then you wouldn't need any 3rd party extensions.


Curtastic(Posted 2007) [#3]

So I guess you have to write special post-load code which has a way to locate the type in question and assign the pointer again. This could be achieved with some kind of ID number system in the types in question and storing that as well as the type pointer. (not instead of because, it would be slow in-game to keep looking up an ID instead of using a pointer).

Thats exactly what I did. I had to introduce ID numbers for every object just for saving and loading. After loading everything I would relink the pointers and never use the ID again.


Grey Alien(Posted 2007) [#4]
Lumooja: Yeah I'm using the TSteam to write out all the fields. It's not a question of if it's fast enough, it's just slow to code due to all the fields that need to be listed in special functions which read and write them. Anyway the real issue was if you had a field which points to ANOTHER type, that link will be broken once you load the type in from disk as the memory for the other type won't be in the same place anymore.

Curtastic: Yeah thought so. Luckily I don't have too many of them, it was more a discussion point for the future because I was interested to see what other people are doing.


Jake L.(Posted 2007) [#5]
My objects all have two functions XLoad (load from XML-node) and XSave (store data in XML-node). So saving a level from within a leveleditor or midgame is handled the same. I use a speaking name (string) as ID, so I don't need to mess with pointers or numbers and I can easily load/save/identify every object by it's name.

This might be too slow for huge games and giant levels, but for a few hundred objects this approach is fast enough.


Grey Alien(Posted 2007) [#6]
Hi Jake. The XML functions sound good. I guess you have to "manually" populate them with the fields you want to read and write, which I'm doing, and thus it's prone to typos - that's why it's worth double checking the output of any writes.

Yeah I used the name system for certain objects where there's not too many like game sounds or images, then I can easily find them by name if they are stored in a list. For non-nameable things, I use ID. Actually most of the time I use pointers, it's just that when I save I have to convert the pointer to and ID and then back to a pointer when I load.