// // Binary Vehicle (*.BV3, *.BV4) // Binary Vehicle (*.BV6, *.BV7) [demo] // (BlockSize: 0x00004000, CoderKey: 0x00000F2E) // //NOTE: Data layout complete, analysis pending //NOTE: BV8/BV9 "Data" is read after "Objects", and "Characteristics" are doubled and reordered (SHGBA,BHSGA). // struct Head { uint32_t FileSize; uint32_t OffsetCount; // 00000001 uint32_t OffsetArray[OffsetCount]; // 0000000C (unused) } if (!__PODDEMO__) { struct Name { uint8_t Length; // Parse: max 31+\0 char8_t String[Length]; // Coder: [i] ^= ~i } } struct Data // one big struct { for (5) // wheel[FrontR,RearR,FrontL,RearL], chassis { uint8_t unknown_0000[57]; uint8_t Unknown_0039; uint8_t unknown_003A[2]; uint32_t Unknown_003C; uint32_t Unknown_0040; uint32_t Unknown_0044; fp1616_t Position[3]; // [0..3].xy, -[4].z uint32_t Unknown_0054; uint8_t unknown_0058[56]; uint32_t Unknown_0090; uint32_t Unknown_0094; uint32_t Unknown_0098; uint32_t Unknown_009C; uint32_t Unknown_00A0; uint8_t unknown_00A4[8]; uint32_t Unknown_00AC; uint32_t Unknown_00B0; uint32_t Unknown_00B4; uint32_t Unknown_00B8; uint32_t Unknown_00BC; uint32_t Unknown_00C0; uint8_t unknown_00C4[20]; } uint8_t unknown_0438[4]; uint32_t unknown_043C; uint8_t unknown_0440[8]; uint8_t Unknown_0448; uint8_t unknown_0449[2]; uint8_t Unknown_044B; uint8_t Unknown_044C[36]; uint8_t unknown_0470[4]; uint32_t Unknown_0474; uint8_t unknown_0478[4]; uint32_t Unknown_047C; uint32_t Unknown_0480; uint32_t Unknown_0484; uint32_t Unknown_0488; uint32_t Unknown_048C; //POD1: this block is 4 bytes larger uint8_t unknown_0490[100]; uint32_t unknown_04F4; uint8_t unknown_04F8[28]; uint32_t Unknown_0514; //... uint32_t Unknown_0518; uint32_t Unknown_051C; uint32_t Unknown_0520; uint8_t unknown_0524[4]; uint32_t Unknown_0528; uint8_t unknown_052C[12]; uint32_t Unknown_0538; uint32_t Unknown_053C; uint32_t Unknown_0540; uint32_t Unknown_0544; uint32_t Unknown_0548; uint32_t Unknown_054C; //POD1: 00000002, POD2: 00000001 uint8_t unknown_0550[8]; struct List { uint32_t Count; uint32_t Array[Count]; } } struct Material { struct Name { uint8_t Length; // Parse: max 11+\0 (right[A-Za-z0-9.&_]) char8_t String[Length]; // Coder: [i] ^= ~i } if (Name.String != "GOURAUD") { uint32_t TextureCount; uint32_t TextureFlags; // "sum" of ImageFlags? for (Count) { uint32_t ImageCount; for (ImageCount) { struct Image { char8_t FileName[32]; struct TextureRect { // 00..FF (even if the texture is 00..7F) uint32_t Left; uint32_t Top; uint32_t Right; uint32_t Bottom; } uint32_t ImageFlags; // 00000001 = Non-zero pixel(s)? } } } if (__BV3__ or __BV6__) { uint8_t Palette[256][3]; // RGB888 for (TextureCount) { uint8_t TexturePixel[256][256]; // PAL8 } } if (__BV4__ or __BV7__) { for (TextureCount) { uint16_t TexturePixel[128][128]; // RGB565 } } } } struct Objects { uint32_t NamedFaces; for (22) // chassis[Good,Damaged,Ruined][RearR,RearL,SideR,SideL,FrontR,FrontL], wheel[FrontR,RearR,FrontL,RearL] { struct Object { uint32_t VertexCount; // uint16_t fp1616_t VertexArray[VertexCount][3]; uint32_t FaceCount; uint32_t TriangleCount; // used for alloc uint32_t QuadrangleCount; // used for alloc for (FaceCount) { struct Face { if (NamedFaces) { struct FaceName { uint8_t Length; char8_t String[Length]; // Coder: [i] ^= ~i } } uint32_t Vertices; // 3..4 uint32_t Indices[4]; fp1616_t Normal[3]; struct MaterialType // "FLAT", "GOURAUD", "TEXTURE", "TEXGOU" { uint8_t Length; char8_t String[Length]; // Coder: [i] ^= ~i } struct MaterialData { union { uint32_t ShadingColor; // "FLAT", "GOURAUD" uint32_t TextureIndex; // "TEXTURE", "TEXGOU" } uint32_t TextureUV[4][2]; // "TEXTURE", "TEXGOU" (00..FF) uint32_t Unknown; } if (Vertices == 4) { fp1616_t QuadReserved[3]; } struct FaceProperties { uint8_t Flags1; // 01 visible, 08 drivable, 20 ? uint8_t Flags2; // 01/02/04 ?, 08 d-sided?, 10 ? uint8_t Unknown[2]; } } } fp1616_t Normals[VertexCount][3]; uint32_t Unknown; } uint8_t Prism[28]; } //POD1: Only 1 shadow object! for (4) // shadow[Good,Ruined][Front,Rear] { struct Object { //... } } for (2) // collision meshes? { struct MaterialName { uint8_t Length; char8_t String[Length]; // Coder: [i] ^= ~i } uint32_t NamedFaces; struct Object { //... } uint8_t Prism[28]; uint32_t Unknown_001C; uint32_t Unknown_0024[3]; uint32_t Unknown_003C; uint32_t Unknown_0020; uint32_t Unknown_0030; uint8_t Unknown_00B8[Unknown_0030][64]; } } struct Noise { uint32_t Runtime; // MEG index uint16_t Unknown[15]; uint16_t Reserved; } struct Characteristics { uint32_t Acceleration; uint32_t Brakes; uint32_t Grip; uint32_t Handling; uint32_t Speed; // Acceleration + Brakes + Grip + Handling + Speed <= 300 } struct Unknown { uint32_t Unknown_0000; // (0..2) uint8_t Unknown_0004[48]; uint32_t Unknown_000C; uint32_t Unknown_0010; uint32_t Unknown_0014; // (0..2) uint32_t Unknown_0018; } if (__PODDEMO__) { struct Name { uint8_t Length; // Parse: max 31+\0 char8_t String[Length]; // Coder: [i] ^= ~i } }