GSF dissection
Posted: Tue Mar 06, 2018 16:39 pm
AyCe said to write this post
https://github.com/BlasSoriano/Paraworld
https://zenhax.com/viewtopic.php?f=9&t=6998
In one block there cant be more than 1000 triangles
//enum {MAX_FACES=1000};
//enum {MAX_FACES_NORMAL_MAPPING=5000};
Face Splitting:
// face index iFIdx
// face mat id iFMatID = pMesh->faces[iFIdx].getMatID()%p_raiMatMap.GetSize();
// iFaceChunkID=aiChunkFSort[aiFaceMatIDsSplit[iFIdx]].m_iChunkIdxReMap
VertexDataSize 8byte structure:
x, y, z, nx, ny, nz, u, v
VertexDataSize 9byte structure:
x, y, z, nx, ny, nz, u, v, unk byte
VertexDataSize 16byte structure:
x, y, z, nx, ny, nz, u, v, BoneIndex1(1byte), BoneIndex2(1byte), BoneIndex3(1byte), BoneIndex4(1byte), BoneWeights(one byte per bone)
icewaste_animals.gsf 21.06.2009
Each vertex stores 8 bytes (64 bits) in the table of vertices, but just the first 39 bits (0-12 for x, 13 to-25 for y, 26-38 for z) are used for the vertex coordinates
bits 0-12: x
bits 13-25: y
bits 26-38: z
bits 39-47: normals (nx ny nz)
bits 48-55: u
bits 56-63: v
Last update: 01.06.2018
To be continued...
Parts that are not included in the icewaste_animals.gsf
0x0211CB95 LINKS
0B 00 00 80 ChunkType
1F 00 00 00 Attributes
B8 7C B7 FE Link guid
76 74 37 BF -0.7166208 PosX
1C C3 1C 3F 0.61235213 PosY
7C 7C 01 40 2.023223 PosZ
B7 2A 17 3F 0.5904955 Quaternion
16 DC D8 BD -0.10588853 Quaternion
FF 1C 20 BE -0.15636061 Quaternion
EB DD 48 3F 0.7846362 Quaternion
48 6E 64 52 "HndR" Link name
00 00 00 00
26 FF FF FF Bone id
FF 00 00 00
0x0211CE6D LINKSv2
0B 00 00 00 ChunkType
1F 00 00 00 Attributes
BC 6A 99 D6 Link guid
0D D0 24 34 PosX
E0 BC 60 40 PosY
9C 1A D3 BA PosZ
00 00 00 00 Quaternion
00 00 00 00 Quaternion
00 00 80 3F Quaternion
69 21 A2 B3 Quaternion
46 6D 30 31 "Fm01"
E0231 PF_BLOCKER
01 00 00 00 Blocker type 00=sphere(hit collision) 01=planes(path blocker)
5A D5 80 C0 PosX
5A D5 80 C0 PosY
C0 C4 0A BE PosZ
5A D5 00 41 ScaleX
5A D5 00 41 ScaleY
BD 9B 03 41 ScaleZ
1F 00 00 00 (guid maybe)
PF_BLOCKERv2 (Collision sphere)
01 00 00 00 Blocker type 00=sphere(hit collision) 01=planes(path blocker)
89 A9 41 3E PosX
C3 84 DA C0 PosY
74 9A 36 40 PosZ
F9 BB C0 40 Scale
80 1A 11 42 Unk
00 00 00 00 Always 00 00 00 00 (padding)
1F 00 00 00 (guid maybe)
https://github.com/BlasSoriano/Paraworld
https://zenhax.com/viewtopic.php?f=9&t=6998
In one block there cant be more than 1000 triangles
//enum {MAX_FACES=1000};
//enum {MAX_FACES_NORMAL_MAPPING=5000};
Face Splitting:
// face index iFIdx
// face mat id iFMatID = pMesh->faces[iFIdx].getMatID()%p_raiMatMap.GetSize();
// iFaceChunkID=aiChunkFSort[aiFaceMatIDsSplit[iFIdx]].m_iChunkIdxReMap
VertexDataSize 8byte structure:
x, y, z, nx, ny, nz, u, v
VertexDataSize 9byte structure:
x, y, z, nx, ny, nz, u, v, unk byte
VertexDataSize 16byte structure:
x, y, z, nx, ny, nz, u, v, BoneIndex1(1byte), BoneIndex2(1byte), BoneIndex3(1byte), BoneIndex4(1byte), BoneWeights(one byte per bone)
icewaste_animals.gsf 21.06.2009
Code: Select all
0x00000000 GSF_PACK_HEADER
47 53 46 00 "GSF 00"
00 00 00 00 FormatVersion = 0
00 00 01 00 ContentsTableOffset = 0x00010000
0x0000000C TREE_NODES
From 0x0000000C to unknown (it needs to be parsed) #Models,anims,sounds,classes(not included in that .gsf),walktransition lists
0x000003F9 SOUNDS
After models and anims list to unknown
27 00 00 00 All sounds count
25 00 00 00 MaxCharsCount in sound name.
30 30 5F 6E 70 63 2F 6E 70 63 5F 64 69 6E 6F 5F 68 75 67 65 31 5F 77 61 74 65 72 5F 61 74 74 31 2E 77 61 76 00 00_npc/npc_dino_huge1_water_att1.wav
01 00 00 00 The frame on which the sound starts
63 00 00 00 Volume
66 66 66 3F Sound speed
00 00 00 00
00 00 00 41
00 00 96 42 42=const
00 00 98 42 42=const
01 00 00 00
00 Splitter (Used to split blocks if the sound is used more than once in the animation)
and 36 more empty entries, 74 bytes each(except 04_step/step_dino_swim5.wav because there the sound should play 3 times per animation) upto 0x00000E1A
0x00000E1B WALK_TRANSITIONS_TABLE
00 00 00 00
00 00 00 00
02 00 00 00 walktransitions count
09 00 00 00 CharsCount
41 6E 69 6D 61 6C 73 31 00 Animals1
09 00 00 00 CharsCount
41 6E 69 6D 61 6C 73 33 00 Animals3
0x00000E41 PADDING
From unknown to 0x0000FFFF #Except when the TREE_NODES is larger 0x00010000 (all_characters.gsf,all_animals.gsf ...)
0x00010000 CONTENTS_TABLE
00 00 00 00 0=const
05 00 00 00 ObjectsCount = 5 #AllModelsCount
0B 00 00 00 SubObjectsCount = 11 #AllAnimsCount
00 00 00 00 0=const
1C 00 00 00 Offset to OBJECTS_TABLE = 0x1002C
05 00 00 00 ObjectsCount = 5 #Models classes count
B8 01 00 00 Offset to ANIMATIONS_CLASSES_TABLE = 0x101D0
0B 00 00 00 SubObjectsCount = 11 #Anim classes count
0x00010020 MATERIALS_HEADER
06 00 00 00 MaterialsCount = 6
4C A0 00 00 MaterialsTableOffset = 0x1A070
E8 03 00 00 TotalEntries = 1000
0x0001002C OBJECTS_TABLE
43 68 61 72 "Char"
38 FE 00 00 Offset to OBJECT_NAME = 0x1FE68
2C FE 00 00 Offset to USED_CHUNKS_TABLE = 0x1FE60 #offset to all chunks offsets
02 00 00 00 USED_CHUNKS_TABLE offsets count = 2
1C A0 00 00 Offset to CONTENTS_TABLE and OBJECTS_TABLE offsets list = 0x1A058
01 00 00 00 00=skip data. 01=read data
00 00 00 00 2 shorts #Unk. Short and Additional effects count
FF FF 00 00 2 shorts #Links offset (where the links table should start or something like that) and links count
00 01 00 00 4 bytes
FF 00 00 00 4 bytes
00 00 00 80 Offset
00 00 00 80 Offset to pathfinder blocker table
00 00 00 00 4 bytes. 1=PF planes to render (green). 2=01=render all volumes 02=render all volumes + nm sphere? 3=PF unknown. 4=unknown
48 AF 10 BF BoundingBoxMinX = -0.565175
FB 41 7E BF BoundingBoxMinY = -0.993194
64 B8 37 BE BoundingBoxMinZ = -0.179414
4A AF 90 3F BoundingBoxMaxX = 1.13035
DA B5 FD 3F BoundingBoxMaxY = 1.98211
57 E6 E1 3E BoundingBoxMaxZ = 0.44121
10 FE 00 00 Offset to ANIM_ATTRIBUTES_TABLE = 0x1FE88
03 00 00 00 Animations count
From 0x0001002C to 0x0001007F (0x54 = 84 bytes) Char (bothriolepis)
From 0x00010080 to 0x000100D3 (0x54 = 84 bytes) Char (dunkleosteus)
From 0x000100D4 to 0x00010127 (0x54 = 84 bytes) Anim (henodus)
From 0x00010128 to 0x0001017B (0x54 = 84 bytes) Anim (quetzalcoatlus)
From 0x0001017C to 0x000101CF (0x54 = 84 bytes) Char (quetzalcoatlus_boden)
0x000101D0 ANIMATIONS_CLASSES_TABLE
43 68 61 72 "Char"
30 01 00 00 Offset to ANIMATION_HEADER = 0x10304
74 04 00 00 Offset to table with ANIM_START_OFFSET and STAND_POS_ANIM_DATA
01 00 00 00 SomeCount = 1
00 00 00 80 Offset to ANIM_USED_CHUNKS_TABLE(null)
01 00 00 00 SomeCount = 1
0A 00 00 00 Anim frames count = 10
From 0x000101D0 to 0x000101EB (0x1C = 28 bytes) Char
From 0x000101EC to 0x00010207 (0x1C = 28 bytes) 00 00 00 00 (Yes, this is the class name) (NOT CHECKED)
From 0x00010208 to 0x00010223 (0x1C = 28 bytes) Char
From 0x00010224 to 0x0001023F (0x1C = 28 bytes) Char
From 0x00010240 to 0x0001025B (0x1C = 28 bytes) Char
From 0x0001025C to 0x00010277 (0x1C = 28 bytes) Char
From 0x00010278 to 0x00010293 (0x1C = 28 bytes) Anim
From 0x00010294 to 0x000102AF (0x1C = 28 bytes) 00 00 00 00 (And this is too) (NOT CHECKED)
From 0x000102B0 to 0x000102CB (0x1C = 28 bytes) Anim
From 0x000102CC to 0x000102E7 (0x1C = 28 bytes) Char
From 0x000102E8 to 0x00010303 (0x1C = 28 bytes) Anim
0x00010304 ANIMATION_HEADER (Anim can support scaling, or may not)
01 00 00 00 StringsCount = 1
14 00 00 00 MaxCharsCount in anim name. If the name is more or equal 14 characters, then 24 00 00 00 (14=20)
08 00 00 00 CharsCount = 8
48 65 6C 70 65 72 30 31 "Helper01"
00 00 00 00 00 00 00 00 00 00 00 00 #Padding (MaxCharsCount)
05 00 00 40 ChunkType = 0x40000005
00 00 00 00 Attributes
5B F9 F4 16 Guid = 0x16F4F95B
00 00 00 80 ChunkType2
FF FF FF FF #short2 - short1 = How many frames from the first should be played to loop walk anim (eg if 0A 00 32 00 then 32 - A = 28 = 40 frames)
00 00 80 BF
00 00 01 00
1C 00 00 00 DataChunkAddress = 0x00010340 + 0x001C = 0x0001035C
A8 01 00 00 NextHeaderAddress = 0x00010344 + 0x01A8 = 0x000104EC
01 00 00 00 NextHeadersCount = 1
0A 00 00 00 TransformationsCount = 10
00 00 00 00 float. For walk anim. Distance between first and second path points
00 00 00 00 float. For walk anim.
00 00 00 00 float. For walk anim. Distance between penultimate and last path points
0x0001035C ANIMATION_DATA (Helper01)
From 0x0001035C to 0x000104EB
40 bytes * 10 transformations = 400 bytes = 0x0190 up to 0x000104EB #model position in the world
From 0x000104EC to 0x0001064F transformations
0x000104EC Header
01 02 01 00
0C 00 00 00 DataChunkAddress = 0x000104F0 + 0x000C = 0x000104FC
A8 00 00 00 NextHeaderAddress = 0x000104F4 + 0x00A8 = 0x0001059C
01 00 00 00 NextHeadersCount = 1
From 0x000104FC to 0x0001059B #mesh1 transformations
02 02 00 00
0C 00 00 00
00 00 00 80
00 00 00 00
00 00 00 00
00 00 00 00
00 00 C0 A0
00 00 80 3F
From 0x000105BC to 0x00010647 #mesh2 transformations
00 00 80 3F
D8 FC FF FF 0x0001064C - 808d = 0x00010324 Offset to animation start
next ANIMATION+ANIMATION_DATA (Helper01)
From 0x00010650 to 0x00011F73
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x00011F74 to 0x000130A7
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x00011F74 to 0x00013C8B
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x00013C8C to 0x000145C7
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x000145C8 to 0x0001470B
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x0001470C to 0x000147E7
next ANIMATION+ANIMATION_DATA (Helper01)
From 0x000147E8 to 0x00015B1B
next ANIMATION+ANIMATION_DATA (Dunkleosteus_helper)
From 0x00015B1C to 0x0001719F
next ANIMATION+ANIMATION_DATA (Helper01)
From 0x000171A0 to 0x000190D3
next ANIMATION+ANIMATION_DATA (Henodus_Helper)
From 0x000190D4 to 0x000195A7
Bothriolepis model start
0x000195A8 BONES_TABLE
05 00 00 00 ChunkType
1F 00 00 00 Attributes
5B F9 F4 16 Guid Crc32b 16F4F95B = "root"
00 00 00 00
5B F9 F4 16 Guid
00 00 00 00 Flags
8C 74 96 B2 AnimPosX
14 DE 7E 3F AnimPosY
A4 A5 61 3C AnimPosZ
00 00 80 3F ScaleX
00 00 80 3F ScaleY
00 00 80 3F ScaleZ
9F EA FC BE Quaternion
FF 85 01 3F Quaternion
9D EA FC 3E Quaternion
FF 85 01 3F Quaternion
01 00 00 00 Childs count
18 00 00 00 Offset to next bone
01 00 00 00 Parent bone сhilds count?
88 00 00 00 Offset to list
03 00 00 00 Bones count?
03 00 00 00 Bones count?
00 00 00 00 Parent bone id?
E3 38 C9 F9 Guid
00 00 00 00 Flags
8F 22 0A 3F AnimPosX
4D 77 E8 35 AnimPosY
53 12 8F B1 AnimPosZ
00 00 80 3F ScaleX
00 00 80 3F ScaleY
00 00 80 3F ScaleZ
E2 23 40 A5 Quaternion
24 73 E5 30 Quaternion
34 70 1C 3D Quaternion
30 D0 7F 3F Quaternion
01 00 00 00 Childs count
08 00 00 00 Offset to next bone
01 00 00 00 Parent bone id?
48 B4 8B B9 Guid
00 00 00 00 Flags
25 4F 26 3F AnimPosX
20 B9 67 34 AnimPosY
0A 12 14 33 AnimPosZ
00 00 80 3F ScaleX
00 00 80 3F ScaleY
00 00 80 3F ScaleZ
3E 87 3B 26 Quaternion
DA C1 50 B0 Quaternion
8B 54 8E BC Quaternion
1C F6 7F 3F Quaternion
00 00 00 00 Childs count
00 00 00 80 Offset to next bone(null)
0x00019678 unk_TABLE
00 00 00 00
A2 8A 7D 33
F8 F2 68 B3
00 00 80 BF
00 00 00 00
34 ED 7F BF
5D 28 C4 3C
12 6B 95 B3
00 00 00 00
62 28 C4 3C 0.023945
34 ED 7F 3F 0.999713
A2 F6 7B B3 -5.86648e-08
00 00 00 80 -0
C0 B5 7E 3F 0.994961
60 0A 1A BD -0.0376076
CA C1 61 33 5.25631e-08
00 00 80 3F 1
59 20 80 33 5.96635e-08
DD 76 55 B3 -4.9701e-08
FE FF 7F BF -1
00 00 00 80 -0
D7 A5 7F BF -0.998624
12 C4 56 BD -0.0524331
A8 3F 8E B3 -6.62397e-08
00 00 00 00 0
0F C4 56 BD
D7 A5 7F 3F
4C C2 7B B3
00 00 00 80
87 F0 E9 3E
C7 A2 33 BB
43 18 6D 33
00 00 80 3F
48 34 7F 33
12 5A 5E B3
FE FF 7F BF
00 00 00 80
B6 F5 7F BF
E8 0B 91 BC
2C 82 91 B3
00 00 00 00
E2 0B 91 BC
B6 F5 7F 3F
E0 FC 7B B3
00 00 00 80
FF 55 45 BE
18 A6 81 3B
A4 88 AF 32
00 00 80 3F
0x0001973C MESH_TRANSFORMATIONS
00 00 00 80 ChunkType
1F 00 00 00 Attributes
B7 19 10 42 Guid
00 00 80 3F ScaleX
00 00 00 00 StretchY
00 00 00 00 StretchZ(x)
00 00 00 00 0
00 00 00 00 StretchX
00 00 80 3F ScaleY
00 00 00 00 StretchZ(y)
00 00 00 00 0
00 00 00 00 ShearX
00 00 00 00 ShearY
00 00 80 3F ScaleZ
00 00 00 00 0
00 00 00 00 PosX
00 00 00 00 PosY
00 00 00 00 PosZ
00 00 80 3F 1
0x00019788 !MESH_BOUNDING_BOX!
02 00 00 00 ChunkType
00 00 00 00 Attributes
08 00 00 00 Offset to BBox1
00 00 00 00 Guid
48 AF 10 BF GlobalBBMinX = -0.565
FB 41 7E BF GlobalBBMinY = -0.993
64 B8 37 BE GlobalBBMinZ = -0.179
4C AF 10 3F GlobalBBMaxX = 1.130
BA 29 7D 3F GlobalBBMaxY = 1.982
25 0A 86 3E GlobalBBMaxZ = 0.441
01 00 00 00 Mesh count and/or MeshLocalBBox count
10 00 00 00 Offset to BBox2
01 00 00 00 Mesh count and/or MeshLocalBBox count
9A 08 00 00 Offset to next MESH_TRANSFORMATIONS or to USED_CHUNKS_TABLE if this is the last mesh in the model
01 00 00 00 Mesh count and/or MeshLocalBBox count
48 AF 10 BF Mesh1LocalBBMinX = -0.565
FB 41 7E BF Mesh1LocalBBMinY = -0.993
64 B8 37 BE Mesh1LocalBBMinZ = -0.179
4C AF 10 3F Mesh1LocalBBMaxX = 1.130
BA 29 7D 3F Mesh1LocalBBMaxY = 1.982
25 0A 86 3E Mesh1LocalBBMaxZ = 0.441
5F 00 00 00 Vertices = 95
67 00 00 00 Triangles = 103
18 00 00 00 Offset to vertices = 0x197FC
04 06 00 00 Offset to faces = 0x19DEC
67 00 00 00 Triangles = 103
10 00 00 00 VertexDataSize = 16
00 00 00 80 SomeOffset = null
00 00 00 00 SomeCount = null
From 0x000197FC to 0x00019DEB Vertices data (0x5F0 = 1520 bytes / VertexDataSize(16) = 95 vertices)
From 0x00019DEC to 0x0001A055 Triangles data (0x26A = 618 bytes / 6 = 103 faces)
From 0x0001A056 to 0x0001A057 unk 2 bytes (maybe padding)
0x0001A058 CONTENTS_TABLE and OBJECTS_TABLE offsets list
A8 5F FF FF Offset to CONTENTS_TABLE
C4 5F FF FF Offset to OBJECTS_TABLE
0x0001A060 USED_MATERIALS_TABLE
0C 00 00 00 Type = 12
01 00 00 00 MaterialsCount = 1
01 00 00 00
00 00 00 00 AdditionalMaterialIndex1 = 0 (Additional effects)
00 00 00 00 AdditionalMaterialIndex2 = 0 (Textures with alpha channel)
0F 00 00 00 15
B8 5D 00 00 Offset to TEXTURE_NAME = 0x1FE30
00 00 00 80 Offset to NM_TEXTURE_NAME(null)
00 00 00 80 Offset to ENV_TEXTURE_NAME(null)
00 00 00 00 0
10 40 00 00 16400
42 00 00 00 66
B6 F8 00 00 Offset to TEXTURE_NAME
E2 F8 00 00 Offset to NM_TEXTURE_NAME
00 00 00 80 Offset to ENV_TEXTURE_NAME
00 00 00 00
01 00 00 00
00 00 00 00
FE F8 00 00 Offset to TEXTURE_NAME
00 00 00 80 Offset to NM_TEXTURE_NAME
00 00 00 80 Offset to ENV_TEXTURE_NAME
00 00 00 00
00 00 00 00
00 00 00 00
0x0001FE60 USED_CHUNKS_TABLE
48 97 FF FF Offset to BONES_TABLE or to animation if there is no skeleton
D8 98 FF FF Offset to MESH_TRANSFORMATIONS
0x0001FE68 OBJECT_NAME
01 00 00 00 StringsCount = 1
14 00 00 00 MaxCharsCount in model name. If the name is more or equal 14 characters, then 24 00 00 00
0C 00 00 00 CharsCount = 12
62 6F 74 68 72 69 6F 6C 65 70 69 73 "bothriolepis"
00 00 00 00 00 00 00 00 Padding
0x0001FE88 ANIM_ATTRIBUTES_TABLE
A4 01 FF FF Offset to OBJECTS_TABLE 0x0001FE88 - 65116d = 0x0001002C
20 00 00 00 Offset to anim1 in ANIM_ATTRIBUTES_TABLE2
01 00 00 00 00=skip data. 01=read data
98 01 FF FF 0x0001FE94 - 65128d = 0x0001002C
00 00 00 80 Offset to anim2 in ANIM_ATTRIBUTES_TABLE2(null)
00 00 00 00 00=skip data. 01=read data
8C 01 FF FF 0x0001FEA0 - 65140d = 0x0001002C
00 00 00 80 Offset to anim3 in ANIM_ATTRIBUTES_TABLE2(null)
00 00 00 00 00=skip data. 01=read data
0x0001FEAC ANIM_ATTRIBUTES_TABLE2
78 04 FF FF Offset to anim1 chunk start 0x0001FEAC - 64392d = 0x00010324 (Decimal from signed 2's complement)
0A 00 00 00 Anim1 frames count
bits 0-12: x
bits 13-25: y
bits 26-38: z
bits 39-47: normals (nx ny nz)
bits 48-55: u
bits 56-63: v
Last update: 01.06.2018
To be continued...
Parts that are not included in the icewaste_animals.gsf
0x0211CB95 LINKS
0B 00 00 80 ChunkType
1F 00 00 00 Attributes
B8 7C B7 FE Link guid
76 74 37 BF -0.7166208 PosX
1C C3 1C 3F 0.61235213 PosY
7C 7C 01 40 2.023223 PosZ
B7 2A 17 3F 0.5904955 Quaternion
16 DC D8 BD -0.10588853 Quaternion
FF 1C 20 BE -0.15636061 Quaternion
EB DD 48 3F 0.7846362 Quaternion
48 6E 64 52 "HndR" Link name
00 00 00 00
26 FF FF FF Bone id
FF 00 00 00
0x0211CE6D LINKSv2
0B 00 00 00 ChunkType
1F 00 00 00 Attributes
BC 6A 99 D6 Link guid
0D D0 24 34 PosX
E0 BC 60 40 PosY
9C 1A D3 BA PosZ
00 00 00 00 Quaternion
00 00 00 00 Quaternion
00 00 80 3F Quaternion
69 21 A2 B3 Quaternion
46 6D 30 31 "Fm01"
E0231 PF_BLOCKER
01 00 00 00 Blocker type 00=sphere(hit collision) 01=planes(path blocker)
5A D5 80 C0 PosX
5A D5 80 C0 PosY
C0 C4 0A BE PosZ
5A D5 00 41 ScaleX
5A D5 00 41 ScaleY
BD 9B 03 41 ScaleZ
1F 00 00 00 (guid maybe)
PF_BLOCKERv2 (Collision sphere)
01 00 00 00 Blocker type 00=sphere(hit collision) 01=planes(path blocker)
89 A9 41 3E PosX
C3 84 DA C0 PosY
74 9A 36 40 PosZ
F9 BB C0 40 Scale
80 1A 11 42 Unk
00 00 00 00 Always 00 00 00 00 (padding)
1F 00 00 00 (guid maybe)