Unoffical .3do by Dan Melchione Unoffical Revision by Dark Rain Verion 0.9.1 November 7th 2002 Copyright (c)1995 Dan Melchione - All Rights Reserved You have permission to distrbute this file without charge, but may not alter it in any way. This includes copying the included information for you own description of the 3do file format. Please if send me any change requests. Thanks for your cooperation. About the revision : Well the website is dead and it's been FOUR years so I assume its a moot point to try to contact him. The latest version of this document can be found at: "http://www.tauniverse.com/~visual-ta/" , in the file format section. The old link for the latest version was : http://www.melchione.com/totala/formats/3dofrmt.txt But it's dead so.... Question, Comments, Complaints To: dmelchione@melchione.com Question, Comments, Complaints about this revision To: RochDenis@hotmail.com .3do files are used by Total Annihilation (designed by Chris Taylor) for drawing the 3 dimensional objects (hence the extension of .3do). This document what I have found about the file format so far. The numbers used in this file are hexadecimal. The beginning of the file starts with following structure: typedef struct tagObject { long VersionSignature; long NumberOfVertexes long NumberOfPrimitives; long OffsetToselectionPrimitive; long XFromParent; long YFromParent; long ZFromParent; long OffsetToObjectName; long Always_0; long OffsetToVertexArray; long OffsetToPrimitiveArray; long OffsetToSiblingObject; long OffsetToChildObject; } Object; /* The fields of this structure are: VersionSignature: This is field is always one. I assume that it represents the signature (which is a somewhat standard thing to do at the beginning of a structure) NumberOfVertexes: This field represents the number of vertexes used by this object. A vertex is simply a 3D point. NumberOfPrimitives: This field represents the number of primitives used by this object. A primitive is a simple 3D object like a point, line, triangle, or quad. OffsetToselectionPrimitive: This fiel is an offset to a primitive in the parent object that will serve as the "selection" rectangle in TA. All Child and Sibling objects should have this value set to -1. XFromParent: YFromParent: ZFromParent: This appears to be the location of the object relative to the parent object. This first object in a file doesn't have any parents. It appears to be a fixed-point integer. The scale is the same as the one used to describe the primitives of an object. OffsetToObjectName: This field is an offset to the name of the object. The name of the object is stored as a null terminated string. Always_0: This field appears to always be zero. If anyone finds a case where this is not so, or has any more onfo, please let me know. OffsetToVertexArray: This is an offset to an array of vertexes used by this object. The number of vertexes in the array is stored above in NumberOfVertexes. OffsetToPrimitiveArray: This is an offset to an array of primitives used by this object. The number of primitives is stored above in NumberOfPrimitives. OffsetToSiblingObject: This is an offset to a sibling object. A sibling object is an object which shares the same parent as this object. The sibling object structure appears to be identical. The objects act like a linked list, terminated by a NULL (offset 00000000) OffsetToChildObject: This is an offset to a child object. A child object is an object which has the current object as a parent. The child object structure appears to be identical. The objects act like a linked list, terminated by a NULL (offset 00000000) */ If we examine the armsy.3do file (the arm shipyard) and overlay the above structure we end up with the following: 00000000 Object 01 00 00 00 00000001 VersionSignature C4 00 00 00 000000C4 VertexCount 6D 00 00 00 0000006D PrimitiveCount 00 00 00 00 00000000 OffsetToselectionPrimitive 00000010 00 00 00 00 00000000 XFromParent 00 00 00 00 00000000 YFromParent 00 00 00 00 00000000 ZFromParent E5 1A 00 00 00001AE5 OffsetToObjectName (base) 00000020 00 00 00 00 00000000 Always_0 15 04 00 00 00000415 OffsetToVertexArray 45 0D 00 00 00000D45 OffsetToPrimitiveArray 00 00 00 00 00000000 OffsetToSiblingObject 00000030 EA 1A 00 00 00001AEA OffsetToChildObject The object has C4 vertexes (at offset 415), 6D primitives (at offset D45), the name of the object is base, and it has a child object at offset 00001AEA. The child object at 1AEA has the same structure: 00001AEA Object 01 00 00 00 00000001 VersionSignature 29 00 00 00 00000029 VertexCount 25 00 00 00 00000025 PrimitiveCount FF FF FF FF FFFFFFFF OffsetToselectionPrimitive 00001AFA 01 00 CD FF FFCD0001 XFromParent 00 40 F7 FF FFF74000 YFromParent 00 40 CC FF FFCC4000 ZFromParent DA 22 00 00 000022DD OffsetToObjectName (turret) 00001B0A 00 00 00 00 00000000 Always_0 4E 1C 00 00 00001C4E OffsetToVertexArray 3A 1E 00 00 00001E3A OffsetToPrimitiveArray E2 22 00 00 000022E2 OffsetToSiblingObject 00001B1A 00 37 00 00 00003700 OffsetToChildObject In this case the object has 29 vertexes (at offset 1C4E), 25 primitives (at offset 1E3A), a sibling object at offset 22E2, and a child object at offset 3700. If you repeat following the sibling and child object nodes you end up with the following tree of objects: base turret1 nano1 beam1 turret2 nano2 beam2 slip light explode explode1 explode2 We find that a number of the objects (for example slip) have only one vertex and no primitives. This is used in scripting, you can set smoke points, targets, explosions etc etc. 00002ADA 01 00 00 00 00000001 VersionSignature 01 00 00 00 00000001 VertexCount 00 00 00 00 00000000 PrimitiveCount FF FF FF FF FFFFFFFF OffsetToselectionPrimitive 00002AEA 00 00 00 00 00000000 XFromParent 00 40 F7 FF FFF74000 YFromParent 00 00 00 00 00000000 ZFromParent 1A 2B 00 00 00002B1A OffsetToObjectName (slip) 00002AFA 00 00 00 00 00000000 Always_0 0E 2B 00 00 00002B0E OffsetToVertexArray 1A 2B 00 00 00002B1A OffsetToPrimitiveArray 1F 2B 00 00 00002B1F OffsetToSiblingObject 00002B0A 00 00 00 00 00000000 OffsetToChildObject In cavedog created .3do files a list of texture names always appear to be stored at offset 00000034 (more on this later): From armysy.3d0: char TextureNameArray[][]; 00000034 TextureNameArray * Pointed to by OffsetToTextureName in PrimitiveArray * Always at offset 34 for cavedog units 6E 6F 69 73 65 36 62 00 41 72 6D 34 62 00 41 72 noise6b.Arm4b.Ar 6D 42 75 69 32 62 00 41 72 6D 56 33 62 00 67 72 mBui2b.ArmV3b.gr 61 79 6E 6F 69 73 65 33 00 6E 6F 69 73 65 32 62 aynoise3.noise2b 00 41 72 6D 70 61 6E 65 6C 31 00 33 32 58 47 6F .Armpanel1.32XGo 75 72 61 75 64 00 6E 6F 69 73 65 36 61 00 66 6C uraud.noise6a.fl 61 73 68 69 6E 67 30 32 00 6D 65 74 61 6C 33 63 ashing02.metal3c 00 6D 65 74 61 6C 33 61 00 6D 65 74 61 6C 33 62 .metal3a.metal3b 00 . In cavedog created .3do files after the texture names appears to be a list of vertex indexes (more on this later) short VertexIndexArray[]; 000000A5 VertexIndexArray * Pointed to by OffsetToVertexIndexArray in PrimitiveArray C0 00 C3 00 C1 00 C2 00 B9 00 B8 00 BB 00 BA 00 000000B5 ... 00000405 06 00 0E 00 0F 00 07 00 08 00 00 00 07 00 0F 00 In cavedog created .3do files after the vertex indexes appears to be the vertexes themselves. These vertexes are pointed to in the Object structure (above) by the OffsetToVertexArray field. The format appears to be the following: typedef struct tagVertex { long x; long y; long z; } Vertex; Vertex VertexArray[]; 00000415 6D 9A D0 FF VertexArray[0].x 00 40 F7 FF VertexArray[0].y 7B 59 32 00 VertexArray[0].z AD 98 CF FF VertexArray[1].x 00000425 ... ... 00000535 6C DA C3 FF VertexArray[C2].z 00 C0 0D 00 VertexArray[C3].y 7B 19 2A 00 VertexArray[C3].x 6C 5A D7 FF VertexArray[C3].z In cavedog created .3do files after the vertexes appears to be the array of primitives. These primitives are pointed to in the Object structure (above) by the OffsetToPrimitiveArray field. The format appears to be the following: typedef struct tagPrimitive { long ColorIndex; long NumberOfVertexIndexes; long Always_0; long OffsetToVertexIndexArray; long OffsetToTextureName; long Unknown_1; long Unknown_2; long Unknown_3; } Primitive; /* ColorIndex: This is the index of a color in the TA color palette. For the color palette, check out at the very end of this file for more detail, it would take too much space to display here. NumberOfVertexIndexes: This indicates the number of vertexes used by the primitive as well as the primitive type (example: 1 = point, 2 = line, 3 = triangle, 4 = quad) Always_0: This field always appears to be 0. OffsetToVertexIndexArray: This points to a an array of shorts which are indexes into the objects vertex array. This allows multiple primitives to share the same vertexes. OffsetToTextureName: This points to a null terminated string which indicates which texture to use for this primtive. A value of 0 probably means no texture. You may notice that there is no u,v mapping coordinates for the textures. That's because you have to generate them. They're generated via the order of the polygon indexes. It really depends on you API which index is the "TO RIGHT" of the texture, the "BOTTOM LEFT" etc. You have to find it yourself. A good trick to do that, is to just have a ground plate in 3do builder and apply a texture to it. Fiddle with the textures coordinates order till you get the same result. You might have noticed that 3DO builder allows you to set the orientation of a texture? It simply does that by changing the index order. Unknown_1: Unknown_2: Unknown_3: These are Cavedog-specific used for their editor, and are not needed. Always set to 0 or ignore them. */ From armsy.3d0: 00000D45 PrimitiveArray * Pointed to by OffsetToPrimitiveArray in Header 00000D45 00 00 00 00 Unknown_0 04 00 00 00 NumberOfVertexIndexes 00 00 00 00 Always_0 A5 00 00 00 OffsetToVertexIndexArray 00 00 00 00 OffsetToTextureName 00 00 00 00 Unknown_0 00 00 00 00 Unknown_1 01 00 00 00 Unknown_2 00000D65 ... ... 00001AC5 00 00 00 00 Unknown_0 04 00 00 00 NumberOfVertexIndexes 00 00 00 00 Always_0 0D 04 00 00 OffsetToVertexIndexArray 52 00 00 00 OffsetToTextureName 00 00 00 00 Unknown_0 00 00 00 00 Unknown_1 00 00 00 00 Unknown_2 In cavedog created .3do files after the pritives appears more objects, texture names, etc. By following the linked lists in the Object structures you can map out the entire file. You may notice that there is no animation data stored in these files. This is because the animation data is stored in .bos (basic object script?) files which are compiled into .cob (cobble) files. I haven't started looking at these yet, so if anyone has any useful infomation please let me know. Well thats it for now, check back for updates. Let me know what you find so we can share the wealth. Dan Melchione dmelchione@melchione.com Dark Rain RochDenis@hotmail.com ----------- Ta palette : Here is a struct containing the whole palette, it's in C++, you can just drop it in your code if that's what you're using, eles convert it to you language using those values. PALETTEENTRY is a windows.h object btw. You can access it like this : (char)TAPalette[i].peRed; (char)TAPalette[i].peGreen; (char)TAPalette[i].peBlue; (char)TAPalette[i].peFlags; Here is the struct : PALETTEENTRY TAPalette[256] = { {0x00, 0x00, 0x00, 0x00}, {0x80, 0x00, 0x00, 0x00}, {0x00, 0x80, 0x00, 0x00}, {0x80, 0x80, 0x00, 0x00}, {0x00, 0x00, 0x80, 0x00}, {0x80, 0x00, 0x80, 0x00}, {0x00, 0x80, 0x80, 0x00}, {0x80, 0x80, 0x80, 0x00}, {0xC0, 0xDC, 0xC0, 0x00}, {0x54, 0x54, 0xFC, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0xFF, 0xEB, 0xF3, 0x00}, {0xEB, 0xC7, 0xD3, 0x00}, {0xD7, 0xA3, 0xB3, 0x00}, {0xC3, 0x87, 0x97, 0x00}, {0xAF, 0x6F, 0x7F, 0x00}, {0x9B, 0x5B, 0x63, 0x00}, {0x8B, 0x47, 0x4F, 0x00}, {0x7B, 0x3B, 0x47, 0x00}, {0x6F, 0x33, 0x3B, 0x00}, {0x63, 0x2B, 0x33, 0x00}, {0x57, 0x23, 0x2B, 0x00}, {0x4B, 0x1B, 0x27, 0x00}, {0x3B, 0x17, 0x1F, 0x00}, {0x2F, 0x0F, 0x17, 0x00}, {0x23, 0x0B, 0x0F, 0x00}, {0x17, 0x07, 0x0B, 0x00}, {0x73, 0xFF, 0xDF, 0x00}, {0x57, 0xE7, 0xBF, 0x00}, {0x43, 0xCF, 0x9F, 0x00}, {0x2F, 0xB7, 0x83, 0x00}, {0x1F, 0x9F, 0x67, 0x00}, {0x13, 0x8B, 0x4F, 0x00}, {0x0F, 0x77, 0x3F, 0x00}, {0x0B, 0x6B, 0x37, 0x00}, {0x07, 0x5F, 0x2F, 0x00}, {0x07, 0x53, 0x2B, 0x00}, {0x00, 0x47, 0x27, 0x00}, {0x00, 0x3F, 0x23, 0x00}, {0x00, 0x33, 0x1B, 0x00}, {0x00, 0x27, 0x17, 0x00}, {0x00, 0x1B, 0x0F, 0x00}, {0x00, 0x13, 0x0B, 0x00}, {0xE3, 0xEF, 0xFF, 0x00}, {0xC7, 0xDF, 0xE7, 0x00}, {0xAF, 0xCF, 0xCB, 0x00}, {0x93, 0xB7, 0xA7, 0x00}, {0x7F, 0x9F, 0x83, 0x00}, {0x6B, 0x87, 0x67, 0x00}, {0x5F, 0x6F, 0x53, 0x00}, {0x5F, 0x63, 0x47, 0x00}, {0x5B, 0x57, 0x3B, 0x00}, {0x53, 0x43, 0x33, 0x00}, {0x47, 0x3B, 0x2B, 0x00}, {0x3B, 0x33, 0x23, 0x00}, {0x2F, 0x2B, 0x1B, 0x00}, {0x23, 0x1F, 0x13, 0x00}, {0x17, 0x13, 0x0F, 0x00}, {0x0B, 0x0B, 0x07, 0x00}, {0xFB, 0xFB, 0xD7, 0x00}, {0xDF, 0xDF, 0xB7, 0x00}, {0xC3, 0xC3, 0x9B, 0x00}, {0xAB, 0xAB, 0x83, 0x00}, {0x93, 0x93, 0x6F, 0x00}, {0x77, 0x77, 0x57, 0x00}, {0x63, 0x63, 0x43, 0x00}, {0x53, 0x53, 0x33, 0x00}, {0x43, 0x43, 0x23, 0x00}, {0x33, 0x33, 0x17, 0x00}, {0x23, 0x23, 0x0F, 0x00}, {0x1B, 0x1B, 0x07, 0x00}, {0x17, 0x17, 0x07, 0x00}, {0x13, 0x13, 0x00, 0x00}, {0x0F, 0x0F, 0x00, 0x00}, {0x0B, 0x0B, 0x00, 0x00}, {0xFB, 0xFB, 0xFB, 0x00}, {0xEB, 0xEB, 0xEB, 0x00}, {0xDB, 0xDB, 0xDB, 0x00}, {0xCB, 0xCB, 0xCB, 0x00}, {0xBB, 0xBB, 0xBB, 0x00}, {0xAB, 0xAB, 0xAB, 0x00}, {0x9B, 0x9B, 0x9B, 0x00}, {0x8B, 0x8B, 0x8B, 0x00}, {0x7B, 0x7B, 0x7B, 0x00}, {0x6B, 0x6B, 0x6B, 0x00}, {0x5B, 0x5B, 0x5B, 0x00}, {0x4B, 0x4B, 0x4B, 0x00}, {0x3B, 0x3B, 0x3B, 0x00}, {0x2B, 0x2B, 0x2B, 0x00}, {0x1F, 0x1F, 0x1F, 0x00}, {0x0F, 0x0F, 0x0F, 0x00}, {0xEB, 0xF3, 0xFF, 0x00}, {0xCB, 0xE3, 0xFF, 0x00}, {0xAF, 0xCF, 0xFF, 0x00}, {0x97, 0xB3, 0xFF, 0x00}, {0x7B, 0x97, 0xFF, 0x00}, {0x67, 0x7F, 0xFF, 0x00}, {0x53, 0x6B, 0xEF, 0x00}, {0x3F, 0x5B, 0xE3, 0x00}, {0x33, 0x4B, 0xD7, 0x00}, {0x23, 0x3B, 0xCB, 0x00}, {0x17, 0x2F, 0xAF, 0x00}, {0x0F, 0x27, 0x97, 0x00}, {0x07, 0x1F, 0x7B, 0x00}, {0x07, 0x17, 0x63, 0x00}, {0x00, 0x0F, 0x47, 0x00}, {0x00, 0x0B, 0x2F, 0x00}, {0xE3, 0xF7, 0xFF, 0x00}, {0xBF, 0xDB, 0xE7, 0x00}, {0x9F, 0xBF, 0xCF, 0x00}, {0x83, 0xA7, 0xB7, 0x00}, {0x6B, 0x8F, 0xA3, 0x00}, {0x53, 0x77, 0x8B, 0x00}, {0x3F, 0x5F, 0x73, 0x00}, {0x2F, 0x4B, 0x5F, 0x00}, {0x27, 0x3F, 0x57, 0x00}, {0x23, 0x37, 0x4F, 0x00}, {0x1F, 0x2F, 0x47, 0x00}, {0x1B, 0x27, 0x3F, 0x00}, {0x17, 0x1F, 0x37, 0x00}, {0x13, 0x1B, 0x2F, 0x00}, {0x0F, 0x13, 0x27, 0x00}, {0x0B, 0x0F, 0x1F, 0x00}, {0xD7, 0xEF, 0xFF, 0x00}, {0xBB, 0xE3, 0xEF, 0x00}, {0x9B, 0xCB, 0xDF, 0x00}, {0x83, 0xB7, 0xCF, 0x00}, {0x6B, 0xA3, 0xC3, 0x00}, {0x53, 0x8F, 0xB3, 0x00}, {0x3F, 0x7B, 0xA3, 0x00}, {0x2F, 0x6B, 0x97, 0x00}, {0x23, 0x5B, 0x87, 0x00}, {0x1B, 0x4B, 0x77, 0x00}, {0x13, 0x3F, 0x67, 0x00}, {0x0B, 0x33, 0x57, 0x00}, {0x07, 0x27, 0x47, 0x00}, {0x00, 0x1B, 0x37, 0x00}, {0x00, 0x13, 0x27, 0x00}, {0x00, 0x0B, 0x1B, 0x00}, {0xFF, 0xE7, 0xFF, 0x00}, {0xE7, 0xC7, 0xEB, 0x00}, {0xD3, 0xAB, 0xD7, 0x00}, {0xBB, 0x93, 0xC3, 0x00}, {0xA7, 0x7B, 0xB3, 0x00}, {0x8F, 0x63, 0x9F, 0x00}, {0x77, 0x4B, 0x8F, 0x00}, {0x63, 0x3B, 0x7F, 0x00}, {0x4F, 0x2B, 0x6F, 0x00}, {0x43, 0x1F, 0x63, 0x00}, {0x37, 0x17, 0x57, 0x00}, {0x2B, 0x0F, 0x47, 0x00}, {0x1F, 0x07, 0x3B, 0x00}, {0x13, 0x00, 0x2B, 0x00}, {0x0B, 0x00, 0x1F, 0x00}, {0x07, 0x00, 0x13, 0x00}, {0xD7, 0xFF, 0xA7, 0x00}, {0xAB, 0xE7, 0x7F, 0x00}, {0x83, 0xD3, 0x5B, 0x00}, {0x67, 0xBF, 0x3F, 0x00}, {0x4B, 0xAB, 0x2B, 0x00}, {0x43, 0x97, 0x2B, 0x00}, {0x37, 0x87, 0x27, 0x00}, {0x2F, 0x77, 0x1B, 0x00}, {0x2B, 0x67, 0x13, 0x00}, {0x23, 0x5B, 0x0F, 0x00}, {0x1F, 0x4F, 0x0B, 0x00}, {0x1B, 0x43, 0x07, 0x00}, {0x17, 0x33, 0x00, 0x00}, {0x0F, 0x27, 0x00, 0x00}, {0x0B, 0x1B, 0x00, 0x00}, {0x07, 0x0F, 0x00, 0x00}, {0xFF, 0xE3, 0x9F, 0x00}, {0xE3, 0xC7, 0x73, 0x00}, {0xCB, 0xAF, 0x53, 0x00}, {0xB3, 0x97, 0x3F, 0x00}, {0x9B, 0x83, 0x2F, 0x00}, {0x83, 0x6F, 0x23, 0x00}, {0x6B, 0x5B, 0x17, 0x00}, {0x53, 0x47, 0x0F, 0x00}, {0x4B, 0x3B, 0x0B, 0x00}, {0x43, 0x33, 0x07, 0x00}, {0x3B, 0x2B, 0x07, 0x00}, {0x37, 0x23, 0x00, 0x00}, {0x2F, 0x1B, 0x00, 0x00}, {0x27, 0x13, 0x00, 0x00}, {0x1F, 0x0F, 0x00, 0x00}, {0x1B, 0x0B, 0x00, 0x00}, {0xFF, 0xFF, 0xA3, 0x00}, {0xFB, 0xF3, 0x83, 0x00}, {0xF7, 0xE3, 0x67, 0x00}, {0xF3, 0xD3, 0x4F, 0x00}, {0xEF, 0xBB, 0x33, 0x00}, {0xEF, 0xA7, 0x1B, 0x00}, {0xEB, 0x8F, 0x13, 0x00}, {0xE7, 0x7B, 0x0F, 0x00}, {0xDF, 0x4F, 0x07, 0x00}, {0xD7, 0x23, 0x00, 0x00}, {0xBF, 0x1F, 0x00, 0x00}, {0xA7, 0x1B, 0x00, 0x00}, {0x93, 0x17, 0x00, 0x00}, {0x7B, 0x13, 0x00, 0x00}, {0x63, 0x13, 0x00, 0x00}, {0x4F, 0x0F, 0x00, 0x00}, {0xFF, 0xFF, 0x00, 0x00}, {0xFF, 0xBF, 0x00, 0x00}, {0xFF, 0x83, 0x00, 0x00}, {0xFF, 0x47, 0x00, 0x00}, {0xD3, 0x2B, 0x00, 0x00}, {0xAB, 0x17, 0x00, 0x00}, {0x7F, 0x07, 0x00, 0x00}, {0x57, 0x00, 0x00, 0x00}, {0xDF, 0xCB, 0xFF, 0x00}, {0xBB, 0x9F, 0xDF, 0x00}, {0x9B, 0x77, 0xBF, 0x00}, {0x7F, 0x57, 0x9F, 0x00}, {0x67, 0x3B, 0x7F, 0x00}, {0x4B, 0x23, 0x5F, 0x00}, {0x33, 0x13, 0x3F, 0x00}, {0x1B, 0x07, 0x1F, 0x00}, {0xD3, 0xDB, 0xFF, 0x00}, {0x87, 0x9F, 0xF7, 0x00}, {0x43, 0x6F, 0xEF, 0x00}, {0x17, 0x47, 0xE7, 0x00}, {0x0B, 0x2B, 0xBB, 0x00}, {0x07, 0x17, 0x8F, 0x00}, {0x00, 0x07, 0x63, 0x00}, {0x00, 0x00, 0x37, 0x00}, {0x7B, 0xFF, 0x77, 0x00}, {0x53, 0xDF, 0x4F, 0x00}, {0x33, 0xBF, 0x2B, 0x00}, {0x1B, 0x9F, 0x13, 0x00}, {0x1B, 0x7F, 0x0B, 0x00}, {0x17, 0x5F, 0x07, 0x00}, {0x13, 0x3F, 0x00, 0x00}, {0x0B, 0x1F, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0xFF, 0xFB, 0xF0, 0x00}, {0xA0, 0xA0, 0xA4, 0x00}, {0x80, 0x80, 0x80, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0x00, 0xFF, 0x00, 0x00}, {0xFF, 0xFF, 0x00, 0x00}, {0x00, 0x00, 0xFF, 0x00}, {0xFF, 0x00, 0xFF, 0x00}, {0x00, 0xFF, 0xFF, 0x00}, {0xFF, 0xFF, 0xFF, 0x00}};