26#include <wx/sstream.h>
28#include <wx/translation.h>
52 uint32_t w1 = aStream.
ReadU32();
53 uint32_t w2 = aStream.
ReadU32();
74 const uint32_t a = aStream.
ReadU32();
75 const uint32_t b = aStream.
ReadU32();
78 const uint64_t
combined = (
static_cast<uint64_t
>( a ) << 32 ) + b;
87template <
typename ARRAY>
90 for(
size_t i = 0; i < aArray.size(); i++ )
101 if constexpr( std::is_same_v<T, uint32_t> )
105 else if constexpr( std::is_same_v<T, uint8_t> )
109 else if constexpr( std::is_same_v<T, uint16_t> )
113 else if constexpr( std::is_same_v<T, int16_t> )
117 else if constexpr( std::is_same_v<T, int32_t> )
121 else if constexpr( std::is_same_v<T, FILE_HEADER::LINKED_LIST> )
123 field =
ReadLL( aStream, aFmtVer );
125 else if constexpr(
requires { std::tuple_size<T>::value; } )
127 for(
size_t i = 0; i < std::tuple_size_v<T>; ++i )
143template <
typename COND_T>
146 if( COND_T::exists( aFmtVer ) )
155 uint32_t masked = aMagic & 0xFFFFFF00;
182 uint32_t majorVer = ( aMagic >> 16 ) & 0xFFFF;
184 if( majorVer <= 0x0012 )
188 const uint32_t topByte = aMagic >> 24;
190 if( topByte >= 0x0F && topByte <= 0x12 && ( aMagic & 0x00FF0000 ) == 0 )
195 THROW_IO_ERRORF(
_(
"Unknown Allegro file version %#010x (rev %d)" ), aMagic, majorVer - 3 );
201 auto header = std::make_unique<ALLEGRO::FILE_HEADER>();
202 const size_t headerStartPos =
m_stream.Position();
204 uint32_t fileMagic =
m_stream.ReadU32();
207 header->m_Magic = fileMagic;
209 header->m_Unknown1a =
m_stream.ReadU32();
210 header->m_FileRole =
m_stream.ReadU32();
211 header->m_Unknown1b =
m_stream.ReadU32();
212 header->m_WriterProgram =
m_stream.ReadU32();
214 header->m_ObjectCount =
m_stream.ReadU32();
216 header->m_UnknownMagic =
m_stream.ReadU32();
217 header->m_UnknownFlags =
m_stream.ReadU32();
275 wxASSERT(
m_stream.Position() - headerStartPos == 0xF8 );
277 wxASSERT(
m_stream.Position() - headerStartPos == 0x124 );
279 wxASSERT(
m_stream.Position() - headerStartPos == 0x144 );
281 m_stream.ReadBytes( header->m_AllegroVersion.data(), header->m_AllegroVersion.size() );
282 header->m_Unknown4 =
m_stream.ReadU32();
283 header->m_MaxKey =
m_stream.ReadU32();
298 header->m_BoardUnits =
static_cast<BOARD_UNITS>( units );
308 header->m_Unknown6 =
m_stream.ReadU32();
313 header->m_Unknown8 =
m_stream.ReadU32();
319 header->m_Unknown10a =
m_stream.ReadU32();
320 header->m_Unknown10b =
m_stream.ReadU32();
321 header->m_Unknown10c =
m_stream.ReadU32();
323 header->m_UnitsDivisor =
m_stream.ReadU32();
327 for(
size_t i = 0; i < header->m_LayerMap.size(); ++i )
329 header->m_LayerMap[i].m_A =
m_stream.ReadU32();
330 header->m_LayerMap[i].m_LayerList0x2A =
m_stream.ReadU32();
333 wxLogTrace(
traceAllegroParser, wxT(
"Parsed header: %d objects, %d strings" ), header->m_ObjectCount,
334 header->GetStringsCount() );
344 static constexpr size_t STRING_TABLE_OFFSET = 0x1200;
346 stream.
Seek( STRING_TABLE_OFFSET );
348 for( uint32_t i = 0; i < count; ++i )
350 uint32_t
id = stream.
ReadU32();
360 uint8_t classCode = aStream.
ReadU8();
361 uint8_t subclassCode = aStream.
ReadU8();
366 .m_Class = classCode,
367 .m_Subclass = subclassCode,
374 auto block = std::make_unique<BLOCK<BLK_0x01_ARC>>( aStream.
Position() );
376 auto& data = block->GetData();
380 data.m_UnknownByte = aStream.
ReadU8();
381 data.m_SubType = aStream.
ReadU8();
382 data.m_Key = aStream.
ReadU32();
383 block->SetKey( data.m_Key );
384 data.m_Next = aStream.
ReadU32();
385 block->SetNext( data.m_Next );
386 data.m_Parent = aStream.
ReadU32();
387 data.m_Unknown1 = aStream.
ReadU32();
389 ReadCond( aStream, aVer, data.m_Unknown6 );
391 data.m_Width = aStream.
ReadU32();
393 data.m_StartX = aStream.
ReadS32();
394 data.m_StartY = aStream.
ReadS32();
395 data.m_EndX = aStream.
ReadS32();
396 data.m_EndY = aStream.
ReadS32();
402 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
404 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
413 auto block = std::make_unique<BLOCK<BLK_0x03_FIELD>>( aStream.
Position() );
415 auto& data = block->GetData();
419 data.m_Hdr1 = aStream.
ReadU16();
420 data.m_Key = aStream.
ReadU32();
421 block->SetKey( data.m_Key );
422 data.m_Next = aStream.
ReadU32();
423 block->SetNext( data.m_Next );
425 ReadCond( aStream, aVer, data.m_Unknown1 );
427 data.m_SubType = aStream.
ReadU8();
428 data.m_Hdr2 = aStream.
ReadU8();
429 data.m_Size = aStream.
ReadU16();
431 ReadCond( aStream, aVer, data.m_Unknown2 );
436 switch( data.m_SubType )
446 data.m_Substruct = aStream.
ReadU32();
451 data.m_Substruct = std::array<uint32_t, 2>{
476 THROW_IO_ERRORF( wxT(
"Block 0x03 subtype 0x6C entry count %u exceeds limit at offset %#010zx" ),
486 data.m_Substruct = std::move( sub );
497 const size_t numEntries = ( sub.
m_X1 + 4 * sub.
m_X0 );
499 for(
size_t i = 0; i < numEntries; ++i )
503 data.m_Substruct = std::move( sub );
509 for(
size_t i = 0; i < sub.
m_Entries.size(); ++i )
513 data.m_Substruct = std::move( sub );
518 if( data.m_Size == 4 )
520 data.m_Substruct = aStream.
ReadU32();
522 else if( data.m_Size == 8 )
524 std::array<uint32_t, 2> sub;
527 data.m_Substruct = std::move( sub );
531 THROW_IO_ERRORF( wxT(
"Unknown substruct type %#02x with size %d" ), data.m_SubType, data.m_Size );
543 auto block = std::make_unique<BLOCK<BLK_0x04_NET_ASSIGNMENT>>( aStream.
Position() );
545 auto& data = block->GetData();
547 data.m_Type = aStream.
ReadU8();
549 data.m_Key = aStream.
ReadU32();
550 block->SetKey( data.m_Key );
551 data.m_Next = aStream.
ReadU32();
552 block->SetNext( data.m_Next );
553 data.m_Net = aStream.
ReadU32();
554 data.m_ConnItem = aStream.
ReadU32();
556 ReadCond( aStream, aVer, data.m_Unknown );
564 auto block = std::make_unique<BLOCK<BLK_0x05_TRACK>>( aStream.
Position() );
566 auto& data = block->GetData();
571 data.m_Key = aStream.
ReadU32();
572 block->SetKey( data.m_Key );
573 data.m_Next = aStream.
ReadU32();
574 block->SetNext( data.m_Next );
575 data.m_NetAssignment = aStream.
ReadU32();
576 data.m_UnknownPtr1 = aStream.
ReadU32();
577 data.m_Unknown2 = aStream.
ReadU32();
578 data.m_Unknown3 = aStream.
ReadU32();
579 data.m_UnknownPtr2a = aStream.
ReadU32();
580 data.m_UnknownPtr2b = aStream.
ReadU32();
581 data.m_Unknown4 = aStream.
ReadU32();
582 data.m_UnknownPtr3a = aStream.
ReadU32();
583 data.m_UnknownPtr3b = aStream.
ReadU32();
585 ReadCond( aStream, aVer, data.m_Unknown5a );
586 ReadCond( aStream, aVer, data.m_Unknown5b );
588 data.m_FirstSegPtr = aStream.
ReadU32();
589 data.m_UnknownPtr5 = aStream.
ReadU32();
590 data.m_Unknown6 = aStream.
ReadU32();
598 auto block = std::make_unique<BLOCK<BLK_0x06_COMPONENT>>( stream.
Position() );
600 auto& data = block->GetData();
605 block->SetKey( data.m_Key );
606 data.m_Next = stream.
ReadU32();
607 block->SetNext( data.m_Next );
608 data.m_CompDeviceType = stream.
ReadU32();
609 data.m_SymbolName = stream.
ReadU32();
610 data.m_FirstInstPtr = stream.
ReadU32();
611 data.m_PtrFunctionSlot = stream.
ReadU32();
612 data.m_PtrPinNumber = stream.
ReadU32();
613 data.m_Fields = stream.
ReadU32();
615 ReadCond( stream, aVer, data.m_Unknown1 );
623 auto block = std::make_unique<BLOCK<BLK_0x07_COMPONENT_INST>>( stream.
Position() );
625 auto& data = block->GetData();
630 block->SetKey( data.m_Key );
631 data.m_Next = stream.
ReadU32();
632 block->SetNext( data.m_Next );
634 ReadCond( stream, aVer, data.m_UnknownPtr1 );
635 ReadCond( stream, aVer, data.m_Unknown2 );
636 ReadCond( stream, aVer, data.m_Unknown3 );
638 data.m_FpInstPtr = stream.
ReadU32();
640 ReadCond( stream, aVer, data.m_Unknown4 );
642 data.m_RefDesStrPtr = stream.
ReadU32();
643 data.m_FunctionInstPtr = stream.
ReadU32();
644 data.m_X03Ptr = stream.
ReadU32();
645 data.m_Unknown5 = stream.
ReadU32();
646 data.m_FirstPadPtr = stream.
ReadU32();
654 auto block = std::make_unique<BLOCK<BLK_0x08_PIN_NUMBER>>( aStream.
Position() );
656 auto& data = block->GetData();
658 data.m_Type = aStream.
ReadU8();
660 data.m_Key = aStream.
ReadU32();
661 block->SetKey( data.m_Key );
663 ReadCond( aStream, aVer, data.m_Previous );
664 ReadCond( aStream, aVer, data.m_StrPtr16x );
666 data.m_Next = aStream.
ReadU32();
667 block->SetNext( data.m_Next );
669 ReadCond( aStream, aVer, data.m_StrPtr );
671 data.m_PinNamePtr = aStream.
ReadU32();
673 ReadCond( aStream, aVer, data.m_Unknown1 );
675 data.m_Ptr4 = aStream.
ReadU32();
683 auto block = std::make_unique<BLOCK<BLK_0x09_FILL_LINK>>( aStream.
Position() );
685 auto& data = block->GetData();
689 data.m_Key = aStream.
ReadU32();
690 block->SetKey( data.m_Key );
692 for(
size_t i = 0; i < data.m_UnknownArray.size(); ++i )
694 data.m_UnknownArray[i] = aStream.
ReadU32();
697 ReadCond( aStream, aVer, data.m_Unknown1 );
699 data.m_UnknownPtr1 = aStream.
ReadU32();
700 data.m_UnknownPtr2 = aStream.
ReadU32();
701 data.m_Unknown2 = aStream.
ReadU32();
702 data.m_UnknownPtr3 = aStream.
ReadU32();
703 data.m_UnknownPtr4 = aStream.
ReadU32();
705 ReadCond( aStream, aVer, data.m_Unknown3 );
713 auto block = std::make_unique<BLOCK<BLK_0x0A_DRC>>( aStream.
Position() );
715 auto& data = block->GetData();
717 data.m_T = aStream.
ReadU8();
719 data.m_Key = aStream.
ReadU32();
720 block->SetKey( data.m_Key );
721 data.m_Next = aStream.
ReadU32();
722 block->SetNext( data.m_Next );
723 data.m_Unknown1 = aStream.
ReadU32();
725 ReadCond( aStream, aVer, data.m_Unknown2 );
727 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
729 data.m_Coords[i] = aStream.
ReadS32();
735 ReadCond( aStream, aVer, data.m_Unknown6 );
743 auto block = std::make_unique<BLOCK<BLK_0x0C_PIN_DEF>>( aStream.
Position() );
745 auto& data = block->GetData();
747 data.m_T = aStream.
ReadU8();
750 data.m_Key = aStream.
ReadU32();
751 block->SetKey( data.m_Key );
752 data.m_Next = aStream.
ReadU32();
753 block->SetNext( data.m_Next );
755 data.m_Unknown1 = aStream.
ReadU32();
756 data.m_Unknown2 = aStream.
ReadU32();
759 ReadCond( aStream, aVer, data.m_Shape );
760 ReadCond( aStream, aVer, data.m_DrillChar );
761 ReadCond( aStream, aVer, data.m_UnknownPadding );
764 ReadCond( aStream, aVer, data.m_Shape16x );
765 ReadCond( aStream, aVer, data.m_DrillChars );
766 ReadCond( aStream, aVer, data.m_Unknown_16x );
768 data.m_Unknown4 = aStream.
ReadU32();
769 ReadCond( aStream, aVer, data.m_Unknown5 );
771 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
773 data.m_Coords[i] = aStream.
ReadS32();
776 for(
size_t i = 0; i < data.m_Size.size(); ++i )
778 data.m_Size[i] = aStream.
ReadS32();
781 data.m_GroupPtr = aStream.
ReadU32();
782 data.m_Unknown6 = aStream.
ReadU32();
783 data.m_Unknown7 = aStream.
ReadU32();
785 ReadCond( aStream, aVer, data.m_Unknown8 );
793 auto block = std::make_unique<BLOCK<BLK_0x0D_PAD>>( aStream.
Position() );
795 auto& data = block->GetData();
799 data.m_Key = aStream.
ReadU32();
800 block->SetKey( data.m_Key );
801 data.m_NameStrId = aStream.
ReadU32();
802 data.m_Next = aStream.
ReadU32();
803 block->SetNext( data.m_Next );
805 ReadCond( aStream, aVer, data.m_Unknown1 );
807 data.m_CoordsX = aStream.
ReadS32();
808 data.m_CoordsY = aStream.
ReadS32();
810 data.m_PadStack = aStream.
ReadU32();
811 data.m_Unknown2 = aStream.
ReadU32();
813 ReadCond( aStream, aVer, data.m_Unknown3 );
815 data.m_Flags = aStream.
ReadU32();
816 data.m_Rotation = aStream.
ReadU32();
824 auto block = std::make_unique<BLOCK<BLK_0x0E_RECT>>( aStream.
Position() );
826 auto& data = block->GetData();
828 data.m_T = aStream.
ReadU8();
830 data.m_Key = aStream.
ReadU32();
831 block->SetKey( data.m_Key );
832 data.m_Next = aStream.
ReadU32();
833 block->SetNext( data.m_Next );
834 data.m_FpPtr = aStream.
ReadU32();
836 data.m_Unknown1 = aStream.
ReadU32();
837 data.m_Unknown2 = aStream.
ReadU32();
838 data.m_Unknown3 = aStream.
ReadU32();
840 ReadCond( aStream, aVer, data.m_Unknown4 );
841 ReadCond( aStream, aVer, data.m_Unknown5 );
843 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
845 data.m_Coords[i] = aStream.
ReadS32();
848 for(
size_t i = 0; i < data.m_UnknownArr.size(); ++i )
850 data.m_UnknownArr[i] = aStream.
ReadU32();
853 data.m_Rotation = aStream.
ReadU32();
861 auto block = std::make_unique<BLOCK<BLK_0x0F_FUNCTION_SLOT>>( stream.
Position() );
863 auto& data = block->GetData();
868 block->SetKey( data.m_Key );
869 data.m_SlotName = stream.
ReadU32();
871 ReadCond( stream, aVer, data.m_Unknown1 );
874 stream.
ReadBytes( data.m_CompDeviceType.data(), data.m_CompDeviceType.size() );
876 ReadCond( stream, aVer, data.m_CompDeviceTypePtr );
878 ReadCond( stream, aVer, data.m_Next );
879 block->SetNext( data.m_Next.value_or( 0 ) );
881 data.m_Ptr0x06 = stream.
ReadU32();
882 data.m_Ptr0x11 = stream.
ReadU32();
883 data.m_Unknown2 = stream.
ReadU32();
891 auto block = std::make_unique<BLOCK<BLK_0x10_FUNCTION_INST>>( stream.
Position() );
893 auto& data = block->GetData();
898 block->SetKey( data.m_Key );
900 ReadCond( stream, aVer, data.m_Unknown1 );
901 data.m_ComponentInstPtr = stream.
ReadU32();
902 ReadCond( stream, aVer, data.m_Unknown2 );
903 data.m_PtrX12 = stream.
ReadU32();
904 data.m_Unknown3 = stream.
ReadU32();
905 data.m_FunctionName = stream.
ReadU32();
906 data.m_Slots = stream.
ReadU32();
907 data.m_Fields = stream.
ReadU32();
915 auto block = std::make_unique<BLOCK<BLK_0x11_PIN_NAME>>( aStream.
Position() );
917 auto& data = block->GetData();
919 data.m_Type = aStream.
ReadU8();
921 data.m_Key = aStream.
ReadU32();
922 block->SetKey( data.m_Key );
923 data.m_PinNameStrPtr = aStream.
ReadU32();
924 data.m_Next = aStream.
ReadU32();
925 block->SetNext( data.m_Next );
926 data.m_PinNumberPtr = aStream.
ReadU32();
927 data.m_Unknown1 = aStream.
ReadU32();
929 ReadCond( aStream, aVer, data.m_Unknown2 );
937 auto block = std::make_unique<BLOCK<BLK_0x12_XREF>>( aStream.
Position() );
939 auto& data = block->GetData();
941 data.m_Type = aStream.
ReadU8();
943 data.m_Key = aStream.
ReadU32();
944 block->SetKey( data.m_Key );
945 data.m_Ptr1 = aStream.
ReadU32();
946 data.m_Ptr2 = aStream.
ReadU32();
947 data.m_Ptr3 = aStream.
ReadU32();
948 data.m_Unknown1 = aStream.
ReadU32();
950 ReadCond( aStream, aVer, data.m_Unknown2 );
951 ReadCond( aStream, aVer, data.m_Unknown3 );
959 auto block = std::make_unique<BLOCK<BLK_0x14_GRAPHIC>>( aStream.
Position() );
961 auto& data = block->GetData();
963 data.m_Type = aStream.
ReadU8();
965 data.m_Key = aStream.
ReadU32();
966 block->SetKey( data.m_Key );
967 data.m_Next = aStream.
ReadU32();
968 block->SetNext( data.m_Next );
969 data.m_Parent = aStream.
ReadU32();
970 data.m_Flags = aStream.
ReadU32();
972 ReadCond( aStream, aVer, data.m_Unknown2 );
974 data.m_SegmentPtr = aStream.
ReadU32();
975 data.m_Ptr0x03 = aStream.
ReadU32();
976 data.m_Ptr0x26 = aStream.
ReadU32();
984 auto block = std::make_unique<BLOCK<BLK_0x15_16_17_SEGMENT>>( aType, aStream.
Position() );
986 auto& data = block->GetData();
990 data.m_Key = aStream.
ReadU32();
991 block->SetKey( data.m_Key );
992 data.m_Next = aStream.
ReadU32();
993 block->SetNext( data.m_Next );
994 data.m_Parent = aStream.
ReadU32();
995 data.m_Flags = aStream.
ReadU32();
997 ReadCond( aStream, aVer, data.m_Unknown2 );
999 data.m_Width = aStream.
ReadU32();
1001 data.m_StartX = aStream.
ReadS32();
1002 data.m_StartY = aStream.
ReadS32();
1003 data.m_EndX = aStream.
ReadS32();
1004 data.m_EndY = aStream.
ReadS32();
1012 auto block = std::make_unique<BLOCK<BLK_0x1A_UNKNOWN>>( aStream.
Position() );
1014 auto& data = block->GetData();
1016 data.m_Type = aStream.
ReadU8();
1017 data.m_T2 = aStream.
ReadU16();
1018 data.m_Key = aStream.
ReadU32();
1019 block->SetKey( data.m_Key );
1029 auto block = std::make_unique<BLOCK<BLK_0x1B_NET>>( stream.
Position() );
1031 auto& data = block->GetData();
1035 data.m_Key = stream.
ReadU32();
1036 block->SetKey( data.m_Key );
1037 data.m_Next = stream.
ReadU32();
1038 block->SetNext( data.m_Next );
1039 data.m_NetName = stream.
ReadU32();
1040 data.m_Unknown1 = stream.
ReadU32();
1042 ReadCond( stream, aVer, data.m_Unknown2 );
1044 data.m_Type = stream.
ReadU32();
1045 data.m_Assignment = stream.
ReadU32();
1046 data.m_Ratline = stream.
ReadU32();
1047 data.m_FieldsPtr = stream.
ReadU32();
1048 data.m_MatchGroupPtr = stream.
ReadU32();
1049 data.m_ModelPtr = stream.
ReadU32();
1050 data.m_UnknownPtr4 = stream.
ReadU32();
1051 data.m_UnknownPtr5 = stream.
ReadU32();
1052 data.m_UnknownPtr6 = stream.
ReadU32();
1061 switch( (aVal & 0xF0) )
1086 auto block = std::make_unique<BLOCK<BLK_0x1C_PADSTACK>>( aStream.
Position() );
1088 auto& data = block->GetData();
1090 data.m_UnknownByte1 = aStream.
ReadU8();
1091 data.m_N = aStream.
ReadU8();
1092 data.m_StartLayer = aStream.
ReadU8();
1094 data.m_Key = aStream.
ReadU32();
1095 block->SetKey( data.m_Key );
1096 data.m_Next = aStream.
ReadU32();
1097 block->SetNext( data.m_Next );
1098 data.m_PadStr = aStream.
ReadU32();
1141 uint8_t padTypeAndA = aStream.
ReadU8();
1143 hdr.
m_A = ( padTypeAndA & 0x0F );
1183 static const uint16_t MAX_LAYER_COUNT = 256;
1184 if( data.GetLayerCount() > MAX_LAYER_COUNT )
1185 throw std::runtime_error(
"Layer count exceeds maximum of " + std::to_string( MAX_LAYER_COUNT ) );
1189 data.m_NumFixedCompEntries = 10;
1191 data.m_NumFixedCompEntries = 11;
1193 data.m_NumFixedCompEntries = 21;
1198 const size_t nComps = data.m_NumFixedCompEntries + ( data.GetLayerCount() * data.m_NumCompsPerLayer );
1200 data.m_Components.reserve( nComps );
1201 for(
size_t i = 0; i < nComps; ++i )
1236 const size_t nElems = data.m_N * ( ( aVer <
FMT_VER::V_172 ) ? 8 : 10 );
1238 data.m_UnknownArrN.reserve( nElems );
1239 for(
size_t i = 0; i < nElems; ++i )
1241 data.m_UnknownArrN.push_back( aStream.
ReadU32() );
1251 auto block = std::make_unique<BLOCK<BLK_0x1D_CONSTRAINT_SET>>( aStream.
Position() );
1253 auto& data = block->GetData();
1257 data.m_Key = aStream.
ReadU32();
1258 block->SetKey( data.m_Key );
1259 data.m_Next = aStream.
ReadU32();
1260 block->SetNext( data.m_Next );
1261 data.m_NameStrKey = aStream.
ReadU32();
1262 data.m_FieldPtr = aStream.
ReadU32();
1264 data.m_SizeA = aStream.
ReadU16();
1265 data.m_SizeB = aStream.
ReadU16();
1267 data.m_DataB.resize( data.m_SizeB );
1270 const size_t layerRecordSize = aVer ==
FMT_VER::V_161 ? 48 :
sizeof( data.m_DataB[0] );
1272 for(
auto& item : data.m_DataB )
1275 aStream.
ReadBytes( item.data(), layerRecordSize );
1278 data.m_DataA.resize( data.m_SizeA );
1280 for(
auto& item : data.m_DataA )
1281 aStream.
ReadBytes( item.data(), item.size() );
1283 ReadCond( aStream, aVer, data.m_Unknown4 );
1291 auto block = std::make_unique<BLOCK<BLK_0x1E_SI_MODEL>>( aStream.
Position() );
1293 auto& data = block->GetData();
1295 data.m_Type = aStream.
ReadU8();
1296 data.m_T2 = aStream.
ReadU16();
1297 data.m_Key = aStream.
ReadU32();
1298 block->SetKey( data.m_Key );
1299 data.m_Next = aStream.
ReadU32();
1300 block->SetNext( data.m_Next );
1302 ReadCond( aStream, aVer, data.m_Unknown2 );
1303 ReadCond( aStream, aVer, data.m_Unknown3 );
1305 data.m_StrPtr = aStream.
ReadU32();
1306 data.m_Size = aStream.
ReadU32();
1310 ReadCond( aStream, aVer, data.m_Unknown4 );
1318 auto block = std::make_unique<BLOCK<BLK_0x1F_PADSTACK_DIM>>( aStream.
Position() );
1320 auto& data = block->GetData();
1324 data.m_Key = aStream.
ReadU32();
1325 block->SetKey( data.m_Key );
1327 data.m_Next = aStream.
ReadU32();
1328 block->SetNext( data.m_Next );
1329 data.m_Unknown2 = aStream.
ReadU32();
1330 data.m_Unknown3 = aStream.
ReadU32();
1331 data.m_Unknown4 = aStream.
ReadU32();
1332 data.m_Unknown5 = aStream.
ReadU16();
1334 data.m_Size = aStream.
ReadU16();
1336 size_t substructSize = 0;
1338 substructSize = data.m_Size * 384 + 8;
1340 substructSize = data.m_Size * 280 + 8;
1342 substructSize = data.m_Size * 280 + 4;
1344 substructSize = data.m_Size * 240 + 4;
1346 data.m_Substruct.resize( substructSize );
1347 aStream.
ReadBytes( data.m_Substruct.data(), substructSize );
1355 auto block = std::make_unique<BLOCK<BLK_0x20_UNKNOWN>>( aStream.
Position() );
1357 auto& data = block->GetData();
1359 data.m_Type = aStream.
ReadU8();
1361 data.m_Key = aStream.
ReadU32();
1362 block->SetKey( data.m_Key );
1363 data.m_Next = aStream.
ReadU32();
1364 block->SetNext( data.m_Next );
1367 ReadCond( aStream, aVer, data.m_UnknownArray2 );
1375 auto block = std::make_unique<BLOCK<BLK_0x21_BLOB>>( aStream.
Position() );
1377 auto& data = block->GetData();
1379 data.m_Type = aStream.
ReadU8();
1382 data.m_Size = aStream.
ReadU32();
1384 if( data.m_Size < 12 )
1386 THROW_IO_ERRORF( wxT(
"Block 0x21 size %u too small (minimum 12) at offset %#010zx" ),
1390 data.m_Key = aStream.
ReadU32();
1391 block->SetKey( data.m_Key );
1393 const size_t nBytes = data.m_Size - 12;
1394 data.m_Data.resize( nBytes );
1395 aStream.
ReadBytes( data.m_Data.data(), nBytes );
1403 auto block = std::make_unique<BLOCK<BLK_0x22_UNKNOWN>>( aStream.
Position() );
1405 auto& data = block->GetData();
1407 data.m_Type = aStream.
ReadU8();
1408 data.m_T2 = aStream.
ReadU16();
1409 data.m_Key = aStream.
ReadU32();
1410 block->SetKey( data.m_Key );
1412 ReadCond( aStream, aVer, data.m_Unknown1 );
1422 auto block = std::make_unique<BLOCK<BLK_0x23_RATLINE>>( aStream.
Position() );
1424 auto& data = block->GetData();
1426 data.m_Type = aStream.
ReadU8();
1428 data.m_Key = aStream.
ReadU32();
1429 block->SetKey( data.m_Key );
1430 data.m_Next = aStream.
ReadU32();
1431 block->SetNext( data.m_Next );
1435 data.m_Ptr1 = aStream.
ReadU32();
1436 data.m_Ptr2 = aStream.
ReadU32();
1437 data.m_Ptr3 = aStream.
ReadU32();
1439 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1441 data.m_Coords[i] = aStream.
ReadS32();
1446 ReadCond( aStream, aVer, data.m_Unknown2 );
1447 ReadCond( aStream, aVer, data.m_Unknown3 );
1455 auto block = std::make_unique<BLOCK<BLK_0x24_RECT>>( aStream.
Position() );
1457 auto& data = block->GetData();
1459 data.m_Type = aStream.
ReadU8();
1461 data.m_Key = aStream.
ReadU32();
1462 block->SetKey( data.m_Key );
1463 data.m_Next = aStream.
ReadU32();
1464 block->SetNext( data.m_Next );
1465 data.m_Parent = aStream.
ReadU32();
1466 data.m_Unknown1 = aStream.
ReadU32();
1468 ReadCond( aStream, aVer, data.m_Unknown2 );
1470 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1472 data.m_Coords[i] = aStream.
ReadS32();
1475 data.m_Ptr2 = aStream.
ReadU32();
1477 data.m_Unknown3 = aStream.
ReadU32();
1478 data.m_Unknown4 = aStream.
ReadU32();
1479 data.m_Rotation = aStream.
ReadU32();
1487 auto block = std::make_unique<BLOCK<BLK_0x26_MATCH_GROUP>>( aStream.
Position() );
1489 auto& data = block->GetData();
1491 data.m_Type = aStream.
ReadU8();
1493 data.m_Key = aStream.
ReadU32();
1494 block->SetKey( data.m_Key );
1495 data.m_MemberPtr = aStream.
ReadU32();
1497 ReadCond( aStream, aVer, data.m_Unknown1 );
1499 data.m_GroupPtr = aStream.
ReadU32();
1500 data.m_ConstPtr = aStream.
ReadU32();
1502 ReadCond( aStream, aVer, data.m_Unknown2 );
1510 auto block = std::make_unique<BLOCK<BLK_0x27_CSTRMGR_XREF>>( aStream.
Position() );
1512 auto& data = block->GetData();
1514 const size_t totalBytes = aEndOff - 1 - aStream.
Position();
1517 constexpr size_t kPadding = 3;
1519 if( totalBytes <= kPadding )
1521 aStream.
Skip( totalBytes );
1525 aStream.
Skip( kPadding );
1527 const size_t payloadBytes = totalBytes - kPadding;
1528 const size_t numValues = payloadBytes / 4;
1529 const size_t remainder = payloadBytes % 4;
1531 data.m_Refs.resize( numValues );
1533 for(
size_t i = 0; i < numValues; i++ )
1534 data.m_Refs[i] = aStream.
ReadU32();
1537 aStream.
Skip( remainder );
1545 auto block = std::make_unique<BLOCK<BLK_0x28_SHAPE>>( aStream.
Position() );
1547 auto& data = block->GetData();
1549 data.m_Type = aStream.
ReadU8();
1551 data.m_Key = aStream.
ReadU32();
1552 block->SetKey( data.m_Key );
1553 data.m_Next = aStream.
ReadU32();
1554 block->SetNext( data.m_Next );
1555 data.m_Ptr1 = aStream.
ReadU32();
1556 data.m_Unknown1 = aStream.
ReadU32();
1558 ReadCond( aStream, aVer, data.m_Unknown2 );
1559 ReadCond( aStream, aVer, data.m_Unknown3 );
1561 data.m_Ptr2 = aStream.
ReadU32();
1562 data.m_Ptr3 = aStream.
ReadU32();
1563 data.m_FirstKeepoutPtr = aStream.
ReadU32();
1564 data.m_FirstSegmentPtr = aStream.
ReadU32();
1565 data.m_Unknown4 = aStream.
ReadU32();
1566 data.m_Unknown5 = aStream.
ReadU32();
1568 ReadCond( aStream, aVer, data.m_TablePtr );
1570 data.m_Ptr6 = aStream.
ReadU32();
1572 ReadCond( aStream, aVer, data.m_TablePtr_16x );
1574 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1576 data.m_Coords[i] = aStream.
ReadS32();
1585 auto block = std::make_unique<BLOCK<BLK_0x29_PIN>>( aStream.
Position() );
1587 auto& data = block->GetData();
1589 data.m_Type = aStream.
ReadU8();
1591 data.m_Key = aStream.
ReadU32();
1592 block->SetKey( data.m_Key );
1594 data.m_Ptr1 = aStream.
ReadU32();
1595 data.m_Ptr2 = aStream.
ReadU32();
1597 data.m_Null = aStream.
ReadU32();
1599 data.m_Ptr3 = aStream.
ReadU32();
1601 data.m_Coord1 = aStream.
ReadS32();
1602 data.m_Coord2 = aStream.
ReadS32();
1604 data.m_PtrPadstack = aStream.
ReadU32();
1606 data.m_Unknown1 = aStream.
ReadU32();
1608 data.m_PtrX30 = aStream.
ReadU32();
1610 data.m_Unknown2 = aStream.
ReadU32();
1611 data.m_Unknown3 = aStream.
ReadU32();
1612 data.m_Unknown4 = aStream.
ReadU32();
1620 auto block = std::make_unique<BLOCK<BLK_0x2A_LAYER_LIST>>( aStream.
Position() );
1622 auto& data = block->GetData();
1626 data.m_NumEntries = aStream.
ReadU16();
1628 ReadCond( aStream, aVer, data.m_Unknown );
1630 if( data.m_NonRefEntries.exists( aVer ) )
1632 data.m_NonRefEntries = std::vector<BLK_0x2A_LAYER_LIST::NONREF_ENTRY>();
1633 data.m_NonRefEntries->reserve( data.m_NumEntries );
1634 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1644 data.m_RefEntries = std::vector<BLK_0x2A_LAYER_LIST::REF_ENTRY>();
1645 data.m_RefEntries->reserve( data.m_NumEntries );
1646 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1656 data.m_Key = aStream.
ReadU32();
1657 block->SetKey( data.m_Key );
1665 auto block = std::make_unique<BLOCK<BLK_0x2B_FOOTPRINT_DEF>>( stream.
Position() );
1667 auto& data = block->GetData();
1671 data.m_Key = stream.
ReadU32();
1672 block->SetKey( data.m_Key );
1673 data.m_FpStrRef = stream.
ReadU32();
1674 data.m_Unknown1 = stream.
ReadU32();
1676 data.m_Next = stream.
ReadU32();
1677 block->SetNext( data.m_Next );
1678 data.m_FirstInstPtr = stream.
ReadU32();
1679 data.m_UnknownPtr3 = stream.
ReadU32();
1680 data.m_UnknownPtr4 = stream.
ReadU32();
1681 data.m_UnknownPtr5 = stream.
ReadU32();
1682 data.m_FieldsPtr = stream.
ReadU32();
1683 data.m_UnknownPtr6 = stream.
ReadU32();
1684 data.m_UnknownPtr7 = stream.
ReadU32();
1685 data.m_UnknownPtr8 = stream.
ReadU32();
1687 ReadCond( stream, aVer, data.m_Unknown2 );
1688 ReadCond( stream, aVer, data.m_Unknown3 );
1696 auto block = std::make_unique<BLOCK<BLK_0x2C_TABLE>>( aStream.
Position() );
1698 auto& data = block->GetData();
1700 data.m_Type = aStream.
ReadU8();
1701 data.m_SubType = aStream.
ReadU16();
1702 data.m_Key = aStream.
ReadU32();
1703 block->SetKey( data.m_Key );
1704 data.m_Next = aStream.
ReadU32();
1705 block->SetNext( data.m_Next );
1707 ReadCond( aStream, aVer, data.m_Unknown1 );
1708 ReadCond( aStream, aVer, data.m_Unknown2 );
1709 ReadCond( aStream, aVer, data.m_Unknown3 );
1711 data.m_StringPtr = aStream.
ReadU32();
1713 ReadCond( aStream, aVer, data.m_Unknown4 );
1715 data.m_Ptr1 = aStream.
ReadU32();
1716 data.m_Ptr2 = aStream.
ReadU32();
1717 data.m_Ptr3 = aStream.
ReadU32();
1719 data.m_Flags = aStream.
ReadU32();
1727 auto block = std::make_unique<BLOCK<BLK_0x2D_FOOTPRINT_INST>>( stream.
Position() );
1729 auto& data = block->GetData();
1731 data.m_UnknownByte1 = stream.
ReadU8();
1732 data.m_Layer = stream.
ReadU8();
1733 data.m_UnknownByte2 = stream.
ReadU8();
1735 data.m_Key = stream.
ReadU32();
1736 block->SetKey( data.m_Key );
1737 data.m_Next = stream.
ReadU32();
1738 block->SetNext( data.m_Next );
1740 ReadCond( stream, aVer, data.m_Unknown1 );
1742 ReadCond( stream, aVer, data.m_InstRef16x );
1744 data.m_Unknown2 = stream.
ReadU16();
1745 data.m_Unknown3 = stream.
ReadU16();
1747 ReadCond( stream, aVer, data.m_Unknown4 );
1749 data.m_Flags = stream.
ReadU32();
1751 data.m_Rotation = stream.
ReadU32();
1752 data.m_CoordX = stream.
ReadS32();
1753 data.m_CoordY = stream.
ReadS32();
1755 ReadCond( stream, aVer, data.m_InstRef );
1757 data.m_GraphicPtr = stream.
ReadU32();
1758 data.m_FirstPadPtr = stream.
ReadU32();
1759 data.m_TextPtr = stream.
ReadU32();
1761 data.m_AssemblyPtr = stream.
ReadU32();
1762 data.m_AreasPtr = stream.
ReadU32();
1763 data.m_UnknownPtr1 = stream.
ReadU32();
1764 data.m_UnknownPtr2 = stream.
ReadU32();
1772 auto block = std::make_unique<BLOCK<BLK_0x2E_CONNECTION>>( aStream.
Position() );
1774 auto& data = block->GetData();
1776 data.m_Type = aStream.
ReadU8();
1777 data.m_T2 = aStream.
ReadU16();
1778 data.m_Key = aStream.
ReadU32();
1779 block->SetKey( data.m_Key );
1780 data.m_Next = aStream.
ReadU32();
1781 block->SetNext( data.m_Next );
1782 data.m_NetAssignment = aStream.
ReadU32();
1783 data.m_Unknown1 = aStream.
ReadU32();
1784 data.m_CoordX = aStream.
ReadU32();
1785 data.m_CoordY = aStream.
ReadU32();
1786 data.m_Connection = aStream.
ReadU32();
1787 data.m_Unknown2 = aStream.
ReadU32();
1789 ReadCond( aStream, aVer, data.m_Unknown3 );
1797 auto block = std::make_unique<BLOCK<BLK_0x2F_UNKNOWN>>( aStream.
Position() );
1799 auto& data = block->GetData();
1801 data.m_Type = aStream.
ReadU8();
1802 data.m_T2 = aStream.
ReadU16();
1803 data.m_Key = aStream.
ReadU32();
1804 block->SetKey( data.m_Key );
1819 uint8_t alignment = aStream.
ReadU8();
1831 uint8_t reversal = aStream.
ReadU8();
1848 auto block = std::make_unique<BLOCK<BLK_0x30_STR_WRAPPER>>( aStream.
Position() );
1850 auto& data = block->GetData();
1852 data.m_Type = aStream.
ReadU8();
1854 data.m_Key = aStream.
ReadU32();
1855 block->SetKey( data.m_Key );
1856 data.m_Next = aStream.
ReadU32();
1857 block->SetNext( data.m_Next );
1859 ReadCond( aStream, aVer, data.m_Unknown1 );
1860 ReadCond( aStream, aVer, data.m_Unknown2 );
1862 if( data.m_Font.exists( aVer ) )
1867 ReadCond( aStream, aVer, data.m_Ptr1 );
1868 ReadCond( aStream, aVer, data.m_Unknown3 );
1870 data.m_StrGraphicPtr = aStream.
ReadU32();
1872 ReadCond( aStream, aVer, data.m_PtrGroup_17x );
1873 ReadCond( aStream, aVer, data.m_Unknown4 );
1875 if( data.m_Font16x.exists( aVer ) )
1880 ReadCond( aStream, aVer, data.m_Ptr2 );
1882 data.m_CoordsX = aStream.
ReadU32();
1883 data.m_CoordsY = aStream.
ReadU32();
1885 data.m_Unknown5 = aStream.
ReadU32();
1886 data.m_Rotation = aStream.
ReadU32();
1888 ReadCond( aStream, aVer, data.m_PtrGroup_16x );
1896 auto block = std::make_unique<BLOCK<BLK_0x31_SGRAPHIC>>( aStream.
Position() );
1898 auto& data = block->GetData();
1900 data.m_T = aStream.
ReadU8();
1903 const uint16_t layer = aStream.
ReadU16();
1918 data.m_Key = aStream.
ReadU32();
1919 block->SetKey( data.m_Key );
1920 data.m_StrGraphicWrapperPtr = aStream.
ReadU32();
1922 data.m_CoordsX = aStream.
ReadU32();
1923 data.m_CoordsY = aStream.
ReadU32();
1925 data.m_Unknown = aStream.
ReadU16();
1926 data.m_Len = aStream.
ReadU16();
1928 ReadCond( aStream, aVer, data.m_Un2 );
1938 auto block = std::make_unique<BLOCK<BLK_0x32_PLACED_PAD>>( aStream.
Position() );
1940 auto& data = block->GetData();
1942 data.m_Type = aStream.
ReadU8();
1944 data.m_Key = aStream.
ReadU32();
1945 block->SetKey( data.m_Key );
1946 data.m_Next = aStream.
ReadU32();
1947 block->SetNext( data.m_Next );
1948 data.m_NetPtr = aStream.
ReadU32();
1949 data.m_Flags = aStream.
ReadU32();
1951 ReadCond( aStream, aVer, data.m_Prev );
1953 data.m_NextInFp = aStream.
ReadU32();
1954 data.m_ParentFp = aStream.
ReadU32();
1955 data.m_Track = aStream.
ReadU32();
1956 data.m_PadPtr = aStream.
ReadU32();
1957 data.m_Ptr6 = aStream.
ReadU32();
1958 data.m_Ratline = aStream.
ReadU32();
1959 data.m_PtrPinNumber = aStream.
ReadU32();
1960 data.m_NextInCompInst = aStream.
ReadU32();
1962 ReadCond( aStream, aVer, data.m_Unknown2 );
1964 data.m_NameText = aStream.
ReadU32();
1965 data.m_Ptr11 = aStream.
ReadU32();
1967 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1969 data.m_Coords[i] = aStream.
ReadS32();
1978 auto block = std::make_unique<BLOCK<BLK_0x33_VIA>>( aStream.
Position() );
1980 auto& data = block->GetData();
1985 data.m_Key = aStream.
ReadU32();
1986 block->SetKey( data.m_Key );
1987 data.m_Next = aStream.
ReadU32();
1988 block->SetNext( data.m_Next );
1989 data.m_NetPtr = aStream.
ReadU32();
1990 data.m_Unknown2 = aStream.
ReadU32();
1992 ReadCond( aStream, aVer, data.m_Unknown3 );
1994 data.m_UnknownPtr1 = aStream.
ReadU32();
1996 ReadCond( aStream, aVer, data.m_UnknownPtr2 );
1998 data.m_CoordsX = aStream.
ReadS32();
1999 data.m_CoordsY = aStream.
ReadS32();
2001 data.m_Connection = aStream.
ReadU32();
2002 data.m_Padstack = aStream.
ReadU32();
2003 data.m_UnknownPtr5 = aStream.
ReadU32();
2004 data.m_UnknownPtr6 = aStream.
ReadU32();
2006 data.m_Unknown4 = aStream.
ReadU32();
2007 data.m_Unknown5 = aStream.
ReadU32();
2009 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
2011 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
2020 auto block = std::make_unique<BLOCK<BLK_0x34_KEEPOUT>>( aStream.
Position() );
2022 auto& data = block->GetData();
2024 data.m_T = aStream.
ReadU8();
2026 data.m_Key = aStream.
ReadU32();
2027 block->SetKey( data.m_Key );
2028 data.m_Next = aStream.
ReadU32();
2029 block->SetNext( data.m_Next );
2030 data.m_Ptr1 = aStream.
ReadU32();
2032 ReadCond( aStream, aVer, data.m_Unknown1 );
2034 data.m_Flags = aStream.
ReadU32();
2035 data.m_FirstSegmentPtr = aStream.
ReadU32();
2036 data.m_Ptr3 = aStream.
ReadU32();
2037 data.m_Unknown2 = aStream.
ReadU32();
2045 auto block = std::make_unique<BLOCK<BLK_0x35_FILE_REF>>( aStream.
Position() );
2047 auto& data = block->GetData();
2049 data.m_T2 = aStream.
ReadU8();
2050 data.m_T3 = aStream.
ReadU16();
2051 aStream.
ReadBytes( data.m_Content.data(), data.m_Content.size() );
2059 auto block = std::make_unique<BLOCK<BLK_0x36_DEF_TABLE>>( aStream.
Position() );
2061 auto& data = block->GetData();
2065 data.m_Code = aStream.
ReadU16();
2066 data.m_Key = aStream.
ReadU32();
2067 block->SetKey( data.m_Key );
2068 data.m_Next = aStream.
ReadU32();
2069 block->SetNext( data.m_Next );
2071 ReadCond( aStream, aVer, data.m_Unknown1 );
2073 data.m_NumItems = aStream.
ReadU32();
2074 data.m_Count = aStream.
ReadU32();
2075 data.m_LastIdx = aStream.
ReadU32();
2076 data.m_Unknown2 = aStream.
ReadU32();
2078 ReadCond( aStream, aVer, data.m_Unknown3 );
2080 if( data.m_NumItems > 1000000 )
2082 THROW_IO_ERRORF( wxT(
"Block 0x36 item count %u exceeds limit at offset %#010zx" ),
2087 if( data.m_Count > data.m_NumItems )
2089 THROW_IO_ERRORF( wxT(
"Block 0x36 filled count %u exceeds capacity %u at offset %#010zx" ),
2098 data.m_Items.reserve( data.m_Count );
2099 for( uint32_t i = 0; i < data.m_NumItems; ++i )
2101 const bool keep = i < data.m_Count;
2103 switch( data.m_Code )
2115 data.m_Items.emplace_back( std::move( item ) );
2129 data.m_Items.emplace_back( std::move( item ) );
2140 data.m_Items.emplace_back( std::move( item ) );
2155 data.m_Items.emplace_back( std::move( item ) );
2177 data.m_Items.emplace_back( std::move( item ) );
2185 data.m_Items.emplace_back( std::move( item ) );
2193 data.m_Items.emplace_back( std::move( item ) );
2201 data.m_Items.emplace_back( std::move( item ) );
2212 data.m_Items.emplace_back( std::move( item ) );
2223 data.m_Items.emplace_back( std::move( item ) );
2231 aStream.
Skip( 1052 );
2234 data.m_Items.emplace_back( std::move( item ) );
2238 default:
THROW_IO_ERRORF( wxT(
"Unknown substruct type %#02x in block 0x36" ), data.m_Code );
2248 auto block = std::make_unique<BLOCK<BLK_0x37_PTR_ARRAY>>( aStream.
Position() );
2250 auto& data = block->GetData();
2252 data.m_T = aStream.
ReadU8();
2253 data.m_T2 = aStream.
ReadU16();
2254 data.m_Key = aStream.
ReadU32();
2255 block->SetKey( data.m_Key );
2256 data.m_GroupPtr = aStream.
ReadU32();
2257 data.m_Next = aStream.
ReadU32();
2258 block->SetNext( data.m_Next );
2259 data.m_Capacity = aStream.
ReadU32();
2260 data.m_Count = aStream.
ReadU32();
2261 data.m_Unknown2 = aStream.
ReadU32();
2263 ReadCond( aStream, aVer, data.m_Unknown3 );
2273 auto block = std::make_unique<BLOCK<BLK_0x38_FILM>>( aStream.
Position() );
2275 auto& data = block->GetData();
2279 data.m_Key = aStream.
ReadU32();
2280 block->SetKey( data.m_Key );
2281 data.m_Next = aStream.
ReadU32();
2282 block->SetNext( data.m_Next );
2283 data.m_LayerList = aStream.
ReadU32();
2285 if( data.m_FilmName.exists( aVer ) )
2290 ReadCond( aStream, aVer, data.m_LayerNameStr );
2291 ReadCond( aStream, aVer, data.m_Unknown2 );
2293 for(
size_t i = 0; i < data.m_UnknownArray1.size(); ++i )
2295 data.m_UnknownArray1[i] = aStream.
ReadU32();
2298 ReadCond( aStream, aVer, data.m_Unknown3 );
2306 auto block = std::make_unique<BLOCK<BLK_0x39_FILM_LAYER_LIST>>( aStream.
Position() );
2308 auto& data = block->GetData();
2312 data.m_Key = aStream.
ReadU32();
2313 block->SetKey( data.m_Key );
2314 data.m_Parent = aStream.
ReadU32();
2315 data.m_Head = aStream.
ReadU32();
2317 for(
size_t i = 0; i < data.m_X.size(); ++i )
2319 data.m_X[i] = aStream.
ReadU16();
2328 auto block = std::make_unique<BLOCK<BLK_0x3A_FILM_LIST_NODE>>( aStream.
Position() );
2330 auto& data = block->GetData();
2335 data.m_Key = aStream.
ReadU32();
2336 block->SetKey( data.m_Key );
2337 data.m_Next = aStream.
ReadU32();
2338 block->SetNext( data.m_Next );
2339 data.m_Unknown = aStream.
ReadU32();
2341 ReadCond( aStream, aVer, data.m_Unknown1 );
2349 auto block = std::make_unique<BLOCK<BLK_0x3B_PROPERTY>>( aStream.
Position() );
2351 auto& data = block->GetData();
2353 data.m_T = aStream.
ReadU8();
2354 data.m_SubType = aStream.
ReadU16();
2355 data.m_Len = aStream.
ReadU32();
2360 data.m_Unknown1 = aStream.
ReadU32();
2361 data.m_Unknown2 = aStream.
ReadU32();
2363 ReadCond( aStream, aVer, data.m_Unknown3 );
2373 auto block = std::make_unique<BLOCK<BLK_0x3E>>( aStream.
Position() );
2375 auto& data = block->GetData();
2379 data.m_Key = aStream.
ReadU32();
2380 block->SetKey( data.m_Key );
2382 for( uint32_t& word : data.m_Unknown )
2391 auto block = std::make_unique<BLOCK<BLK_0x3C_KEY_LIST>>( aStream.
Position() );
2393 auto& data = block->GetData();
2395 data.m_T = aStream.
ReadU8();
2396 data.m_T2 = aStream.
ReadU16();
2397 data.m_Key = aStream.
ReadU32();
2398 block->SetKey( data.m_Key );
2400 ReadCond( aStream, aVer, data.m_Unknown );
2402 data.m_NumEntries = aStream.
ReadU32();
2404 if( data.m_NumEntries > 1000000 )
2406 THROW_IO_ERRORF( wxT(
"Block 0x3C entry count %u exceeds limit at offset %#010zx" ),
2411 data.m_Entries.reserve( data.m_NumEntries );
2413 for( uint32_t i = 0; i < data.m_NumEntries; ++i )
2414 data.m_Entries.push_back( aStream.
ReadU32() );
2424 uint8_t type = 0x00;
2427 aEndOfObjectsMarker =
true;
2431 std::unique_ptr<BLOCK_BASE> block;
2591 THROW_IO_ERRORF( wxT(
"Current offset %#010zx is at or past the expected end of block 0x27 at %#010zx" ),
2711 aEndOfObjectsMarker =
true;
2735 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
2739 const size_t offset =
m_stream.Position();
2742 wxASSERT_MSG( offset % 4 == 0,
2743 wxString::Format(
"Allegro object at %#010zx, offset not aligned to 4 bytes", offset ) );
2748 uint8_t blockTypeByte = 0;
2752 bool endOfObjectsMarker =
false;
2753 std::unique_ptr<BLOCK_BASE> block = blockParser.
ParseBlock( endOfObjectsMarker );
2755 if( endOfObjectsMarker )
2761 size_t scanPos =
m_stream.Position();
2762 uint8_t nextByte = 0;
2764 while(
m_stream.GetU8( nextByte ) && nextByte == 0x00 )
2767 if( nextByte > 0x00 && nextByte <= 0x3E )
2769 size_t blockStart = scanPos;
2771 if( blockStart % 4 != 0 )
2772 blockStart -= ( blockStart % 4 );
2777 uint8_t alignedByte = 0;
2782 if( alignedByte == 0x00 || alignedByte > 0x3E )
2786 wxString::Format(
"V18 zero gap from %#010zx to %#010zx, "
2787 "continuing at block type %#04x",
2788 offset, blockStart, nextByte ) );
2796 wxString::Format(
"End of objects marker (0x00) at index %zu, offset %#010zx",
2807 THROW_IO_ERRORF( wxT(
"Do not have parser for block index %zu type %#02x available at offset %#010zx" ),
2815 wxString::Format(
"Ending at unknown block, index %zu type %#04x at offset %#010zx",
2818 wxFAIL_MSG(
"Failed to create block" );
2825 wxString::Format(
"Added block %zu, type %#04x from %#010zx to %#010zx",
2843template <
typename T>
2846 if constexpr( std::is_same_v<T, FILE_HEADER::LINKED_LIST> )
2850 else if constexpr( VERSIONED_COND_FIELD<T> && std::is_same_v<typename T::value_type, FILE_HEADER::LINKED_LIST> )
2852 if( aLL.has_value() )
2860 std::unique_ptr<BRD_DB> board = std::make_unique<BRD_DB>();
2875 if( !board->m_Header )
2881 wxLogTrace(
traceAllegroParser,
"Header linked lists (ver=%#010x):", board->m_Header->m_Magic );
2883 dumpLL(
"V18_1", board->m_Header->m_LL_V18_1 );
2884 dumpLL(
"V18_2", board->m_Header->m_LL_V18_2 );
2885 dumpLL(
"V18_3", board->m_Header->m_LL_V18_3 );
2886 dumpLL(
"V18_4", board->m_Header->m_LL_V18_4 );
2887 dumpLL(
"V18_5", board->m_Header->m_LL_V18_5 );
2889 dumpLL(
"0x04", board->m_Header->m_LL_0x04 );
2890 dumpLL(
"0x06", board->m_Header->m_LL_0x06 );
2891 dumpLL(
"0x0C", board->m_Header->m_LL_0x0C );
2892 dumpLL(
"Shapes", board->m_Header->m_LL_Shapes );
2893 dumpLL(
"0x14", board->m_Header->m_LL_0x14 );
2894 dumpLL(
"0x1B_Nets", board->m_Header->m_LL_0x1B_Nets );
2895 dumpLL(
"0x1C", board->m_Header->m_LL_0x1C );
2896 dumpLL(
"0x24_0x28", board->m_Header->m_LL_0x24_0x28 );
2897 dumpLL(
"Unknown1", board->m_Header->m_LL_Unknown1 );
2898 dumpLL(
"0x2B", board->m_Header->m_LL_0x2B );
2899 dumpLL(
"0x03_0x30", board->m_Header->m_LL_0x03_0x30 );
2900 dumpLL(
"0x0A", board->m_Header->m_LL_0x0A );
2901 dumpLL(
"0x1D_0x1E_0x1F", board->m_Header->m_LL_0x1D_0x1E_0x1F );
2902 dumpLL(
"Unknown2", board->m_Header->m_LL_Unknown2 );
2903 dumpLL(
"0x38", board->m_Header->m_LL_0x38 );
2904 dumpLL(
"0x2C", board->m_Header->m_LL_0x2C );
2905 dumpLL(
"0x0C_2", board->m_Header->m_LL_0x0C_2 );
2906 dumpLL(
"Unknown3", board->m_Header->m_LL_Unknown3 );
2907 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_preV18 );
2908 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_V18 );
2909 dumpLL(
"0x36", board->m_Header->m_LL_0x36 );
2910 dumpLL(
"Unknown6", board->m_Header->m_LL_Unknown6 );
2911 dumpLL(
"0x0A_2", board->m_Header->m_LL_0x0A_2 );
2913 dumpLL(
"V18_6", board->m_Header->m_LL_V18_6 );
2919 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2920 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2922 if( board->m_Header )
2923 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2925 s += wxString::Format(
"File magic: Unknown\n" );
2934 wxString verStr( board->m_Header->m_AllegroVersion.data(), 60 );
2937 THROW_IO_ERRORF(
_(
"This file was created with %s, which uses a binary format that predates Allegro 16.0 "
2938 "and is not supported by this importer.\n\n"
2939 "To import this design, open it in Cadence Allegro PCB Editor version 16.0 or later "
2940 "and re-save, then import the resulting file." ), verStr );
2943 const uint32_t stringsCount = board->m_Header->GetStringsCount();
2944 board->ReserveCapacity( board->m_Header->m_ObjectCount, stringsCount,
m_stream.Size() );
2950 wxLogTrace(
traceAllegroPerf, wxT(
" ReadStringMap (%u strings): %.3f ms" ),
2951 stringsCount, parseTimer.
msecs(
true ) );
2955 wxLogTrace(
traceAllegroPerf, wxT(
" readObjects (%zu objects): %.3f ms" ),
2956 board->GetObjectCount(), parseTimer.
msecs(
true ) );
2961 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2962 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2964 if( board->m_Header )
2965 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2967 s += wxString::Format(
"File magic: Unknown\n" );
2973 board->ResolveAndValidate();
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x35(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x36(FILE_STREAM &aStream, FMT_VER aVer)
void dumpLL(const char *name, const T &aLL)
static FILE_HEADER::LINKED_LIST ReadLL(FILE_STREAM &aStream, FMT_VER aVer)
static PAD_TYPE decodePadType(uint8_t aVal)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x04_NET_ASSIGNMENT(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2C_TABLE(FILE_STREAM &aStream, FMT_VER aVer)
static void ReadStringMap(FILE_STREAM &stream, BRD_DB &aDb, uint32_t count)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1F(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x3A_FILM_LIST_NODE(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x3C(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x14(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x08(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x10(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1B_NET(FILE_STREAM &stream, FMT_VER aVer)
static const wxChar *const traceAllegroParserBlocks
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x0F(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x05_TRACK(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1D(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1C_PADSTACK(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x34_KEEPOUT(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x01_ARC(FILE_STREAM &aStream, FMT_VER aVer)
static BLK_0x30_STR_WRAPPER::TEXT_PROPERTIES ParseTextProps(FILE_STREAM &aStream)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x0D_PAD(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1E(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x20(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x0A_DRC(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x06(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x0E(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x1A(FILE_STREAM &aStream, FMT_VER aVer)
static void ReadArrayU32(FILE_STREAM &aStream, ARRAY &aArray)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x39_FILM_LAYER_LIST(FILE_STREAM &aStream, FMT_VER aVer)
static void ReadCond(FILE_STREAM &aStream, FMT_VER aFmtVer, COND_T &aField)
Read a single conditional field from the stream, if it exists at the current version.
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x09(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x38_FILM(FILE_STREAM &aStream, FMT_VER aVer)
static double ReadAllegroFloat(FILE_STREAM &aStream)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x24_RECT(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2E(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x03(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x12(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x15_16_17_SEGMENT(FILE_STREAM &aStream, FMT_VER aVer, uint8_t aType)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x31_SGRAPHIC(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x22(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x27(FILE_STREAM &aStream, FMT_VER aVer, size_t aEndOff)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2A(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2F(FILE_STREAM &aStream, FMT_VER aVer)
static LAYER_INFO ParseLayerInfo(FILE_STREAM &aStream)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x07(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x33_VIA(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x32_PLACED_PAD(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x37(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2B(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x2D(FILE_STREAM &stream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x21(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x23_RATLINE(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x28_SHAPE(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x11(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x26(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x3B(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x0C(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x29_PIN(FILE_STREAM &aStream, FMT_VER aVer)
static T ReadField(FILE_STREAM &aStream, FMT_VER aFmtVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x3E(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x30_STR_WRAPPER(FILE_STREAM &aStream, FMT_VER aVer)
The block parser is responsible for parsing individual blocks of data from the file stream.
std::unique_ptr< BLOCK_BASE > ParseBlock(bool &aEndOfObjectsMarker)
Parse one block from the stream, returning a BLOCK_BASE representing the raw data of the block.
const size_t m_x27_end
To parse an 0x27 block, we need to know where the end of the block is in the stream.
An Allegro board database representing the contents of a .brd (and presumably .dra) file.
std::unique_ptr< FILE_HEADER > m_Header
size_t GetObjectCount() const
void InsertBlock(std::unique_ptr< BLOCK_BASE > aBlock)
void AddString(uint32_t aKey, wxString &&aStr)
Stream that reads primitive types from a memory buffer containing Allegro .brd (or ....
void ReadBytes(void *aDest, size_t aSize)
Read a number of bytes from the stream into the destination buffer.
std::string ReadString(bool aRoundToNextU32)
std::string ReadStringFixed(size_t aLen, bool aRoundToNextU32)
PROGRESS_REPORTER * m_progressReporter
void readObjects(BRD_DB &aDb)
std::unique_ptr< BRD_DB > Parse()
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A small class to help profiling.
double msecs(bool aSinceLast=false)
Rate-limiter that fires at most once per interval.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
static const wxChar *const traceAllegroParser
Flag to enable debug output of Allegro parsing.
PAD_TYPE
The type of the padstack.
FMT_VER
The format of an Allegro file.
static const wxChar *const traceAllegroPerf
std::vector< uint32_t > m_Entries
std::vector< uint32_t > m_Entries
std::array< uint32_t, 20 > m_Entries
uint32_t m_Properties
Same layer flags as REF_ENTRY, stored after the 32 byte name.
TEXT_ALIGNMENT m_Alignment
COND_GE< FMT_VER::V_172, std::array< uint32_t, 8 > > m_Ys
uint32_t m_CharacterSpace
COND_GE_LT< FMT_VER::V_174, FMT_VER::V_190, uint32_t > m_Unknown2
std::array< uint32_t, 14 > m_Xs
COND_GE< FMT_VER::V_172, std::array< uint32_t, 2 > > m_Zs
COND_GE< FMT_VER::V_164, std::array< uint32_t, 3 > > m_Ys
COND_GE< FMT_VER::V_172, std::string > m_Str
COND_GE< FMT_VER::V_174, uint32_t > m_Unknown1
COND_LT< FMT_VER::V_172, std::string > m_Str16x
std::array< uint8_t, 28 > m_Unknown
COND_GE< FMT_VER::V_175, uint32_t > m_Unknown2
COND_LT< FMT_VER::V_172, std::array< uint32_t, 50 > > m_Unknown2
std::array< uint8_t, 1016 > m_Unknown
std::array< uint8_t, 232 > m_Unknown
std::array< uint8_t, 200 > m_Unknown
std::array< uint32_t, 3 > m_Ptrs
std::array< uint8_t, 108 > m_Unknown
COND_GE< FMT_VER::V_180, uint32_t > m_Unknown2
Substruct in a padstack object.
A type that is always false.
wxString result
Test unit parsing edge cases and error handling.