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;
178 uint32_t majorVer = ( aMagic >> 16 ) & 0xFFFF;
180 if( majorVer <= 0x0012 )
185 THROW_IO_ERROR( wxString::Format(
"Unknown Allegro file version %#010x (rev %d)", aMagic, majorVer - 3 ) );
191 auto header = std::make_unique<ALLEGRO::FILE_HEADER>();
192 const size_t headerStartPos =
m_stream.Position();
194 uint32_t fileMagic =
m_stream.ReadU32();
197 header->m_Magic = fileMagic;
264 wxASSERT(
m_stream.Position() - headerStartPos == 0xF8 );
266 wxASSERT(
m_stream.Position() - headerStartPos == 0x124 );
289 THROW_IO_ERROR( wxString::Format(
"Unknown board units %d", units ) );
314 for(
size_t i = 0; i <
header->m_LayerMap.size(); ++i )
321 header->GetStringsCount() );
331 static constexpr size_t STRING_TABLE_OFFSET = 0x1200;
333 stream.
Seek( STRING_TABLE_OFFSET );
335 for( uint32_t i = 0; i < count; ++i )
337 uint32_t
id = stream.
ReadU32();
347 uint8_t classCode = aStream.
ReadU8();
348 uint8_t subclassCode = aStream.
ReadU8();
353 .m_Class = classCode,
354 .m_Subclass = subclassCode,
361 auto block = std::make_unique<BLOCK<BLK_0x01_ARC>>( aStream.
Position() );
363 auto& data = block->GetData();
367 data.m_UnknownByte = aStream.
ReadU8();
368 data.m_SubType = aStream.
ReadU8();
369 data.m_Key = aStream.
ReadU32();
370 block->SetKey( data.m_Key );
371 data.m_Next = aStream.
ReadU32();
372 block->SetNext( data.m_Next );
373 data.m_Parent = aStream.
ReadU32();
374 data.m_Unknown1 = aStream.
ReadU32();
376 ReadCond( aStream, aVer, data.m_Unknown6 );
378 data.m_Width = aStream.
ReadU32();
380 data.m_StartX = aStream.
ReadS32();
381 data.m_StartY = aStream.
ReadS32();
382 data.m_EndX = aStream.
ReadS32();
383 data.m_EndY = aStream.
ReadS32();
389 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
391 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
400 auto block = std::make_unique<BLOCK<BLK_0x03_FIELD>>( aStream.
Position() );
402 auto& data = block->GetData();
406 data.m_Hdr1 = aStream.
ReadU16();
407 data.m_Key = aStream.
ReadU32();
408 block->SetKey( data.m_Key );
409 data.m_Next = aStream.
ReadU32();
410 block->SetNext( data.m_Next );
412 ReadCond( aStream, aVer, data.m_Unknown1 );
414 data.m_SubType = aStream.
ReadU8();
415 data.m_Hdr2 = aStream.
ReadU8();
416 data.m_Size = aStream.
ReadU16();
418 ReadCond( aStream, aVer, data.m_Unknown2 );
423 switch( data.m_SubType )
433 data.m_Substruct = aStream.
ReadU32();
438 data.m_Substruct = std::array<uint32_t, 2>{
464 "Block 0x03 subtype 0x6C entry count %u exceeds limit at offset %#010zx",
474 data.m_Substruct = std::move( sub );
485 const size_t numEntries = ( sub.
m_X1 + 4 * sub.
m_X0 );
487 for(
size_t i = 0; i < numEntries; ++i )
491 data.m_Substruct = std::move( sub );
497 for(
size_t i = 0; i < sub.
m_Entries.size(); ++i )
501 data.m_Substruct = std::move( sub );
506 if( data.m_Size == 4 )
508 data.m_Substruct = aStream.
ReadU32();
510 else if( data.m_Size == 8 )
512 std::array<uint32_t, 2> sub;
515 data.m_Substruct = std::move( sub );
520 wxString::Format(
"Unknown substruct type %#02x with size %d", data.m_SubType, data.m_Size ) );
532 auto block = std::make_unique<BLOCK<BLK_0x04_NET_ASSIGNMENT>>( aStream.
Position() );
534 auto& data = block->GetData();
536 data.m_Type = aStream.
ReadU8();
538 data.m_Key = aStream.
ReadU32();
539 block->SetKey( data.m_Key );
540 data.m_Next = aStream.
ReadU32();
541 block->SetNext( data.m_Next );
542 data.m_Net = aStream.
ReadU32();
543 data.m_ConnItem = aStream.
ReadU32();
545 ReadCond( aStream, aVer, data.m_Unknown );
553 auto block = std::make_unique<BLOCK<BLK_0x05_TRACK>>( aStream.
Position() );
555 auto& data = block->GetData();
560 data.m_Key = aStream.
ReadU32();
561 block->SetKey( data.m_Key );
562 data.m_Next = aStream.
ReadU32();
563 block->SetNext( data.m_Next );
564 data.m_NetAssignment = aStream.
ReadU32();
565 data.m_UnknownPtr1 = aStream.
ReadU32();
566 data.m_Unknown2 = aStream.
ReadU32();
567 data.m_Unknown3 = aStream.
ReadU32();
568 data.m_UnknownPtr2a = aStream.
ReadU32();
569 data.m_UnknownPtr2b = aStream.
ReadU32();
570 data.m_Unknown4 = aStream.
ReadU32();
571 data.m_UnknownPtr3a = aStream.
ReadU32();
572 data.m_UnknownPtr3b = aStream.
ReadU32();
574 ReadCond( aStream, aVer, data.m_Unknown5a );
575 ReadCond( aStream, aVer, data.m_Unknown5b );
577 data.m_FirstSegPtr = aStream.
ReadU32();
578 data.m_UnknownPtr5 = aStream.
ReadU32();
579 data.m_Unknown6 = aStream.
ReadU32();
587 auto block = std::make_unique<BLOCK<BLK_0x06_COMPONENT>>( stream.
Position() );
589 auto& data = block->GetData();
594 block->SetKey( data.m_Key );
595 data.m_Next = stream.
ReadU32();
596 block->SetNext( data.m_Next );
597 data.m_CompDeviceType = stream.
ReadU32();
598 data.m_SymbolName = stream.
ReadU32();
599 data.m_FirstInstPtr = stream.
ReadU32();
600 data.m_PtrFunctionSlot = stream.
ReadU32();
601 data.m_PtrPinNumber = stream.
ReadU32();
602 data.m_Fields = stream.
ReadU32();
604 ReadCond( stream, aVer, data.m_Unknown1 );
612 auto block = std::make_unique<BLOCK<BLK_0x07_COMPONENT_INST>>( stream.
Position() );
614 auto& data = block->GetData();
619 block->SetKey( data.m_Key );
620 data.m_Next = stream.
ReadU32();
621 block->SetNext( data.m_Next );
623 ReadCond( stream, aVer, data.m_UnknownPtr1 );
624 ReadCond( stream, aVer, data.m_Unknown2 );
625 ReadCond( stream, aVer, data.m_Unknown3 );
627 data.m_FpInstPtr = stream.
ReadU32();
629 ReadCond( stream, aVer, data.m_Unknown4 );
631 data.m_RefDesStrPtr = stream.
ReadU32();
632 data.m_FunctionInstPtr = stream.
ReadU32();
633 data.m_X03Ptr = stream.
ReadU32();
634 data.m_Unknown5 = stream.
ReadU32();
635 data.m_FirstPadPtr = stream.
ReadU32();
643 auto block = std::make_unique<BLOCK<BLK_0x08_PIN_NUMBER>>( aStream.
Position() );
645 auto& data = block->GetData();
647 data.m_Type = aStream.
ReadU8();
649 data.m_Key = aStream.
ReadU32();
650 block->SetKey( data.m_Key );
652 ReadCond( aStream, aVer, data.m_Previous );
653 ReadCond( aStream, aVer, data.m_StrPtr16x );
655 data.m_Next = aStream.
ReadU32();
656 block->SetNext( data.m_Next );
658 ReadCond( aStream, aVer, data.m_StrPtr );
660 data.m_PinNamePtr = aStream.
ReadU32();
662 ReadCond( aStream, aVer, data.m_Unknown1 );
664 data.m_Ptr4 = aStream.
ReadU32();
672 auto block = std::make_unique<BLOCK<BLK_0x09_FILL_LINK>>( aStream.
Position() );
674 auto& data = block->GetData();
678 data.m_Key = aStream.
ReadU32();
679 block->SetKey( data.m_Key );
681 for(
size_t i = 0; i < data.m_UnknownArray.size(); ++i )
683 data.m_UnknownArray[i] = aStream.
ReadU32();
686 ReadCond( aStream, aVer, data.m_Unknown1 );
688 data.m_UnknownPtr1 = aStream.
ReadU32();
689 data.m_UnknownPtr2 = aStream.
ReadU32();
690 data.m_Unknown2 = aStream.
ReadU32();
691 data.m_UnknownPtr3 = aStream.
ReadU32();
692 data.m_UnknownPtr4 = aStream.
ReadU32();
694 ReadCond( aStream, aVer, data.m_Unknown3 );
702 auto block = std::make_unique<BLOCK<BLK_0x0A_DRC>>( aStream.
Position() );
704 auto& data = block->GetData();
706 data.m_T = aStream.
ReadU8();
708 data.m_Key = aStream.
ReadU32();
709 block->SetKey( data.m_Key );
710 data.m_Next = aStream.
ReadU32();
711 block->SetNext( data.m_Next );
712 data.m_Unknown1 = aStream.
ReadU32();
714 ReadCond( aStream, aVer, data.m_Unknown2 );
716 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
718 data.m_Coords[i] = aStream.
ReadS32();
724 ReadCond( aStream, aVer, data.m_Unknown6 );
732 auto block = std::make_unique<BLOCK<BLK_0x0C_PIN_DEF>>( aStream.
Position() );
734 auto& data = block->GetData();
736 data.m_T = aStream.
ReadU8();
739 data.m_Key = aStream.
ReadU32();
740 block->SetKey( data.m_Key );
741 data.m_Next = aStream.
ReadU32();
742 block->SetNext( data.m_Next );
744 data.m_Unknown1 = aStream.
ReadU32();
745 data.m_Unknown2 = aStream.
ReadU32();
748 ReadCond( aStream, aVer, data.m_Shape );
749 ReadCond( aStream, aVer, data.m_DrillChar );
750 ReadCond( aStream, aVer, data.m_UnknownPadding );
753 ReadCond( aStream, aVer, data.m_Shape16x );
754 ReadCond( aStream, aVer, data.m_DrillChars );
755 ReadCond( aStream, aVer, data.m_Unknown_16x );
757 data.m_Unknown4 = aStream.
ReadU32();
758 ReadCond( aStream, aVer, data.m_Unknown5 );
760 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
762 data.m_Coords[i] = aStream.
ReadS32();
765 for(
size_t i = 0; i < data.m_Size.size(); ++i )
767 data.m_Size[i] = aStream.
ReadS32();
770 data.m_GroupPtr = aStream.
ReadU32();
771 data.m_Unknown6 = aStream.
ReadU32();
772 data.m_Unknown7 = aStream.
ReadU32();
774 ReadCond( aStream, aVer, data.m_Unknown8 );
782 auto block = std::make_unique<BLOCK<BLK_0x0D_PAD>>( aStream.
Position() );
784 auto& data = block->GetData();
788 data.m_Key = aStream.
ReadU32();
789 block->SetKey( data.m_Key );
790 data.m_NameStrId = aStream.
ReadU32();
791 data.m_Next = aStream.
ReadU32();
792 block->SetNext( data.m_Next );
794 ReadCond( aStream, aVer, data.m_Unknown1 );
796 data.m_CoordsX = aStream.
ReadS32();
797 data.m_CoordsY = aStream.
ReadS32();
799 data.m_PadStack = aStream.
ReadU32();
800 data.m_Unknown2 = aStream.
ReadU32();
802 ReadCond( aStream, aVer, data.m_Unknown3 );
804 data.m_Flags = aStream.
ReadU32();
805 data.m_Rotation = aStream.
ReadU32();
813 auto block = std::make_unique<BLOCK<BLK_0x0E_RECT>>( aStream.
Position() );
815 auto& data = block->GetData();
817 data.m_T = aStream.
ReadU8();
819 data.m_Key = aStream.
ReadU32();
820 block->SetKey( data.m_Key );
821 data.m_Next = aStream.
ReadU32();
822 block->SetNext( data.m_Next );
823 data.m_FpPtr = aStream.
ReadU32();
825 data.m_Unknown1 = aStream.
ReadU32();
826 data.m_Unknown2 = aStream.
ReadU32();
827 data.m_Unknown3 = aStream.
ReadU32();
829 ReadCond( aStream, aVer, data.m_Unknown4 );
830 ReadCond( aStream, aVer, data.m_Unknown5 );
832 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
834 data.m_Coords[i] = aStream.
ReadS32();
837 for(
size_t i = 0; i < data.m_UnknownArr.size(); ++i )
839 data.m_UnknownArr[i] = aStream.
ReadU32();
842 data.m_Rotation = aStream.
ReadU32();
850 auto block = std::make_unique<BLOCK<BLK_0x0F_FUNCTION_SLOT>>( stream.
Position() );
852 auto& data = block->GetData();
857 block->SetKey( data.m_Key );
858 data.m_SlotName = stream.
ReadU32();
860 ReadCond( stream, aVer, data.m_Unknown1 );
862 stream.
ReadBytes( data.m_CompDeviceType.data(), data.m_CompDeviceType.size() );
864 ReadCond( stream, aVer, data.m_Next );
865 block->SetNext( data.m_Next.value_or( 0 ) );
867 data.m_Ptr0x06 = stream.
ReadU32();
868 data.m_Ptr0x11 = stream.
ReadU32();
869 data.m_Unknown2 = stream.
ReadU32();
877 auto block = std::make_unique<BLOCK<BLK_0x10_FUNCTION_INST>>( stream.
Position() );
879 auto& data = block->GetData();
884 block->SetKey( data.m_Key );
886 ReadCond( stream, aVer, data.m_Unknown1 );
887 data.m_ComponentInstPtr = stream.
ReadU32();
888 ReadCond( stream, aVer, data.m_Unknown2 );
889 data.m_PtrX12 = stream.
ReadU32();
890 data.m_Unknown3 = stream.
ReadU32();
891 data.m_FunctionName = stream.
ReadU32();
892 data.m_Slots = stream.
ReadU32();
893 data.m_Fields = stream.
ReadU32();
901 auto block = std::make_unique<BLOCK<BLK_0x11_PIN_NAME>>( aStream.
Position() );
903 auto& data = block->GetData();
905 data.m_Type = aStream.
ReadU8();
907 data.m_Key = aStream.
ReadU32();
908 block->SetKey( data.m_Key );
909 data.m_PinNameStrPtr = aStream.
ReadU32();
910 data.m_Next = aStream.
ReadU32();
911 block->SetNext( data.m_Next );
912 data.m_PinNumberPtr = aStream.
ReadU32();
913 data.m_Unknown1 = aStream.
ReadU32();
915 ReadCond( aStream, aVer, data.m_Unknown2 );
923 auto block = std::make_unique<BLOCK<BLK_0x12_XREF>>( aStream.
Position() );
925 auto& data = block->GetData();
927 data.m_Type = aStream.
ReadU8();
929 data.m_Key = aStream.
ReadU32();
930 block->SetKey( data.m_Key );
931 data.m_Ptr1 = aStream.
ReadU32();
932 data.m_Ptr2 = aStream.
ReadU32();
933 data.m_Ptr3 = aStream.
ReadU32();
934 data.m_Unknown1 = aStream.
ReadU32();
936 ReadCond( aStream, aVer, data.m_Unknown2 );
937 ReadCond( aStream, aVer, data.m_Unknown3 );
945 auto block = std::make_unique<BLOCK<BLK_0x14_GRAPHIC>>( aStream.
Position() );
947 auto& data = block->GetData();
949 data.m_Type = aStream.
ReadU8();
951 data.m_Key = aStream.
ReadU32();
952 block->SetKey( data.m_Key );
953 data.m_Next = aStream.
ReadU32();
954 block->SetNext( data.m_Next );
955 data.m_Parent = aStream.
ReadU32();
956 data.m_Flags = aStream.
ReadU32();
958 ReadCond( aStream, aVer, data.m_Unknown2 );
960 data.m_SegmentPtr = aStream.
ReadU32();
961 data.m_Ptr0x03 = aStream.
ReadU32();
962 data.m_Ptr0x26 = aStream.
ReadU32();
970 auto block = std::make_unique<BLOCK<BLK_0x15_16_17_SEGMENT>>( aType, aStream.
Position() );
972 auto& data = block->GetData();
976 data.m_Key = aStream.
ReadU32();
977 block->SetKey( data.m_Key );
978 data.m_Next = aStream.
ReadU32();
979 block->SetNext( data.m_Next );
980 data.m_Parent = aStream.
ReadU32();
981 data.m_Flags = aStream.
ReadU32();
983 ReadCond( aStream, aVer, data.m_Unknown2 );
985 data.m_Width = aStream.
ReadU32();
987 data.m_StartX = aStream.
ReadS32();
988 data.m_StartY = aStream.
ReadS32();
989 data.m_EndX = aStream.
ReadS32();
990 data.m_EndY = aStream.
ReadS32();
998 auto block = std::make_unique<BLOCK<BLK_0x1B_NET>>( stream.
Position() );
1000 auto& data = block->GetData();
1004 data.m_Key = stream.
ReadU32();
1005 block->SetKey( data.m_Key );
1006 data.m_Next = stream.
ReadU32();
1007 block->SetNext( data.m_Next );
1008 data.m_NetName = stream.
ReadU32();
1009 data.m_Unknown1 = stream.
ReadU32();
1011 ReadCond( stream, aVer, data.m_Unknown2 );
1013 data.m_Type = stream.
ReadU32();
1014 data.m_Assignment = stream.
ReadU32();
1015 data.m_Ratline = stream.
ReadU32();
1016 data.m_FieldsPtr = stream.
ReadU32();
1017 data.m_MatchGroupPtr = stream.
ReadU32();
1018 data.m_ModelPtr = stream.
ReadU32();
1019 data.m_UnknownPtr4 = stream.
ReadU32();
1020 data.m_UnknownPtr5 = stream.
ReadU32();
1021 data.m_UnknownPtr6 = stream.
ReadU32();
1030 switch( (aVal & 0xF0) )
1047 THROW_IO_ERROR( wxString::Format(
"Unknown padstack type 0x%x", aVal ) );
1055 auto block = std::make_unique<BLOCK<BLK_0x1C_PADSTACK>>( aStream.
Position() );
1057 auto& data = block->GetData();
1059 data.m_UnknownByte1 = aStream.
ReadU8();
1060 data.m_N = aStream.
ReadU8();
1061 data.m_UnknownByte2 = aStream.
ReadU8();
1063 data.m_Key = aStream.
ReadU32();
1064 block->SetKey( data.m_Key );
1065 data.m_Next = aStream.
ReadU32();
1066 block->SetNext( data.m_Next );
1067 data.m_PadStr = aStream.
ReadU32();
1110 uint8_t padTypeAndA = aStream.
ReadU8();
1112 hdr.
m_A = ( padTypeAndA & 0x0F );
1152 static const uint16_t MAX_LAYER_COUNT = 256;
1153 if( data.GetLayerCount() > MAX_LAYER_COUNT )
1154 throw std::runtime_error(
"Layer count exceeds maximum of " + std::to_string( MAX_LAYER_COUNT ) );
1158 data.m_NumFixedCompEntries = 10;
1160 data.m_NumFixedCompEntries = 11;
1162 data.m_NumFixedCompEntries = 21;
1167 const size_t nComps = data.m_NumFixedCompEntries + ( data.GetLayerCount() * data.m_NumCompsPerLayer );
1169 data.m_Components.reserve( nComps );
1170 for(
size_t i = 0; i < nComps; ++i )
1200 const size_t nElems = data.m_N * ( ( aVer <
FMT_VER::V_172 ) ? 8 : 10 );
1202 data.m_UnknownArrN.reserve( nElems );
1203 for(
size_t i = 0; i < nElems; ++i )
1205 data.m_UnknownArrN.push_back( aStream.
ReadU32() );
1215 auto block = std::make_unique<BLOCK<BLK_0x1D_CONSTRAINT_SET>>( aStream.
Position() );
1217 auto& data = block->GetData();
1221 data.m_Key = aStream.
ReadU32();
1222 block->SetKey( data.m_Key );
1223 data.m_Next = aStream.
ReadU32();
1224 block->SetNext( data.m_Next );
1225 data.m_NameStrKey = aStream.
ReadU32();
1226 data.m_FieldPtr = aStream.
ReadU32();
1228 data.m_SizeA = aStream.
ReadU16();
1229 data.m_SizeB = aStream.
ReadU16();
1231 data.m_DataB.resize( data.m_SizeB );
1233 for(
auto& item : data.m_DataB )
1234 aStream.
ReadBytes( item.data(), item.size() );
1236 data.m_DataA.resize( data.m_SizeA );
1238 for(
auto& item : data.m_DataA )
1239 aStream.
ReadBytes( item.data(), item.size() );
1241 ReadCond( aStream, aVer, data.m_Unknown4 );
1249 auto block = std::make_unique<BLOCK<BLK_0x1E_SI_MODEL>>( aStream.
Position() );
1251 auto& data = block->GetData();
1253 data.m_Type = aStream.
ReadU8();
1254 data.m_T2 = aStream.
ReadU16();
1255 data.m_Key = aStream.
ReadU32();
1256 block->SetKey( data.m_Key );
1257 data.m_Next = aStream.
ReadU32();
1258 block->SetNext( data.m_Next );
1260 ReadCond( aStream, aVer, data.m_Unknown2 );
1261 ReadCond( aStream, aVer, data.m_Unknown3 );
1263 data.m_StrPtr = aStream.
ReadU32();
1264 data.m_Size = aStream.
ReadU32();
1268 ReadCond( aStream, aVer, data.m_Unknown4 );
1276 auto block = std::make_unique<BLOCK<BLK_0x1F_PADSTACK_DIM>>( aStream.
Position() );
1278 auto& data = block->GetData();
1282 data.m_Key = aStream.
ReadU32();
1283 block->SetKey( data.m_Key );
1285 data.m_Next = aStream.
ReadU32();
1286 block->SetNext( data.m_Next );
1287 data.m_Unknown2 = aStream.
ReadU32();
1288 data.m_Unknown3 = aStream.
ReadU32();
1289 data.m_Unknown4 = aStream.
ReadU32();
1290 data.m_Unknown5 = aStream.
ReadU16();
1292 data.m_Size = aStream.
ReadU16();
1294 size_t substructSize = 0;
1296 substructSize = data.m_Size * 384 + 8;
1298 substructSize = data.m_Size * 280 + 8;
1300 substructSize = data.m_Size * 280 + 4;
1302 substructSize = data.m_Size * 240 + 4;
1304 data.m_Substruct.resize( substructSize );
1305 aStream.
ReadBytes( data.m_Substruct.data(), substructSize );
1313 auto block = std::make_unique<BLOCK<BLK_0x20_UNKNOWN>>( aStream.
Position() );
1315 auto& data = block->GetData();
1317 data.m_Type = aStream.
ReadU8();
1319 data.m_Key = aStream.
ReadU32();
1320 block->SetKey( data.m_Key );
1321 data.m_Next = aStream.
ReadU32();
1322 block->SetNext( data.m_Next );
1325 ReadCond( aStream, aVer, data.m_UnknownArray2 );
1333 auto block = std::make_unique<BLOCK<BLK_0x21_BLOB>>( aStream.
Position() );
1335 auto& data = block->GetData();
1337 data.m_Type = aStream.
ReadU8();
1340 data.m_Size = aStream.
ReadU32();
1342 if( data.m_Size < 12 )
1344 THROW_IO_ERROR( wxString::Format(
"Block 0x21 size %u too small (minimum 12) at offset %#010zx",
1345 data.m_Size, aStream.
Position() ) );
1348 data.m_Key = aStream.
ReadU32();
1349 block->SetKey( data.m_Key );
1351 const size_t nBytes = data.m_Size - 12;
1352 data.m_Data.resize( nBytes );
1353 aStream.
ReadBytes( data.m_Data.data(), nBytes );
1361 auto block = std::make_unique<BLOCK<BLK_0x22_UNKNOWN>>( aStream.
Position() );
1363 auto& data = block->GetData();
1365 data.m_Type = aStream.
ReadU8();
1366 data.m_T2 = aStream.
ReadU16();
1367 data.m_Key = aStream.
ReadU32();
1368 block->SetKey( data.m_Key );
1370 ReadCond( aStream, aVer, data.m_Unknown1 );
1380 auto block = std::make_unique<BLOCK<BLK_0x23_RATLINE>>( aStream.
Position() );
1382 auto& data = block->GetData();
1384 data.m_Type = aStream.
ReadU8();
1386 data.m_Key = aStream.
ReadU32();
1387 block->SetKey( data.m_Key );
1388 data.m_Next = aStream.
ReadU32();
1389 block->SetNext( data.m_Next );
1393 data.m_Ptr1 = aStream.
ReadU32();
1394 data.m_Ptr2 = aStream.
ReadU32();
1395 data.m_Ptr3 = aStream.
ReadU32();
1397 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1399 data.m_Coords[i] = aStream.
ReadS32();
1404 ReadCond( aStream, aVer, data.m_Unknown2 );
1405 ReadCond( aStream, aVer, data.m_Unknown3 );
1413 auto block = std::make_unique<BLOCK<BLK_0x24_RECT>>( aStream.
Position() );
1415 auto& data = block->GetData();
1417 data.m_Type = aStream.
ReadU8();
1419 data.m_Key = aStream.
ReadU32();
1420 block->SetKey( data.m_Key );
1421 data.m_Next = aStream.
ReadU32();
1422 block->SetNext( data.m_Next );
1423 data.m_Parent = aStream.
ReadU32();
1424 data.m_Unknown1 = aStream.
ReadU32();
1426 ReadCond( aStream, aVer, data.m_Unknown2 );
1428 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1430 data.m_Coords[i] = aStream.
ReadS32();
1433 data.m_Ptr2 = aStream.
ReadU32();
1435 data.m_Unknown3 = aStream.
ReadU32();
1436 data.m_Unknown4 = aStream.
ReadU32();
1437 data.m_Rotation = aStream.
ReadU32();
1445 auto block = std::make_unique<BLOCK<BLK_0x26_MATCH_GROUP>>( aStream.
Position() );
1447 auto& data = block->GetData();
1449 data.m_Type = aStream.
ReadU8();
1451 data.m_Key = aStream.
ReadU32();
1452 block->SetKey( data.m_Key );
1453 data.m_MemberPtr = aStream.
ReadU32();
1455 ReadCond( aStream, aVer, data.m_Unknown1 );
1457 data.m_GroupPtr = aStream.
ReadU32();
1458 data.m_ConstPtr = aStream.
ReadU32();
1460 ReadCond( aStream, aVer, data.m_Unknown2 );
1468 auto block = std::make_unique<BLOCK<BLK_0x27_CSTRMGR_XREF>>( aStream.
Position() );
1470 auto& data = block->GetData();
1472 const size_t totalBytes = aEndOff - 1 - aStream.
Position();
1475 constexpr size_t kPadding = 3;
1477 if( totalBytes <= kPadding )
1479 aStream.
Skip( totalBytes );
1483 aStream.
Skip( kPadding );
1485 const size_t payloadBytes = totalBytes - kPadding;
1486 const size_t numValues = payloadBytes / 4;
1487 const size_t remainder = payloadBytes % 4;
1489 data.m_Refs.resize( numValues );
1491 for(
size_t i = 0; i < numValues; i++ )
1492 data.m_Refs[i] = aStream.
ReadU32();
1495 aStream.
Skip( remainder );
1503 auto block = std::make_unique<BLOCK<BLK_0x28_SHAPE>>( aStream.
Position() );
1505 auto& data = block->GetData();
1507 data.m_Type = aStream.
ReadU8();
1509 data.m_Key = aStream.
ReadU32();
1510 block->SetKey( data.m_Key );
1511 data.m_Next = aStream.
ReadU32();
1512 block->SetNext( data.m_Next );
1513 data.m_Ptr1 = aStream.
ReadU32();
1514 data.m_Unknown1 = aStream.
ReadU32();
1516 ReadCond( aStream, aVer, data.m_Unknown2 );
1517 ReadCond( aStream, aVer, data.m_Unknown3 );
1519 data.m_Ptr2 = aStream.
ReadU32();
1520 data.m_Ptr3 = aStream.
ReadU32();
1521 data.m_FirstKeepoutPtr = aStream.
ReadU32();
1522 data.m_FirstSegmentPtr = aStream.
ReadU32();
1523 data.m_Unknown4 = aStream.
ReadU32();
1524 data.m_Unknown5 = aStream.
ReadU32();
1526 ReadCond( aStream, aVer, data.m_TablePtr );
1528 data.m_Ptr6 = aStream.
ReadU32();
1530 ReadCond( aStream, aVer, data.m_TablePtr_16x );
1532 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1534 data.m_Coords[i] = aStream.
ReadS32();
1543 auto block = std::make_unique<BLOCK<BLK_0x29_PIN>>( aStream.
Position() );
1545 auto& data = block->GetData();
1547 data.m_Type = aStream.
ReadU8();
1549 data.m_Key = aStream.
ReadU32();
1550 block->SetKey( data.m_Key );
1552 data.m_Ptr1 = aStream.
ReadU32();
1553 data.m_Ptr2 = aStream.
ReadU32();
1555 data.m_Null = aStream.
ReadU32();
1557 data.m_Ptr3 = aStream.
ReadU32();
1559 data.m_Coord1 = aStream.
ReadS32();
1560 data.m_Coord2 = aStream.
ReadS32();
1562 data.m_PtrPadstack = aStream.
ReadU32();
1564 data.m_Unknown1 = aStream.
ReadU32();
1566 data.m_PtrX30 = aStream.
ReadU32();
1568 data.m_Unknown2 = aStream.
ReadU32();
1569 data.m_Unknown3 = aStream.
ReadU32();
1570 data.m_Unknown4 = aStream.
ReadU32();
1578 auto block = std::make_unique<BLOCK<BLK_0x2A_LAYER_LIST>>( aStream.
Position() );
1580 auto& data = block->GetData();
1584 data.m_NumEntries = aStream.
ReadU16();
1586 ReadCond( aStream, aVer, data.m_Unknown );
1588 if( data.m_NonRefEntries.exists( aVer ) )
1590 data.m_NonRefEntries = std::vector<BLK_0x2A_LAYER_LIST::NONREF_ENTRY>();
1591 data.m_NonRefEntries->reserve( data.m_NumEntries );
1592 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1601 data.m_RefEntries = std::vector<BLK_0x2A_LAYER_LIST::REF_ENTRY>();
1602 data.m_RefEntries->reserve( data.m_NumEntries );
1603 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1613 data.m_Key = aStream.
ReadU32();
1614 block->SetKey( data.m_Key );
1622 auto block = std::make_unique<BLOCK<BLK_0x2B_FOOTPRINT_DEF>>( stream.
Position() );
1624 auto& data = block->GetData();
1628 data.m_Key = stream.
ReadU32();
1629 block->SetKey( data.m_Key );
1630 data.m_FpStrRef = stream.
ReadU32();
1631 data.m_Unknown1 = stream.
ReadU32();
1633 data.m_Next = stream.
ReadU32();
1634 block->SetNext( data.m_Next );
1635 data.m_FirstInstPtr = stream.
ReadU32();
1636 data.m_UnknownPtr3 = stream.
ReadU32();
1637 data.m_UnknownPtr4 = stream.
ReadU32();
1638 data.m_UnknownPtr5 = stream.
ReadU32();
1639 data.m_SymLibPathPtr = stream.
ReadU32();
1640 data.m_UnknownPtr6 = stream.
ReadU32();
1641 data.m_UnknownPtr7 = stream.
ReadU32();
1642 data.m_UnknownPtr8 = stream.
ReadU32();
1644 ReadCond( stream, aVer, data.m_Unknown2 );
1645 ReadCond( stream, aVer, data.m_Unknown3 );
1653 auto block = std::make_unique<BLOCK<BLK_0x2C_TABLE>>( aStream.
Position() );
1655 auto& data = block->GetData();
1657 data.m_Type = aStream.
ReadU8();
1658 data.m_SubType = aStream.
ReadU16();
1659 data.m_Key = aStream.
ReadU32();
1660 block->SetKey( data.m_Key );
1661 data.m_Next = aStream.
ReadU32();
1662 block->SetNext( data.m_Next );
1664 ReadCond( aStream, aVer, data.m_Unknown1 );
1665 ReadCond( aStream, aVer, data.m_Unknown2 );
1666 ReadCond( aStream, aVer, data.m_Unknown3 );
1668 data.m_StringPtr = aStream.
ReadU32();
1670 ReadCond( aStream, aVer, data.m_Unknown4 );
1672 data.m_Ptr1 = aStream.
ReadU32();
1673 data.m_Ptr2 = aStream.
ReadU32();
1674 data.m_Ptr3 = aStream.
ReadU32();
1676 data.m_Flags = aStream.
ReadU32();
1684 auto block = std::make_unique<BLOCK<BLK_0x2D_FOOTPRINT_INST>>( stream.
Position() );
1686 auto& data = block->GetData();
1688 data.m_UnknownByte1 = stream.
ReadU8();
1689 data.m_Layer = stream.
ReadU8();
1690 data.m_UnknownByte2 = stream.
ReadU8();
1692 data.m_Key = stream.
ReadU32();
1693 block->SetKey( data.m_Key );
1694 data.m_Next = stream.
ReadU32();
1695 block->SetNext( data.m_Next );
1697 ReadCond( stream, aVer, data.m_Unknown1 );
1699 ReadCond( stream, aVer, data.m_InstRef16x );
1701 data.m_Unknown2 = stream.
ReadU16();
1702 data.m_Unknown3 = stream.
ReadU16();
1704 ReadCond( stream, aVer, data.m_Unknown4 );
1706 data.m_Flags = stream.
ReadU32();
1708 data.m_Rotation = stream.
ReadU32();
1709 data.m_CoordX = stream.
ReadS32();
1710 data.m_CoordY = stream.
ReadS32();
1712 ReadCond( stream, aVer, data.m_InstRef );
1714 data.m_GraphicPtr = stream.
ReadU32();
1715 data.m_FirstPadPtr = stream.
ReadU32();
1716 data.m_TextPtr = stream.
ReadU32();
1718 data.m_AssemblyPtr = stream.
ReadU32();
1719 data.m_AreasPtr = stream.
ReadU32();
1720 data.m_UnknownPtr1 = stream.
ReadU32();
1721 data.m_UnknownPtr2 = stream.
ReadU32();
1729 auto block = std::make_unique<BLOCK<BLK_0x2E_CONNECTION>>( aStream.
Position() );
1731 auto& data = block->GetData();
1733 data.m_Type = aStream.
ReadU8();
1734 data.m_T2 = aStream.
ReadU16();
1735 data.m_Key = aStream.
ReadU32();
1736 block->SetKey( data.m_Key );
1737 data.m_Next = aStream.
ReadU32();
1738 block->SetNext( data.m_Next );
1739 data.m_NetAssignment = aStream.
ReadU32();
1740 data.m_Unknown1 = aStream.
ReadU32();
1741 data.m_CoordX = aStream.
ReadU32();
1742 data.m_CoordY = aStream.
ReadU32();
1743 data.m_Connection = aStream.
ReadU32();
1744 data.m_Unknown2 = aStream.
ReadU32();
1746 ReadCond( aStream, aVer, data.m_Unknown3 );
1754 auto block = std::make_unique<BLOCK<BLK_0x2F_UNKNOWN>>( aStream.
Position() );
1756 auto& data = block->GetData();
1758 data.m_Type = aStream.
ReadU8();
1759 data.m_T2 = aStream.
ReadU16();
1760 data.m_Key = aStream.
ReadU32();
1761 block->SetKey( data.m_Key );
1776 uint8_t alignment = aStream.
ReadU8();
1788 uint8_t reversal = aStream.
ReadU8();
1804 auto block = std::make_unique<BLOCK<BLK_0x30_STR_WRAPPER>>( aStream.
Position() );
1806 auto& data = block->GetData();
1808 data.m_Type = aStream.
ReadU8();
1810 data.m_Key = aStream.
ReadU32();
1811 block->SetKey( data.m_Key );
1812 data.m_Next = aStream.
ReadU32();
1813 block->SetNext( data.m_Next );
1815 ReadCond( aStream, aVer, data.m_Unknown1 );
1816 ReadCond( aStream, aVer, data.m_Unknown2 );
1818 if( data.m_Font.exists( aVer ) )
1823 ReadCond( aStream, aVer, data.m_Ptr1 );
1824 ReadCond( aStream, aVer, data.m_Unknown3 );
1826 data.m_StrGraphicPtr = aStream.
ReadU32();
1828 ReadCond( aStream, aVer, data.m_PtrGroup_17x );
1829 ReadCond( aStream, aVer, data.m_Unknown4 );
1831 if( data.m_Font16x.exists( aVer ) )
1836 ReadCond( aStream, aVer, data.m_Ptr2 );
1838 data.m_CoordsX = aStream.
ReadU32();
1839 data.m_CoordsY = aStream.
ReadU32();
1841 data.m_Unknown5 = aStream.
ReadU32();
1842 data.m_Rotation = aStream.
ReadU32();
1844 ReadCond( aStream, aVer, data.m_PtrGroup_16x );
1852 auto block = std::make_unique<BLOCK<BLK_0x31_SGRAPHIC>>( aStream.
Position() );
1854 auto& data = block->GetData();
1856 data.m_T = aStream.
ReadU8();
1859 const uint16_t layer = aStream.
ReadU16();
1874 data.m_Key = aStream.
ReadU32();
1875 block->SetKey( data.m_Key );
1876 data.m_StrGraphicWrapperPtr = aStream.
ReadU32();
1878 data.m_CoordsX = aStream.
ReadU32();
1879 data.m_CoordsY = aStream.
ReadU32();
1881 data.m_Unknown = aStream.
ReadU16();
1882 data.m_Len = aStream.
ReadU16();
1884 ReadCond( aStream, aVer, data.m_Un2 );
1894 auto block = std::make_unique<BLOCK<BLK_0x32_PLACED_PAD>>( aStream.
Position() );
1896 auto& data = block->GetData();
1898 data.m_Type = aStream.
ReadU8();
1900 data.m_Key = aStream.
ReadU32();
1901 block->SetKey( data.m_Key );
1902 data.m_Next = aStream.
ReadU32();
1903 block->SetNext( data.m_Next );
1904 data.m_NetPtr = aStream.
ReadU32();
1905 data.m_Flags = aStream.
ReadU32();
1907 ReadCond( aStream, aVer, data.m_Prev );
1909 data.m_NextInFp = aStream.
ReadU32();
1910 data.m_ParentFp = aStream.
ReadU32();
1911 data.m_Track = aStream.
ReadU32();
1912 data.m_PadPtr = aStream.
ReadU32();
1913 data.m_Ptr6 = aStream.
ReadU32();
1914 data.m_Ratline = aStream.
ReadU32();
1915 data.m_PtrPinNumber = aStream.
ReadU32();
1916 data.m_NextInCompInst = aStream.
ReadU32();
1918 ReadCond( aStream, aVer, data.m_Unknown2 );
1920 data.m_NameText = aStream.
ReadU32();
1921 data.m_Ptr11 = aStream.
ReadU32();
1923 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1925 data.m_Coords[i] = aStream.
ReadS32();
1934 auto block = std::make_unique<BLOCK<BLK_0x33_VIA>>( aStream.
Position() );
1936 auto& data = block->GetData();
1941 data.m_Key = aStream.
ReadU32();
1942 block->SetKey( data.m_Key );
1943 data.m_Next = aStream.
ReadU32();
1944 block->SetNext( data.m_Next );
1945 data.m_NetPtr = aStream.
ReadU32();
1946 data.m_Unknown2 = aStream.
ReadU32();
1948 ReadCond( aStream, aVer, data.m_Unknown3 );
1950 data.m_UnknownPtr1 = aStream.
ReadU32();
1952 ReadCond( aStream, aVer, data.m_UnknownPtr2 );
1954 data.m_CoordsX = aStream.
ReadS32();
1955 data.m_CoordsY = aStream.
ReadS32();
1957 data.m_Connection = aStream.
ReadU32();
1958 data.m_Padstack = aStream.
ReadU32();
1959 data.m_UnknownPtr5 = aStream.
ReadU32();
1960 data.m_UnknownPtr6 = aStream.
ReadU32();
1962 data.m_Unknown4 = aStream.
ReadU32();
1963 data.m_Unknown5 = aStream.
ReadU32();
1965 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
1967 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
1976 auto block = std::make_unique<BLOCK<BLK_0x34_KEEPOUT>>( aStream.
Position() );
1978 auto& data = block->GetData();
1980 data.m_T = aStream.
ReadU8();
1982 data.m_Key = aStream.
ReadU32();
1983 block->SetKey( data.m_Key );
1984 data.m_Next = aStream.
ReadU32();
1985 block->SetNext( data.m_Next );
1986 data.m_Ptr1 = aStream.
ReadU32();
1988 ReadCond( aStream, aVer, data.m_Unknown1 );
1990 data.m_Flags = aStream.
ReadU32();
1991 data.m_FirstSegmentPtr = aStream.
ReadU32();
1992 data.m_Ptr3 = aStream.
ReadU32();
1993 data.m_Unknown2 = aStream.
ReadU32();
2001 auto block = std::make_unique<BLOCK<BLK_0x35_FILE_REF>>( aStream.
Position() );
2003 auto& data = block->GetData();
2005 data.m_T2 = aStream.
ReadU8();
2006 data.m_T3 = aStream.
ReadU16();
2007 aStream.
ReadBytes( data.m_Content.data(), data.m_Content.size() );
2015 auto block = std::make_unique<BLOCK<BLK_0x36_DEF_TABLE>>( aStream.
Position() );
2017 auto& data = block->GetData();
2021 data.m_Code = aStream.
ReadU16();
2022 data.m_Key = aStream.
ReadU32();
2023 block->SetKey( data.m_Key );
2024 data.m_Next = aStream.
ReadU32();
2025 block->SetNext( data.m_Next );
2027 ReadCond( aStream, aVer, data.m_Unknown1 );
2029 data.m_NumItems = aStream.
ReadU32();
2030 data.m_Count = aStream.
ReadU32();
2031 data.m_LastIdx = aStream.
ReadU32();
2032 data.m_Unknown2 = aStream.
ReadU32();
2034 ReadCond( aStream, aVer, data.m_Unknown3 );
2036 if( data.m_NumItems > 1000000 )
2039 "Block 0x36 item count %u exceeds limit at offset %#010zx",
2040 data.m_NumItems, aStream.
Position() ) );
2043 if( data.m_Count > data.m_NumItems )
2046 "Block 0x36 filled count %u exceeds capacity %u at offset %#010zx",
2047 data.m_Count, data.m_NumItems, aStream.
Position() ) );
2053 data.m_Items.reserve( data.m_Count );
2054 for( uint32_t i = 0; i < data.m_NumItems; ++i )
2056 const bool keep = i < data.m_Count;
2058 switch( data.m_Code )
2070 data.m_Items.emplace_back( std::move( item ) );
2084 data.m_Items.emplace_back( std::move( item ) );
2095 data.m_Items.emplace_back( std::move( item ) );
2110 data.m_Items.emplace_back( std::move( item ) );
2132 data.m_Items.emplace_back( std::move( item ) );
2140 data.m_Items.emplace_back( std::move( item ) );
2148 data.m_Items.emplace_back( std::move( item ) );
2156 data.m_Items.emplace_back( std::move( item ) );
2166 data.m_Items.emplace_back( std::move( item ) );
2175 data.m_Items.emplace_back( std::move( item ) );
2182 aStream.
Skip( 1052 );
2184 data.m_Items.emplace_back( std::move( item ) );
2187 default:
THROW_IO_ERROR( wxString::Format(
"Unknown substruct type %#02x in block 0x36", data.m_Code ) );
2197 auto block = std::make_unique<BLOCK<BLK_0x37_PTR_ARRAY>>( aStream.
Position() );
2199 auto& data = block->GetData();
2201 data.m_T = aStream.
ReadU8();
2202 data.m_T2 = aStream.
ReadU16();
2203 data.m_Key = aStream.
ReadU32();
2204 block->SetKey( data.m_Key );
2205 data.m_GroupPtr = aStream.
ReadU32();
2206 data.m_Next = aStream.
ReadU32();
2207 block->SetNext( data.m_Next );
2208 data.m_Capacity = aStream.
ReadU32();
2209 data.m_Count = aStream.
ReadU32();
2210 data.m_Unknown2 = aStream.
ReadU32();
2212 ReadCond( aStream, aVer, data.m_Unknown3 );
2222 auto block = std::make_unique<BLOCK<BLK_0x38_FILM>>( aStream.
Position() );
2224 auto& data = block->GetData();
2228 data.m_Key = aStream.
ReadU32();
2229 block->SetKey( data.m_Key );
2230 data.m_Next = aStream.
ReadU32();
2231 block->SetNext( data.m_Next );
2232 data.m_LayerList = aStream.
ReadU32();
2234 if( data.m_FilmName.exists( aVer ) )
2239 ReadCond( aStream, aVer, data.m_LayerNameStr );
2240 ReadCond( aStream, aVer, data.m_Unknown2 );
2242 for(
size_t i = 0; i < data.m_UnknownArray1.size(); ++i )
2244 data.m_UnknownArray1[i] = aStream.
ReadU32();
2247 ReadCond( aStream, aVer, data.m_Unknown3 );
2255 auto block = std::make_unique<BLOCK<BLK_0x39_FILM_LAYER_LIST>>( aStream.
Position() );
2257 auto& data = block->GetData();
2261 data.m_Key = aStream.
ReadU32();
2262 block->SetKey( data.m_Key );
2263 data.m_Parent = aStream.
ReadU32();
2264 data.m_Head = aStream.
ReadU32();
2266 for(
size_t i = 0; i < data.m_X.size(); ++i )
2268 data.m_X[i] = aStream.
ReadU16();
2277 auto block = std::make_unique<BLOCK<BLK_0x3A_FILM_LIST_NODE>>( aStream.
Position() );
2279 auto& data = block->GetData();
2284 data.m_Key = aStream.
ReadU32();
2285 block->SetKey( data.m_Key );
2286 data.m_Next = aStream.
ReadU32();
2287 block->SetNext( data.m_Next );
2288 data.m_Unknown = aStream.
ReadU32();
2290 ReadCond( aStream, aVer, data.m_Unknown1 );
2298 auto block = std::make_unique<BLOCK<BLK_0x3B_PROPERTY>>( aStream.
Position() );
2300 auto& data = block->GetData();
2302 data.m_T = aStream.
ReadU8();
2303 data.m_SubType = aStream.
ReadU16();
2304 data.m_Len = aStream.
ReadU32();
2309 data.m_Unknown1 = aStream.
ReadU32();
2310 data.m_Unknown2 = aStream.
ReadU32();
2312 ReadCond( aStream, aVer, data.m_Unknown3 );
2322 auto block = std::make_unique<BLOCK<BLK_0x3C_KEY_LIST>>( aStream.
Position() );
2324 auto& data = block->GetData();
2326 data.m_T = aStream.
ReadU8();
2327 data.m_T2 = aStream.
ReadU16();
2328 data.m_Key = aStream.
ReadU32();
2329 block->SetKey( data.m_Key );
2331 ReadCond( aStream, aVer, data.m_Unknown );
2333 data.m_NumEntries = aStream.
ReadU32();
2335 if( data.m_NumEntries > 1000000 )
2338 "Block 0x3C entry count %u exceeds limit at offset %#010zx",
2339 data.m_NumEntries, aStream.
Position() ) );
2342 data.m_Entries.reserve( data.m_NumEntries );
2343 for( uint32_t i = 0; i < data.m_NumEntries; ++i )
2345 data.m_Entries.push_back( aStream.
ReadU32() );
2356 uint8_t type = 0x00;
2359 aEndOfObjectsMarker =
true;
2363 std::unique_ptr<BLOCK_BASE> block;
2519 wxString::Format(
"Current offset %#010zx is at or past the expected end of block 0x27 at %#010zx",
2633 aEndOfObjectsMarker =
true;
2657 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
2661 const size_t offset =
m_stream.Position();
2664 wxASSERT_MSG( offset % 4 == 0,
2665 wxString::Format(
"Allegro object at %#010zx, offset not aligned to 4 bytes", offset ) );
2670 uint8_t blockTypeByte = 0;
2674 bool endOfObjectsMarker =
false;
2675 std::unique_ptr<BLOCK_BASE> block = blockParser.
ParseBlock( endOfObjectsMarker );
2677 if( endOfObjectsMarker )
2683 size_t scanPos =
m_stream.Position();
2684 uint8_t nextByte = 0;
2686 while(
m_stream.GetU8( nextByte ) && nextByte == 0x00 )
2689 if( nextByte > 0x00 && nextByte <= 0x3C )
2691 size_t blockStart = scanPos;
2693 if( blockStart % 4 != 0 )
2694 blockStart -= ( blockStart % 4 );
2699 uint8_t alignedByte = 0;
2704 if( alignedByte == 0x00 || alignedByte > 0x3C )
2708 wxString::Format(
"V18 zero gap from %#010zx to %#010zx, "
2709 "continuing at block type %#04x",
2710 offset, blockStart, nextByte ) );
2718 wxString::Format(
"End of objects marker (0x00) at index %zu, offset %#010zx",
2730 "Do not have parser for block index %zu type %#02x available at offset %#010zx",
2736 wxString::Format(
"Ending at unknown block, index %zu type %#04x at offset %#010zx",
2739 wxFAIL_MSG(
"Failed to create block" );
2746 wxString::Format(
"Added block %zu, type %#04x from %#010zx to %#010zx",
2764template <
typename T>
2767 if constexpr( std::is_same_v<T, FILE_HEADER::LINKED_LIST> )
2771 else if constexpr( VERSIONED_COND_FIELD<T> &&
2772 std::is_same_v<typename T::value_type, FILE_HEADER::LINKED_LIST> )
2774 if( aLL.has_value() )
2782 std::unique_ptr<BRD_DB> board = std::make_unique<BRD_DB>();
2797 if( !board->m_Header )
2806 board->m_Header->m_Magic );
2808 dumpLL(
"V18_1", board->m_Header->m_LL_V18_1 );
2809 dumpLL(
"V18_2", board->m_Header->m_LL_V18_2 );
2810 dumpLL(
"V18_3", board->m_Header->m_LL_V18_3 );
2811 dumpLL(
"V18_4", board->m_Header->m_LL_V18_4 );
2812 dumpLL(
"V18_5", board->m_Header->m_LL_V18_5 );
2814 dumpLL(
"0x04", board->m_Header->m_LL_0x04 );
2815 dumpLL(
"0x06", board->m_Header->m_LL_0x06 );
2816 dumpLL(
"0x0C", board->m_Header->m_LL_0x0C );
2817 dumpLL(
"Shapes", board->m_Header->m_LL_Shapes );
2818 dumpLL(
"0x14", board->m_Header->m_LL_0x14 );
2819 dumpLL(
"0x1B_Nets", board->m_Header->m_LL_0x1B_Nets );
2820 dumpLL(
"0x1C", board->m_Header->m_LL_0x1C );
2821 dumpLL(
"0x24_0x28", board->m_Header->m_LL_0x24_0x28 );
2822 dumpLL(
"Unknown1", board->m_Header->m_LL_Unknown1 );
2823 dumpLL(
"0x2B", board->m_Header->m_LL_0x2B );
2824 dumpLL(
"0x03_0x30", board->m_Header->m_LL_0x03_0x30 );
2825 dumpLL(
"0x0A", board->m_Header->m_LL_0x0A );
2826 dumpLL(
"0x1D_0x1E_0x1F", board->m_Header->m_LL_0x1D_0x1E_0x1F );
2827 dumpLL(
"Unknown2", board->m_Header->m_LL_Unknown2 );
2828 dumpLL(
"0x38", board->m_Header->m_LL_0x38 );
2829 dumpLL(
"0x2C", board->m_Header->m_LL_0x2C );
2830 dumpLL(
"0x0C_2", board->m_Header->m_LL_0x0C_2 );
2831 dumpLL(
"Unknown3", board->m_Header->m_LL_Unknown3 );
2832 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_preV18 );
2833 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_V18 );
2834 dumpLL(
"0x36", board->m_Header->m_LL_0x36 );
2835 dumpLL(
"Unknown6", board->m_Header->m_LL_Unknown6 );
2836 dumpLL(
"0x0A_2", board->m_Header->m_LL_0x0A_2 );
2838 dumpLL(
"V18_6", board->m_Header->m_LL_V18_6 );
2844 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2845 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2847 if( board->m_Header )
2848 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2850 s += wxString::Format(
"File magic: Unknown\n" );
2859 wxString verStr( board->m_Header->m_AllegroVersion.data(), 60 );
2863 _(
"This file was created with %s, which uses a binary format that "
2864 "predates Allegro 16.0 and is not supported by this importer.\n\n"
2865 "To import this design, open it in Cadence Allegro PCB Editor "
2866 "version 16.0 or later and re-save, then import the resulting file." ),
2870 const uint32_t stringsCount = board->m_Header->GetStringsCount();
2871 board->ReserveCapacity( board->m_Header->m_ObjectCount, stringsCount );
2877 wxLogTrace(
traceAllegroPerf, wxT(
" ReadStringMap (%u strings): %.3f ms" ),
2878 stringsCount, parseTimer.
msecs(
true ) );
2882 wxLogTrace(
traceAllegroPerf, wxT(
" readObjects (%zu objects): %.3f ms" ),
2883 board->GetObjectCount(), parseTimer.
msecs(
true ) );
2888 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2889 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2891 if( board->m_Header )
2892 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2894 s += wxString::Format(
"File magic: Unknown\n" );
2900 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 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_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.
static const wxChar *const traceAllegroParser
Flag to enable debug output of Allegro parsing.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
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
TEXT_ALIGNMENT m_Alignment
COND_GE< FMT_VER::V_172, std::array< uint32_t, 8 > > m_Ys
uint32_t m_CharacterSpace
COND_GE< FMT_VER::V_174, 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_174, 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.
std::vector< std::string > header
wxString result
Test unit parsing edge cases and error handling.