- v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
- Use this page to report any issues related to the migration.
Difference between revisions of "User talk:Jifodus/Dwarf Fortress Utility Framework"
Line 126: | Line 126: | ||
} | } | ||
</pre> | </pre> | ||
− | [[User:Sphr|Sphr]] | + | |
+ | ===additonal notes:=== | ||
+ | This is some stuff taken from what I did which can hopefully be of use as ideas even your method is different. | ||
+ | A memory map just describes a structure. A run-time mapped memory object simply consists of a ordered pair of a real address acting as a base, as well as a map. | ||
+ | |||
+ | e.g. the df_process "memory object" is simply (0x0000, getmap("v0_27_169_33c")) or something. Note that in the FULL case, it probably need the process handle as well as it is addressing a shared memory, i.e. { baseaddress=???, process_handle=???, map=??? } | ||
+ | |||
+ | Not sure about your implementation, but from what I have tried out, I find that if there are means to automatically keep track of memory objects (their base address as well as their map) returned to queries of named offsets, it would work better. Example follows: | ||
+ | |||
+ | say I create a df_process object | ||
+ | <pre> | ||
+ | df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c")) | ||
+ | </pre> , where hProcess is the processhandle the program has to get, and getmap is just returns the process memory map structure for some binary version. | ||
+ | |||
+ | If say I call a function to retrieve the named offset "main_creature_vector", e,g, | ||
+ | <pre> | ||
+ | my_creature_vector = GetSubObject(df_obj, "main_creature_vector") | ||
+ | </pre> | ||
+ | |||
+ | I should get back something equivalent to | ||
+ | <pre> | ||
+ | my_creature_vector == (0x0141FA30, hProcess, getmap("creature_vector_33b")) | ||
+ | </pre> | ||
+ | |||
+ | where the base-address, process handle and the resultant map is all automatically resolved, so that end user don't have to deal with addresses and stuff. | ||
+ | |||
+ | // mock up program (with no additional object wrappers, have to know memory maps) | ||
+ | <pre> | ||
+ | df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c")); | ||
+ | ASSERT(df_obj) | ||
+ | my_creature_vector = df_obj.GetSubObject("main_creature_vector"); | ||
+ | ASSERT(my_creature_vector) | ||
+ | num_creatures = my_creature_vector.GetLength(); | ||
+ | for( i=0; i < num_creatures; ++ i ) { | ||
+ | acreature = my_creature_vector.GetIndexedObject(i); | ||
+ | first_name = acreature.GetSubObject("first_name"); | ||
+ | // print out first name | ||
+ | // etc | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | // mock up program (with object wrapping so that don't have to deal with memory maps after binding) | ||
+ | // i.e. don;t have to use the GetSubObject("...") method, which can be error-prone if user gets the string wrong. | ||
+ | <pre> | ||
+ | df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c")); | ||
+ | ASSERT(df_obj) | ||
+ | |||
+ | DFWrappedProcess df_wrapped_ob(df_obj); //creates wrapped object | ||
+ | ASSERT(df_wrapped_obj.IsValid()) | ||
+ | |||
+ | int num_creatures = df_wrapped_obj.GetCreatures().GetLength(); | ||
+ | |||
+ | for( i=0; i < num_creatures; ++ i ) { | ||
+ | DFWrappedCreature acreature = df_wrapped_obj.GetCreatures().GetIndexedObject(i); | ||
+ | first_name = acreature.GetFirstName() | ||
+ | // print out first name | ||
+ | // etc | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | Of coz, the above is a little troublesome due to C's strong typing. Perhaps you can come up with an even easier-to-use version for lua. | ||
+ | |||
+ | |||
+ | [[User:Sphr|Sphr]] 03:00, 13 December 2007 (EST) |
Revision as of 08:00, 13 December 2007
Sphr's comments
Update: added some comments on binary version data at the end A suggestion to consider: Unify map type defninition so that it can be used in inline definitions as well as global references.
In general a map has:
@name (optional) Does not need name if inlined @size (optional) not needed for predefined types of known size. Optional for most cases except when used as valuetype in array/vector @type (optional) name of predefined/user-defined map @(type-specific parameters) (e.g. vector/array/pointer may have a "valuetype", array may also need a "length". complex will have a "mapping" of named offsets)
An element in a "complex" 's "mapping" has
@name (required) name of mapping @offset (required) address offset from base of map @type (optional) name of predefined/user-defined map OR inlined defined type @(type-specific parameters) (e.g. vector/array/pointer may have a "valuetype", array may also need a "length". complex will have a "mapping" of named offsets)
Basically
- Every map definition can be used inline in another definitionwhere a "type" is expected.
- Every named map definition can be referenced wherever a "type" is expected.
The following shows some examples (may contain human errors) Pardon the bastardized lua syntax... I added the map{ ... } to mark out the part that defines a map, and I used [..] to denote a list.
E.g.
string_map = map{ name="string", size=28, type="complex", mapping=[ // mapping is used only by "complex" type {name="buffer", offset=0x04, type="array", valuetype="byte", length="16"}, // have to define length for array if arrays are used as valuetypes for other arrays/vectors {name="pointer", offset=0x04, type="pointer", valuetype=map{type="array", valuetype="byte"} }, // inline definintion of byte array as valuetype {name="length", offset=0x14, type="dword"}, {name="capacity", offset=0x18, type="dword"} ] } creature_33b_map = map{ name = "creature_33b", type="complex", mapping=[ { name="first_name" , offset=0x00, type="string" }, // refers to string type, no inlined definintions { name="nick_name" , offset=0x04, type="string" } .... ] } creature_33b_ptr_map = map{ name = "creature_33b_ptr", // maybe no need to define size. size of predefined types can be assumed to be well-known type="pointer", valuetype="creature_33b" } creature_vector_33b_map = map{ name = "creature_vector_33b", type="vector", valuetype="creature_33b_ptr" } df_33b_map = map{ name="df_v0_27_169_33b", size = ???, type = "complex", mapping= // start of list of mappings for complex type [ { name="main_creature_vector", offset=0x0141FA30, type = "creature_vector_33b" }, // the following is similar to "main_creature_vector" defined almost totally inlined (except string) in an alternative way { name="creature_vector_2", offset=0x01417A48, type = "vector" valuetype = map{ type = "pointer", valuetype= map{ type="complex", mapping=[ { name="first_name" , offset=0x00, type="string" }, { name="nick_name" , offset=0x04, type="string" } .... ] } } }, ... ] // end of list of mappings }
Notice that mapping defined for the whole process is no different from that defined for a structure. The process structure is just a global structure bound to address 0x0000 of the DF process at run-time.
As for version, I suggest a separate section or even separate file.
versions={ { version="v0_27_169_33b", timstamp="????", // include a variety of data to support different binary identification methods. crc32="????", map="df_v0_27_169_33b" //name of base process's memory map, as defined earlier }, { version="v0_27_169_33c", timstamp="????", // include a variety of data to support different binary identification methods. crc32="????", map= {... } //can even define to whole monstrous structure inline! }, ... }
additonal notes:
This is some stuff taken from what I did which can hopefully be of use as ideas even your method is different. A memory map just describes a structure. A run-time mapped memory object simply consists of a ordered pair of a real address acting as a base, as well as a map.
e.g. the df_process "memory object" is simply (0x0000, getmap("v0_27_169_33c")) or something. Note that in the FULL case, it probably need the process handle as well as it is addressing a shared memory, i.e. { baseaddress=???, process_handle=???, map=??? }
Not sure about your implementation, but from what I have tried out, I find that if there are means to automatically keep track of memory objects (their base address as well as their map) returned to queries of named offsets, it would work better. Example follows:
say I create a df_process object
df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c"))
, where hProcess is the processhandle the program has to get, and getmap is just returns the process memory map structure for some binary version.
If say I call a function to retrieve the named offset "main_creature_vector", e,g,
my_creature_vector = GetSubObject(df_obj, "main_creature_vector")
I should get back something equivalent to
my_creature_vector == (0x0141FA30, hProcess, getmap("creature_vector_33b"))
where the base-address, process handle and the resultant map is all automatically resolved, so that end user don't have to deal with addresses and stuff.
// mock up program (with no additional object wrappers, have to know memory maps)
df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c")); ASSERT(df_obj) my_creature_vector = df_obj.GetSubObject("main_creature_vector"); ASSERT(my_creature_vector) num_creatures = my_creature_vector.GetLength(); for( i=0; i < num_creatures; ++ i ) { acreature = my_creature_vector.GetIndexedObject(i); first_name = acreature.GetSubObject("first_name"); // print out first name // etc }
// mock up program (with object wrapping so that don't have to deal with memory maps after binding)
// i.e. don;t have to use the GetSubObject("...") method, which can be error-prone if user gets the string wrong.
df_obj = CreateMemObject(0x0000, hProcess, getmap("v0_27_169_33c")); ASSERT(df_obj) DFWrappedProcess df_wrapped_ob(df_obj); //creates wrapped object ASSERT(df_wrapped_obj.IsValid()) int num_creatures = df_wrapped_obj.GetCreatures().GetLength(); for( i=0; i < num_creatures; ++ i ) { DFWrappedCreature acreature = df_wrapped_obj.GetCreatures().GetIndexedObject(i); first_name = acreature.GetFirstName() // print out first name // etc }
Of coz, the above is a little troublesome due to C's strong typing. Perhaps you can come up with an even easier-to-use version for lua.
Sphr 03:00, 13 December 2007 (EST)