31#include <wx/sstream.h>
33#include <wx/translation.h>
56 uint32_t w1 = aStream.
ReadU32();
57 uint32_t w2 = aStream.
ReadU32();
78 const uint32_t a = aStream.
ReadU32();
79 const uint32_t b = aStream.
ReadU32();
82 const uint64_t
combined = (
static_cast<uint64_t
>( a ) << 32 ) + b;
91template <
typename ARRAY>
94 for(
size_t i = 0; i < aArray.size(); i++ )
105 if constexpr( std::is_same_v<T, uint32_t> )
109 else if constexpr( std::is_same_v<T, uint8_t> )
113 else if constexpr( std::is_same_v<T, uint16_t> )
117 else if constexpr( std::is_same_v<T, int16_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( aField.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;
199 header->m_Unknown1a =
m_stream.ReadU32();
200 header->m_FileRole =
m_stream.ReadU32();
201 header->m_Unknown1b =
m_stream.ReadU32();
202 header->m_WriterProgram =
m_stream.ReadU32();
204 header->m_ObjectCount =
m_stream.ReadU32();
206 header->m_UnknownMagic =
m_stream.ReadU32();
207 header->m_UnknownFlags =
m_stream.ReadU32();
264 wxASSERT(
m_stream.Position() - headerStartPos == 0xF8 );
266 wxASSERT(
m_stream.Position() - headerStartPos == 0x124 );
268 m_stream.ReadBytes( header->m_AllegroVersion.data(), header->m_AllegroVersion.size() );
269 header->m_Unknown4 =
m_stream.ReadU32();
270 header->m_MaxKey =
m_stream.ReadU32();
282 default:
THROW_IO_ERROR( wxString::Format(
"Unknown board units %d", units ) );
288 header->m_Unknown6 =
m_stream.ReadU32();
293 header->m_Unknown8 =
m_stream.ReadU32();
299 header->m_Unknown10a =
m_stream.ReadU32();
300 header->m_Unknown10b =
m_stream.ReadU32();
301 header->m_Unknown10c =
m_stream.ReadU32();
303 header->m_UnitsDivisor =
m_stream.ReadU32();
307 for(
size_t i = 0; i < header->m_LayerMap.size(); ++i )
309 header->m_LayerMap[i].m_A =
m_stream.ReadU32();
310 header->m_LayerMap[i].m_LayerList0x2A =
m_stream.ReadU32();
313 wxLogTrace(
traceAllegroParser, wxT(
"Parsed header: %d objects, %d strings" ), header->m_ObjectCount,
314 header->GetStringsCount() );
324 for( uint32_t i = 0; i < count; ++i )
326 uint32_t
id = stream.
ReadU32();
336 uint8_t classCode = aStream.
ReadU8();
337 uint8_t subclassCode = aStream.
ReadU8();
342 .m_Class = classCode,
343 .m_Subclass = subclassCode,
350 auto block = std::make_unique<BLOCK<BLK_0x01_ARC>>( 0x01, aStream.
Position() );
352 auto& data = block->GetData();
356 data.m_UnknownByte = aStream.
ReadU8();
357 data.m_SubType = aStream.
ReadU8();
358 data.m_Key = aStream.
ReadU32();
359 data.m_Next = aStream.
ReadU32();
360 data.m_Parent = aStream.
ReadU32();
361 data.m_Unknown1 = aStream.
ReadU32();
363 ReadCond( aStream, aVer, data.m_Unknown6 );
365 data.m_Width = aStream.
ReadU32();
367 data.m_StartX = aStream.
ReadS32();
368 data.m_StartY = aStream.
ReadS32();
369 data.m_EndX = aStream.
ReadS32();
370 data.m_EndY = aStream.
ReadS32();
376 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
378 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
387 auto block = std::make_unique<BLOCK<BLK_0x03_FIELD>>( 0x03, aStream.
Position() );
389 auto& data = block->GetData();
393 data.m_Hdr1 = aStream.
ReadU16();
394 data.m_Key = aStream.
ReadU32();
395 data.m_Next = aStream.
ReadU32();
397 ReadCond( aStream, aVer, data.m_Unknown1 );
399 data.m_SubType = aStream.
ReadU8();
400 data.m_Hdr2 = aStream.
ReadU8();
401 data.m_Size = aStream.
ReadU16();
403 ReadCond( aStream, aVer, data.m_Unknown2 );
408 switch( data.m_SubType )
418 data.m_Substruct = aStream.
ReadU32();
423 data.m_Substruct = std::array<uint32_t, 2>{
449 "Block 0x03 subtype 0x6C entry count %u exceeds limit at offset %#010zx",
459 data.m_Substruct = std::move( sub );
470 const size_t numEntries = ( sub.
m_X1 + 4 * sub.
m_X0 );
472 for(
size_t i = 0; i < numEntries; ++i )
476 data.m_Substruct = std::move( sub );
482 for(
size_t i = 0; i < sub.
m_Entries.size(); ++i )
486 data.m_Substruct = std::move( sub );
491 if( data.m_Size == 4 )
493 data.m_Substruct = aStream.
ReadU32();
495 else if( data.m_Size == 8 )
497 std::array<uint32_t, 2> sub;
500 data.m_Substruct = std::move( sub );
505 wxString::Format(
"Unknown substruct type %#02x with size %d", data.m_SubType, data.m_Size ) );
517 auto block = std::make_unique<BLOCK<BLK_0x04_NET_ASSIGNMENT>>( 0x04, aStream.
Position() );
519 auto& data = block->GetData();
521 data.m_Type = aStream.
ReadU8();
523 data.m_Key = aStream.
ReadU32();
524 data.m_Next = aStream.
ReadU32();
525 data.m_Net = aStream.
ReadU32();
526 data.m_ConnItem = aStream.
ReadU32();
528 ReadCond( aStream, aVer, data.m_Unknown );
536 auto block = std::make_unique<BLOCK<BLK_0x05_TRACK>>( 0x05, aStream.
Position() );
538 auto& data = block->GetData();
543 data.m_Key = aStream.
ReadU32();
544 data.m_Next = aStream.
ReadU32();
545 data.m_NetAssignment = aStream.
ReadU32();
546 data.m_UnknownPtr1 = aStream.
ReadU32();
547 data.m_Unknown2 = aStream.
ReadU32();
548 data.m_Unknown3 = aStream.
ReadU32();
549 data.m_UnknownPtr2a = aStream.
ReadU32();
550 data.m_UnknownPtr2b = aStream.
ReadU32();
551 data.m_Unknown4 = aStream.
ReadU32();
552 data.m_UnknownPtr3a = aStream.
ReadU32();
553 data.m_UnknownPtr3b = aStream.
ReadU32();
555 ReadCond( aStream, aVer, data.m_Unknown5a );
556 ReadCond( aStream, aVer, data.m_Unknown5b );
558 data.m_FirstSegPtr = aStream.
ReadU32();
559 data.m_UnknownPtr5 = aStream.
ReadU32();
560 data.m_Unknown6 = aStream.
ReadU32();
568 auto block = std::make_unique<BLOCK<BLK_0x06_COMPONENT>>( 0x06, stream.
Position() );
570 auto& data = block->GetData();
575 data.m_Next = stream.
ReadU32();
576 data.m_CompDeviceType = stream.
ReadU32();
577 data.m_SymbolName = stream.
ReadU32();
578 data.m_FirstInstPtr = stream.
ReadU32();
579 data.m_PtrFunctionSlot = stream.
ReadU32();
580 data.m_PtrPinNumber = stream.
ReadU32();
581 data.m_Fields = stream.
ReadU32();
583 ReadCond( stream, aVer, data.m_Unknown1 );
591 auto block = std::make_unique<BLOCK<BLK_0x07_COMPONENT_INST>>( 0x07, stream.
Position() );
593 auto& data = block->GetData();
598 data.m_Next = stream.
ReadU32();
600 ReadCond( stream, aVer, data.m_UnknownPtr1 );
601 ReadCond( stream, aVer, data.m_Unknown2 );
602 ReadCond( stream, aVer, data.m_Unknown3 );
604 data.m_FpInstPtr = stream.
ReadU32();
606 ReadCond( stream, aVer, data.m_Unknown4 );
608 data.m_RefDesStrPtr = stream.
ReadU32();
609 data.m_FunctionInstPtr = stream.
ReadU32();
610 data.m_X03Ptr = stream.
ReadU32();
611 data.m_Unknown5 = stream.
ReadU32();
612 data.m_FirstPadPtr = stream.
ReadU32();
620 auto block = std::make_unique<BLOCK<BLK_0x08_PIN_NUMBER>>( 0x08, aStream.
Position() );
622 auto& data = block->GetData();
624 data.m_Type = aStream.
ReadU8();
626 data.m_Key = aStream.
ReadU32();
628 ReadCond( aStream, aVer, data.m_Previous );
629 ReadCond( aStream, aVer, data.m_StrPtr16x );
631 data.m_Next = aStream.
ReadU32();
633 ReadCond( aStream, aVer, data.m_StrPtr );
635 data.m_PinNamePtr = aStream.
ReadU32();
637 ReadCond( aStream, aVer, data.m_Unknown1 );
639 data.m_Ptr4 = aStream.
ReadU32();
647 auto block = std::make_unique<BLOCK<BLK_0x09_FILL_LINK>>( 0x09, aStream.
Position() );
649 auto& data = block->GetData();
653 data.m_Key = aStream.
ReadU32();
655 for(
size_t i = 0; i < data.m_UnknownArray.size(); ++i )
657 data.m_UnknownArray[i] = aStream.
ReadU32();
660 ReadCond( aStream, aVer, data.m_Unknown1 );
662 data.m_UnknownPtr1 = aStream.
ReadU32();
663 data.m_UnknownPtr2 = aStream.
ReadU32();
664 data.m_Unknown2 = aStream.
ReadU32();
665 data.m_UnknownPtr3 = aStream.
ReadU32();
666 data.m_UnknownPtr4 = aStream.
ReadU32();
668 ReadCond( aStream, aVer, data.m_Unknown3 );
676 auto block = std::make_unique<BLOCK<BLK_0x0A_DRC>>( 0x0A, aStream.
Position() );
678 auto& data = block->GetData();
680 data.m_T = aStream.
ReadU8();
682 data.m_Key = aStream.
ReadU32();
683 data.m_Next = aStream.
ReadU32();
684 data.m_Unknown1 = aStream.
ReadU32();
686 ReadCond( aStream, aVer, data.m_Unknown2 );
688 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
690 data.m_Coords[i] = aStream.
ReadS32();
696 ReadCond( aStream, aVer, data.m_Unknown6 );
704 auto block = std::make_unique<BLOCK<BLK_0x0C_PIN_DEF>>( 0x0C, aStream.
Position() );
706 auto& data = block->GetData();
708 data.m_T = aStream.
ReadU8();
711 data.m_Key = aStream.
ReadU32();
712 data.m_Next = aStream.
ReadU32();
714 data.m_Unknown1 = aStream.
ReadU32();
715 data.m_Unknown2 = aStream.
ReadU32();
718 ReadCond( aStream, aVer, data.m_Shape );
719 ReadCond( aStream, aVer, data.m_DrillChar );
720 ReadCond( aStream, aVer, data.m_UnknownPadding );
723 ReadCond( aStream, aVer, data.m_Shape16x );
724 ReadCond( aStream, aVer, data.m_DrillChars );
725 ReadCond( aStream, aVer, data.m_Unknown_16x );
727 data.m_Unknown4 = aStream.
ReadU32();
729 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
731 data.m_Coords[i] = aStream.
ReadS32();
734 for(
size_t i = 0; i < data.m_Size.size(); ++i )
736 data.m_Size[i] = aStream.
ReadS32();
739 for(
size_t i = 0; i < data.m_UnknownArray.size(); ++i )
741 data.m_UnknownArray[i] = aStream.
ReadU32();
744 ReadCond( aStream, aVer, data.m_Unknown6 );
752 auto block = std::make_unique<BLOCK<BLK_0x0D_PAD>>( 0x0D, aStream.
Position() );
754 auto& data = block->GetData();
758 data.m_Key = aStream.
ReadU32();
759 data.m_NameStrId = aStream.
ReadU32();
760 data.m_Next = aStream.
ReadU32();
762 ReadCond( aStream, aVer, data.m_Unknown1 );
764 data.m_CoordsX = aStream.
ReadS32();
765 data.m_CoordsY = aStream.
ReadS32();
767 data.m_PadStack = aStream.
ReadU32();
768 data.m_Unknown2 = aStream.
ReadU32();
770 ReadCond( aStream, aVer, data.m_Unknown3 );
772 data.m_Flags = aStream.
ReadU32();
773 data.m_Rotation = aStream.
ReadU32();
781 auto block = std::make_unique<BLOCK<BLK_0x0E_SHAPE_SEG>>( 0x0E, aStream.
Position() );
783 auto& data = block->GetData();
785 data.m_T = aStream.
ReadU8();
787 data.m_Key = aStream.
ReadU32();
788 data.m_Next = aStream.
ReadU32();
789 data.m_FpPtr = aStream.
ReadU32();
791 data.m_Unknown1 = aStream.
ReadU32();
792 data.m_Unknown2 = aStream.
ReadU32();
793 data.m_Unknown3 = aStream.
ReadU32();
795 ReadCond( aStream, aVer, data.m_Unknown4 );
796 ReadCond( aStream, aVer, data.m_Unknown5 );
798 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
800 data.m_Coords[i] = aStream.
ReadS32();
803 for(
size_t i = 0; i < data.m_UnknownArr.size(); ++i )
805 data.m_UnknownArr[i] = aStream.
ReadU32();
814 auto block = std::make_unique<BLOCK<BLK_0x0F_FUNCTION_SLOT>>( 0x0F, stream.
Position() );
816 auto& data = block->GetData();
821 data.m_SlotName = stream.
ReadU32();
822 stream.
ReadBytes( data.m_CompDeviceType.data(), data.m_CompDeviceType.size() );
824 data.m_Ptr0x06 = stream.
ReadU32();
825 data.m_Ptr0x11 = stream.
ReadU32();
826 data.m_Unknown1 = stream.
ReadU32();
828 ReadCond( stream, aVer, data.m_Unknown2 );
829 ReadCond( stream, aVer, data.m_Unknown3 );
837 auto block = std::make_unique<BLOCK<BLK_0x10_FUNCTION_INST>>( 0x10, stream.
Position() );
839 auto& data = block->GetData();
845 ReadCond( stream, aVer, data.m_Unknown1 );
846 data.m_ComponentInstPtr = stream.
ReadU32();
847 ReadCond( stream, aVer, data.m_Unknown2 );
848 data.m_PtrX12 = stream.
ReadU32();
849 data.m_Unknown3 = stream.
ReadU32();
850 data.m_FunctionName = stream.
ReadU32();
851 data.m_Slots = stream.
ReadU32();
852 data.m_Fields = stream.
ReadU32();
860 auto block = std::make_unique<BLOCK<BLK_0x11_PIN_NAME>>( 0x11, aStream.
Position() );
862 auto& data = block->GetData();
864 data.m_Type = aStream.
ReadU8();
866 data.m_Key = aStream.
ReadU32();
867 data.m_PinNameStrPtr = aStream.
ReadU32();
868 data.m_Next = aStream.
ReadU32();
869 data.m_PinNumberPtr = aStream.
ReadU32();
870 data.m_Unknown1 = aStream.
ReadU32();
872 ReadCond( aStream, aVer, data.m_Unknown2 );
880 auto block = std::make_unique<BLOCK<BLK_0x12_XREF>>( 0x12, aStream.
Position() );
882 auto& data = block->GetData();
884 data.m_Type = aStream.
ReadU8();
886 data.m_Key = aStream.
ReadU32();
887 data.m_Ptr1 = aStream.
ReadU32();
888 data.m_Ptr2 = aStream.
ReadU32();
889 data.m_Ptr3 = aStream.
ReadU32();
890 data.m_Unknown1 = aStream.
ReadU32();
892 ReadCond( aStream, aVer, data.m_Unknown2 );
893 ReadCond( aStream, aVer, data.m_Unknown3 );
901 auto block = std::make_unique<BLOCK<BLK_0x14_GRAPHIC>>( 0x14, aStream.
Position() );
903 auto& data = block->GetData();
905 data.m_Type = aStream.
ReadU8();
907 data.m_Key = aStream.
ReadU32();
908 data.m_Next = aStream.
ReadU32();
909 data.m_Parent = aStream.
ReadU32();
910 data.m_Flags = aStream.
ReadU32();
912 ReadCond( aStream, aVer, data.m_Unknown2 );
914 data.m_SegmentPtr = aStream.
ReadU32();
915 data.m_Ptr0x03 = aStream.
ReadU32();
916 data.m_Ptr0x26 = aStream.
ReadU32();
924 auto block = std::make_unique<BLOCK<BLK_0x15_16_17_SEGMENT>>( aType, aStream.
Position() );
926 auto& data = block->GetData();
930 data.m_Key = aStream.
ReadU32();
931 data.m_Next = aStream.
ReadU32();
932 data.m_Parent = aStream.
ReadU32();
933 data.m_Flags = aStream.
ReadU32();
935 ReadCond( aStream, aVer, data.m_Unknown2 );
937 data.m_Width = aStream.
ReadU32();
939 data.m_StartX = aStream.
ReadS32();
940 data.m_StartY = aStream.
ReadS32();
941 data.m_EndX = aStream.
ReadS32();
942 data.m_EndY = aStream.
ReadS32();
950 auto block = std::make_unique<BLOCK<BLK_0x1B_NET>>( 0x1B, stream.
Position() );
952 auto& data = block->GetData();
957 data.m_Next = stream.
ReadU32();
958 data.m_NetName = stream.
ReadU32();
959 data.m_Unknown1 = stream.
ReadU32();
961 ReadCond( stream, aVer, data.m_Unknown2 );
963 data.m_Type = stream.
ReadU32();
964 data.m_Assignment = stream.
ReadU32();
965 data.m_Ratline = stream.
ReadU32();
966 data.m_FieldsPtr = stream.
ReadU32();
967 data.m_MatchGroupPtr = stream.
ReadU32();
968 data.m_ModelPtr = stream.
ReadU32();
969 data.m_UnknownPtr4 = stream.
ReadU32();
970 data.m_UnknownPtr5 = stream.
ReadU32();
971 data.m_UnknownPtr6 = stream.
ReadU32();
979 auto block = std::make_unique<BLOCK<BLK_0x1C_PADSTACK>>( 0x1C, aStream.
Position() );
981 auto& data = block->GetData();
983 data.m_UnknownByte1 = aStream.
ReadU8();
984 data.m_N = aStream.
ReadU8();
985 data.m_UnknownByte2 = aStream.
ReadU8();
987 data.m_Key = aStream.
ReadU32();
988 data.m_Next = aStream.
ReadU32();
990 data.m_PadStr = aStream.
ReadU32();
991 data.m_Drill = aStream.
ReadU32();
992 data.m_Unknown2 = aStream.
ReadU32();
993 data.m_PadPath = aStream.
ReadU32();
995 ReadCond( aStream, aVer, data.m_Unknown3 );
996 ReadCond( aStream, aVer, data.m_Unknown4 );
997 ReadCond( aStream, aVer, data.m_Unknown5 );
998 ReadCond( aStream, aVer, data.m_Unknown6 );
1001 const uint8_t t = aStream.
ReadU8();
1004 switch( (t & 0xF0) >> 4 )
1023 THROW_IO_ERROR( wxString::Format(
"Unknown padstack type 0x%x", t ) );
1027 data.m_A = ( t & 0x0F );
1030 data.m_B = aStream.
ReadU8();
1031 data.m_C = aStream.
ReadU8();
1032 data.m_D = aStream.
ReadU8();
1034 ReadCond( aStream, aVer, data.m_Unknown7 );
1035 ReadCond( aStream, aVer, data.m_Unknown8 );
1036 ReadCond( aStream, aVer, data.m_Unknown9 );
1038 ReadCond( aStream, aVer, data.m_Unknown10 );
1039 data.m_LayerCount = aStream.
ReadU16();
1041 if( data.m_LayerCount > 256 )
1043 THROW_IO_ERROR( wxString::Format(
"Padstack layer count %u exceeds maximum at offset %#010zx",
1044 data.m_LayerCount, aStream.
Position() ) );
1047 ReadCond( aStream, aVer, data.m_Unknown11 );
1051 ReadCond( aStream, aVer, data.m_SlotAndUnknownArr );
1052 ReadCond( aStream, aVer, data.m_UnknownArr8_2 );
1055 ReadCond( aStream, aVer, data.m_V180Trailer );
1061 const size_t nComps = data.m_NumFixedCompEntries + ( data.m_LayerCount * data.m_NumCompsPerLayer );
1063 data.m_Components.reserve( nComps );
1064 for(
size_t i = 0; i < nComps; ++i )
1096 const size_t nElems = data.m_N * ( ( aVer <
FMT_VER::V_172 ) ? 8 : 10 );
1098 data.m_UnknownArrN.reserve( nElems );
1099 for(
size_t i = 0; i < nElems; ++i )
1101 data.m_UnknownArrN.push_back( aStream.
ReadU32() );
1111 auto block = std::make_unique<BLOCK<BLK_0x1D_CONSTRAINT_SET>>( 0x1D, aStream.
Position() );
1113 auto& data = block->GetData();
1117 data.m_Key = aStream.
ReadU32();
1118 data.m_Next = aStream.
ReadU32();
1119 data.m_NameStrKey = aStream.
ReadU32();
1120 data.m_FieldPtr = aStream.
ReadU32();
1122 data.m_SizeA = aStream.
ReadU16();
1123 data.m_SizeB = aStream.
ReadU16();
1125 data.m_DataB.resize( data.m_SizeB );
1127 for(
auto& item : data.m_DataB )
1128 aStream.
ReadBytes( item.data(), item.size() );
1130 data.m_DataA.resize( data.m_SizeA );
1132 for(
auto& item : data.m_DataA )
1133 aStream.
ReadBytes( item.data(), item.size() );
1135 ReadCond( aStream, aVer, data.m_Unknown4 );
1143 auto block = std::make_unique<BLOCK<BLK_0x1E_SI_MODEL>>( 0x1E, aStream.
Position() );
1145 auto& data = block->GetData();
1147 data.m_Type = aStream.
ReadU8();
1148 data.m_T2 = aStream.
ReadU16();
1149 data.m_Key = aStream.
ReadU32();
1150 data.m_Next = aStream.
ReadU32();
1152 ReadCond( aStream, aVer, data.m_Unknown2 );
1153 ReadCond( aStream, aVer, data.m_Unknown3 );
1155 data.m_StrPtr = aStream.
ReadU32();
1156 data.m_Size = aStream.
ReadU32();
1160 ReadCond( aStream, aVer, data.m_Unknown4 );
1168 auto block = std::make_unique<BLOCK<BLK_0x1F_PADSTACK_DIM>>( 0x1F, aStream.
Position() );
1170 auto& data = block->GetData();
1174 data.m_Key = aStream.
ReadU32();
1176 data.m_Next = aStream.
ReadU32();
1177 data.m_Unknown2 = aStream.
ReadU32();
1178 data.m_Unknown3 = aStream.
ReadU32();
1179 data.m_Unknown4 = aStream.
ReadU32();
1180 data.m_Unknown5 = aStream.
ReadU16();
1182 data.m_Size = aStream.
ReadU16();
1184 size_t substructSize = 0;
1186 substructSize = data.m_Size * 384 + 8;
1188 substructSize = data.m_Size * 280 + 8;
1190 substructSize = data.m_Size * 280 + 4;
1192 substructSize = data.m_Size * 240 + 4;
1194 data.m_Substruct.resize( substructSize );
1195 aStream.
ReadBytes( data.m_Substruct.data(), substructSize );
1203 auto block = std::make_unique<BLOCK<BLK_0x20_UNKNOWN>>( 0x20, aStream.
Position() );
1205 auto& data = block->GetData();
1207 data.m_Type = aStream.
ReadU8();
1209 data.m_Key = aStream.
ReadU32();
1210 data.m_Next = aStream.
ReadU32();
1213 ReadCond( aStream, aVer, data.m_UnknownArray2 );
1221 auto block = std::make_unique<BLOCK<BLK_0x21_BLOB>>( 0x21, aStream.
Position() );
1223 auto& data = block->GetData();
1225 data.m_Type = aStream.
ReadU8();
1228 data.m_Size = aStream.
ReadU32();
1230 if( data.m_Size < 12 )
1232 THROW_IO_ERROR( wxString::Format(
"Block 0x21 size %u too small (minimum 12) at offset %#010zx",
1233 data.m_Size, aStream.
Position() ) );
1236 data.m_Key = aStream.
ReadU32();
1238 const size_t nBytes = data.m_Size - 12;
1239 data.m_Data.resize( nBytes );
1240 aStream.
ReadBytes( data.m_Data.data(), nBytes );
1248 auto block = std::make_unique<BLOCK<BLK_0x22_UNKNOWN>>( 0x22, aStream.
Position() );
1250 auto& data = block->GetData();
1252 data.m_Type = aStream.
ReadU8();
1253 data.m_T2 = aStream.
ReadU16();
1254 data.m_Key = aStream.
ReadU32();
1256 ReadCond( aStream, aVer, data.m_Unknown1 );
1266 auto block = std::make_unique<BLOCK<BLK_0x23_RATLINE>>( 0x23, aStream.
Position() );
1268 auto& data = block->GetData();
1270 data.m_Type = aStream.
ReadU8();
1272 data.m_Key = aStream.
ReadU32();
1273 data.m_Next = aStream.
ReadU32();
1277 data.m_Ptr1 = aStream.
ReadU32();
1278 data.m_Ptr2 = aStream.
ReadU32();
1279 data.m_Ptr3 = aStream.
ReadU32();
1281 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1283 data.m_Coords[i] = aStream.
ReadS32();
1288 ReadCond( aStream, aVer, data.m_Unknown2 );
1289 ReadCond( aStream, aVer, data.m_Unknown3 );
1297 auto block = std::make_unique<BLOCK<BLK_0x24_RECT>>( 0x24, aStream.
Position() );
1299 auto& data = block->GetData();
1301 data.m_Type = aStream.
ReadU8();
1303 data.m_Key = aStream.
ReadU32();
1304 data.m_Next = aStream.
ReadU32();
1305 data.m_Parent = aStream.
ReadU32();
1306 data.m_Unknown1 = aStream.
ReadU32();
1308 ReadCond( aStream, aVer, data.m_Unknown2 );
1310 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1312 data.m_Coords[i] = aStream.
ReadS32();
1315 data.m_Ptr2 = aStream.
ReadU32();
1317 data.m_Unknown3 = aStream.
ReadU32();
1318 data.m_Unknown4 = aStream.
ReadU32();
1319 data.m_Unknown5 = aStream.
ReadU32();
1327 auto block = std::make_unique<BLOCK<BLK_0x26_MATCH_GROUP>>( 0x26, aStream.
Position() );
1329 auto& data = block->GetData();
1331 data.m_Type = aStream.
ReadU8();
1333 data.m_Key = aStream.
ReadU32();
1334 data.m_MemberPtr = aStream.
ReadU32();
1336 ReadCond( aStream, aVer, data.m_Unknown1 );
1338 data.m_GroupPtr = aStream.
ReadU32();
1339 data.m_ConstPtr = aStream.
ReadU32();
1341 ReadCond( aStream, aVer, data.m_Unknown2 );
1349 auto block = std::make_unique<BLOCK<BLK_0x27_CSTRMGR_XREF>>( 0x27, aStream.
Position() );
1351 auto& data = block->GetData();
1353 const size_t totalBytes = aEndOff - 1 - aStream.
Position();
1356 constexpr size_t kPadding = 3;
1358 if( totalBytes <= kPadding )
1360 aStream.
Skip( totalBytes );
1364 aStream.
Skip( kPadding );
1366 const size_t payloadBytes = totalBytes - kPadding;
1367 const size_t numValues = payloadBytes / 4;
1368 const size_t remainder = payloadBytes % 4;
1370 data.m_Refs.resize( numValues );
1372 for(
size_t i = 0; i < numValues; i++ )
1373 data.m_Refs[i] = aStream.
ReadU32();
1376 aStream.
Skip( remainder );
1384 auto block = std::make_unique<BLOCK<BLK_0x28_SHAPE>>( 0x28, aStream.
Position() );
1386 auto& data = block->GetData();
1388 data.m_Type = aStream.
ReadU8();
1390 data.m_Key = aStream.
ReadU32();
1391 data.m_Next = aStream.
ReadU32();
1392 data.m_Ptr1 = aStream.
ReadU32();
1393 data.m_Unknown1 = aStream.
ReadU32();
1395 ReadCond( aStream, aVer, data.m_Unknown2 );
1396 ReadCond( aStream, aVer, data.m_Unknown3 );
1398 data.m_Ptr2 = aStream.
ReadU32();
1399 data.m_Ptr3 = aStream.
ReadU32();
1400 data.m_Ptr4 = aStream.
ReadU32();
1401 data.m_FirstSegmentPtr = aStream.
ReadU32();
1402 data.m_Unknown4 = aStream.
ReadU32();
1403 data.m_Unknown5 = aStream.
ReadU32();
1405 ReadCond( aStream, aVer, data.m_Ptr7 );
1407 data.m_Ptr6 = aStream.
ReadU32();
1409 ReadCond( aStream, aVer, data.m_Ptr7_16x );
1411 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1413 data.m_Coords[i] = aStream.
ReadS32();
1422 auto block = std::make_unique<BLOCK<BLK_0x29_PIN>>( 0x29, aStream.
Position() );
1424 auto& data = block->GetData();
1426 data.m_Type = aStream.
ReadU8();
1428 data.m_Key = aStream.
ReadU32();
1430 data.m_Ptr1 = aStream.
ReadU32();
1431 data.m_Ptr2 = aStream.
ReadU32();
1433 data.m_Null = aStream.
ReadU32();
1435 data.m_Ptr3 = aStream.
ReadU32();
1437 data.m_Coord1 = aStream.
ReadS32();
1438 data.m_Coord2 = aStream.
ReadS32();
1440 data.m_PtrPadstack = aStream.
ReadU32();
1442 data.m_Unknown1 = aStream.
ReadU32();
1444 data.m_PtrX30 = aStream.
ReadU32();
1446 data.m_Unknown2 = aStream.
ReadU32();
1447 data.m_Unknown3 = aStream.
ReadU32();
1448 data.m_Unknown4 = aStream.
ReadU32();
1456 auto block = std::make_unique<BLOCK<BLK_0x2A_LAYER_LIST>>( 0x2A, aStream.
Position() );
1458 auto& data = block->GetData();
1462 data.m_NumEntries = aStream.
ReadU16();
1464 ReadCond( aStream, aVer, data.m_Unknown );
1466 if( data.m_NonRefEntries.exists( aVer ) )
1468 data.m_NonRefEntries = std::vector<BLK_0x2A_LAYER_LIST::NONREF_ENTRY>();
1469 data.m_NonRefEntries->reserve( data.m_NumEntries );
1470 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1479 data.m_RefEntries = std::vector<BLK_0x2A_LAYER_LIST::REF_ENTRY>();
1480 data.m_RefEntries->reserve( data.m_NumEntries );
1481 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1491 data.m_Key = aStream.
ReadU32();
1499 auto block = std::make_unique<BLOCK<BLK_0x2B_FOOTPRINT_DEF>>( 0x2B, stream.
Position() );
1501 auto& data = block->GetData();
1505 data.m_Key = stream.
ReadU32();
1506 data.m_FpStrRef = stream.
ReadU32();
1507 data.m_Unknown1 = stream.
ReadU32();
1509 data.m_Next = stream.
ReadU32();
1510 data.m_FirstInstPtr = stream.
ReadU32();
1511 data.m_UnknownPtr3 = stream.
ReadU32();
1512 data.m_UnknownPtr4 = stream.
ReadU32();
1513 data.m_UnknownPtr5 = stream.
ReadU32();
1514 data.m_SymLibPathPtr = stream.
ReadU32();
1515 data.m_UnknownPtr6 = stream.
ReadU32();
1516 data.m_UnknownPtr7 = stream.
ReadU32();
1517 data.m_UnknownPtr8 = stream.
ReadU32();
1519 ReadCond( stream, aVer, data.m_Unknown2 );
1520 ReadCond( stream, aVer, data.m_Unknown3 );
1528 auto block = std::make_unique<BLOCK<BLK_0x2C_TABLE>>( 0x2C, aStream.
Position() );
1530 auto& data = block->GetData();
1532 data.m_Type = aStream.
ReadU8();
1533 data.m_T2 = aStream.
ReadU16();
1534 data.m_Key = aStream.
ReadU32();
1535 data.m_Next = aStream.
ReadU32();
1537 ReadCond( aStream, aVer, data.m_Unknown1 );
1538 ReadCond( aStream, aVer, data.m_Unknown2 );
1539 ReadCond( aStream, aVer, data.m_Unknown3 );
1541 data.m_StringPtr = aStream.
ReadU32();
1543 ReadCond( aStream, aVer, data.m_Unknown4 );
1545 data.m_Ptr1 = aStream.
ReadU32();
1546 data.m_Ptr2 = aStream.
ReadU32();
1547 data.m_Ptr3 = aStream.
ReadU32();
1549 data.m_Flags = aStream.
ReadU32();
1557 auto block = std::make_unique<BLOCK<BLK_0x2D_FOOTPRINT_INST>>( 0x2D, stream.
Position() );
1559 auto& data = block->GetData();
1561 data.m_UnknownByte1 = stream.
ReadU8();
1562 data.m_Layer = stream.
ReadU8();
1563 data.m_UnknownByte2 = stream.
ReadU8();
1565 data.m_Key = stream.
ReadU32();
1566 data.m_Next = stream.
ReadU32();
1568 ReadCond( stream, aVer, data.m_Unknown1 );
1570 ReadCond( stream, aVer, data.m_InstRef16x );
1572 data.m_Unknown2 = stream.
ReadU16();
1573 data.m_Unknown3 = stream.
ReadU16();
1575 ReadCond( stream, aVer, data.m_Unknown4 );
1577 data.m_Flags = stream.
ReadU32();
1579 data.m_Rotation = stream.
ReadU32();
1580 data.m_CoordX = stream.
ReadS32();
1581 data.m_CoordY = stream.
ReadS32();
1583 ReadCond( stream, aVer, data.m_InstRef );
1585 data.m_GraphicPtr = stream.
ReadU32();
1586 data.m_FirstPadPtr = stream.
ReadU32();
1587 data.m_TextPtr = stream.
ReadU32();
1589 data.m_AssemblyPtr = stream.
ReadU32();
1590 data.m_AreasPtr = stream.
ReadU32();
1591 data.m_UnknownPtr1 = stream.
ReadU32();
1592 data.m_UnknownPtr2 = stream.
ReadU32();
1600 auto block = std::make_unique<BLOCK<BLK_0x2E_CONNECTION>>( 0x2E, aStream.
Position() );
1602 auto& data = block->GetData();
1604 data.m_Type = aStream.
ReadU8();
1605 data.m_T2 = aStream.
ReadU16();
1606 data.m_Key = aStream.
ReadU32();
1607 data.m_Next = aStream.
ReadU32();
1608 data.m_NetAssignment = aStream.
ReadU32();
1609 data.m_Unknown1 = aStream.
ReadU32();
1610 data.m_CoordX = aStream.
ReadU32();
1611 data.m_CoordY = aStream.
ReadU32();
1612 data.m_Connection = aStream.
ReadU32();
1613 data.m_Unknown2 = aStream.
ReadU32();
1615 ReadCond( aStream, aVer, data.m_Unknown3 );
1623 auto block = std::make_unique<BLOCK<BLK_0x2F_UNKNOWN>>( 0x2F, aStream.
Position() );
1625 auto& data = block->GetData();
1627 data.m_Type = aStream.
ReadU8();
1628 data.m_T2 = aStream.
ReadU16();
1629 data.m_Key = aStream.
ReadU32();
1644 uint8_t alignment = aStream.
ReadU8();
1656 uint8_t reversal = aStream.
ReadU8();
1672 auto block = std::make_unique<BLOCK<BLK_0x30_STR_WRAPPER>>( 0x30, aStream.
Position() );
1674 auto& data = block->GetData();
1676 data.m_Type = aStream.
ReadU8();
1678 data.m_Key = aStream.
ReadU32();
1679 data.m_Next = aStream.
ReadU32();
1681 ReadCond( aStream, aVer, data.m_Unknown1 );
1682 ReadCond( aStream, aVer, data.m_Unknown2 );
1684 if( data.m_Font.exists( aVer ) )
1689 ReadCond( aStream, aVer, data.m_Ptr1 );
1690 ReadCond( aStream, aVer, data.m_Unknown3 );
1692 data.m_StrGraphicPtr = aStream.
ReadU32();
1693 data.m_Unknown4 = aStream.
ReadU32();
1695 if( data.m_Font16x.exists( aVer ) )
1700 ReadCond( aStream, aVer, data.m_Ptr2 );
1702 data.m_CoordsX = aStream.
ReadU32();
1703 data.m_CoordsY = aStream.
ReadU32();
1705 data.m_Unknown5 = aStream.
ReadU32();
1706 data.m_Rotation = aStream.
ReadU32();
1708 ReadCond( aStream, aVer, data.m_Ptr3_16x );
1716 auto block = std::make_unique<BLOCK<BLK_0x31_SGRAPHIC>>( 0x31, aStream.
Position() );
1718 auto& data = block->GetData();
1720 data.m_T = aStream.
ReadU8();
1723 const uint16_t layer = aStream.
ReadU16();
1738 data.m_Key = aStream.
ReadU32();
1739 data.m_StrGraphicWrapperPtr = aStream.
ReadU32();
1741 data.m_CoordsX = aStream.
ReadU32();
1742 data.m_CoordsY = aStream.
ReadU32();
1744 data.m_Unknown = aStream.
ReadU16();
1745 data.m_Len = aStream.
ReadU16();
1747 ReadCond( aStream, aVer, data.m_Un2 );
1757 auto block = std::make_unique<BLOCK<BLK_0x32_PLACED_PAD>>( 0x32, aStream.
Position() );
1759 auto& data = block->GetData();
1761 data.m_Type = aStream.
ReadU8();
1763 data.m_Key = aStream.
ReadU32();
1764 data.m_Next = aStream.
ReadU32();
1765 data.m_NetPtr = aStream.
ReadU32();
1766 data.m_Flags = aStream.
ReadU32();
1768 ReadCond( aStream, aVer, data.m_Prev );
1770 data.m_NextInFp = aStream.
ReadU32();
1771 data.m_ParentFp = aStream.
ReadU32();
1772 data.m_Track = aStream.
ReadU32();
1773 data.m_PadPtr = aStream.
ReadU32();
1774 data.m_Ptr6 = aStream.
ReadU32();
1775 data.m_Ratline = aStream.
ReadU32();
1776 data.m_PtrPinNumber = aStream.
ReadU32();
1777 data.m_NextInCompInst = aStream.
ReadU32();
1779 ReadCond( aStream, aVer, data.m_Unknown2 );
1781 data.m_NameText = aStream.
ReadU32();
1782 data.m_Ptr11 = aStream.
ReadU32();
1784 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1786 data.m_Coords[i] = aStream.
ReadS32();
1795 auto block = std::make_unique<BLOCK<BLK_0x33_VIA>>( 0x33, aStream.
Position() );
1797 auto& data = block->GetData();
1802 data.m_Key = aStream.
ReadU32();
1803 data.m_Next = aStream.
ReadU32();
1804 data.m_NetPtr = aStream.
ReadU32();
1805 data.m_Unknown2 = aStream.
ReadU32();
1807 ReadCond( aStream, aVer, data.m_Unknown3 );
1809 data.m_UnknownPtr1 = aStream.
ReadU32();
1811 ReadCond( aStream, aVer, data.m_UnknownPtr2 );
1813 data.m_CoordsX = aStream.
ReadS32();
1814 data.m_CoordsY = aStream.
ReadS32();
1816 data.m_Connection = aStream.
ReadU32();
1817 data.m_Padstack = aStream.
ReadU32();
1818 data.m_UnknownPtr5 = aStream.
ReadU32();
1819 data.m_UnknownPtr6 = aStream.
ReadU32();
1821 data.m_Unknown4 = aStream.
ReadU32();
1822 data.m_Unknown5 = aStream.
ReadU32();
1824 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
1826 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
1835 auto block = std::make_unique<BLOCK<BLK_0x34_KEEPOUT>>( 0x34, aStream.
Position() );
1837 auto& data = block->GetData();
1839 data.m_T = aStream.
ReadU8();
1841 data.m_Key = aStream.
ReadU32();
1842 data.m_Next = aStream.
ReadU32();
1843 data.m_Ptr1 = aStream.
ReadU32();
1845 ReadCond( aStream, aVer, data.m_Unknown1 );
1847 data.m_Flags = aStream.
ReadU32();
1848 data.m_Ptr2 = aStream.
ReadU32();
1849 data.m_Ptr3 = aStream.
ReadU32();
1850 data.m_Unknown2 = aStream.
ReadU32();
1858 auto block = std::make_unique<BLOCK<BLK_0x35_FILE_REF>>( 0x35, aStream.
Position() );
1860 auto& data = block->GetData();
1862 data.m_T2 = aStream.
ReadU8();
1863 data.m_T3 = aStream.
ReadU16();
1864 aStream.
ReadBytes( data.m_Content.data(), data.m_Content.size() );
1872 auto block = std::make_unique<BLOCK<BLK_0x36_DEF_TABLE>>( 0x36, aStream.
Position() );
1874 auto& data = block->GetData();
1878 data.m_Code = aStream.
ReadU16();
1879 data.m_Key = aStream.
ReadU32();
1880 data.m_Next = aStream.
ReadU32();
1882 ReadCond( aStream, aVer, data.m_Unknown1 );
1884 data.m_NumItems = aStream.
ReadU32();
1885 data.m_Count = aStream.
ReadU32();
1886 data.m_LastIdx = aStream.
ReadU32();
1887 data.m_Unknown2 = aStream.
ReadU32();
1889 ReadCond( aStream, aVer, data.m_Unknown3 );
1891 if( data.m_NumItems > 1000000 )
1894 "Block 0x36 item count %u exceeds limit at offset %#010zx",
1895 data.m_NumItems, aStream.
Position() ) );
1898 data.m_Items.reserve( data.m_NumItems );
1899 for( uint32_t i = 0; i < data.m_NumItems; ++i )
1901 switch( data.m_Code )
1912 data.m_Items.emplace_back( std::move( item ) );
1925 data.m_Items.emplace_back( std::move( item ) );
1934 data.m_Items.emplace_back( std::move( item ) );
1948 data.m_Items.emplace_back( std::move( item ) );
1964 data.m_Items.emplace_back( std::move( item ) );
1971 data.m_Items.emplace_back( std::move( item ) );
1978 data.m_Items.emplace_back( std::move( item ) );
1985 data.m_Items.emplace_back( std::move( item ) );
1994 data.m_Items.emplace_back( std::move( item ) );
2002 data.m_Items.emplace_back( std::move( item ) );
2005 default:
THROW_IO_ERROR( wxString::Format(
"Unknown substruct type %#02x in block 0x36", data.m_Code ) );
2015 auto block = std::make_unique<BLOCK<BLK_0x37_PTR_ARRAY>>( 0x37, aStream.
Position() );
2017 auto& data = block->GetData();
2019 data.m_T = aStream.
ReadU8();
2020 data.m_T2 = aStream.
ReadU16();
2021 data.m_Key = aStream.
ReadU32();
2022 data.m_Ptr1 = aStream.
ReadU32();
2023 data.m_Unknown1 = aStream.
ReadU32();
2024 data.m_Capacity = aStream.
ReadU32();
2025 data.m_Count = aStream.
ReadU32();
2026 data.m_Unknown2 = aStream.
ReadU32();
2030 ReadCond( aStream, aVer, data.m_UnknownArr );
2038 auto block = std::make_unique<BLOCK<BLK_0x38_FILM>>( 0x38, aStream.
Position() );
2040 auto& data = block->GetData();
2044 data.m_Key = aStream.
ReadU32();
2045 data.m_Next = aStream.
ReadU32();
2046 data.m_LayerList = aStream.
ReadU32();
2048 if( data.m_FilmName.exists( aVer ) )
2053 ReadCond( aStream, aVer, data.m_LayerNameStr );
2054 ReadCond( aStream, aVer, data.m_Unknown2 );
2056 for(
size_t i = 0; i < data.m_UnknownArray1.size(); ++i )
2058 data.m_UnknownArray1[i] = aStream.
ReadU32();
2061 ReadCond( aStream, aVer, data.m_Unknown3 );
2069 auto block = std::make_unique<BLOCK<BLK_0x39_FILM_LAYER_LIST>>( 0x39, aStream.
Position() );
2071 auto& data = block->GetData();
2075 data.m_Key = aStream.
ReadU32();
2076 data.m_Parent = aStream.
ReadU32();
2077 data.m_Head = aStream.
ReadU32();
2079 for(
size_t i = 0; i < data.m_X.size(); ++i )
2081 data.m_X[i] = aStream.
ReadU16();
2090 auto block = std::make_unique<BLOCK<BLK_0x3A_FILM_LIST_NODE>>( 0x3A, aStream.
Position() );
2092 auto& data = block->GetData();
2097 data.m_Key = aStream.
ReadU32();
2098 data.m_Next = aStream.
ReadU32();
2099 data.m_Unknown = aStream.
ReadU32();
2101 ReadCond( aStream, aVer, data.m_Unknown1 );
2109 auto block = std::make_unique<BLOCK<BLK_0x3B_PROPERTY>>( 0x3B, aStream.
Position() );
2111 auto& data = block->GetData();
2113 data.m_T = aStream.
ReadU8();
2114 data.m_SubType = aStream.
ReadU16();
2115 data.m_Len = aStream.
ReadU32();
2120 data.m_Unknown1 = aStream.
ReadU32();
2121 data.m_Unknown2 = aStream.
ReadU32();
2123 ReadCond( aStream, aVer, data.m_Unknown3 );
2133 auto block = std::make_unique<BLOCK<BLK_0x3C_KEY_LIST>>( 0x3C, aStream.
Position() );
2135 auto& data = block->GetData();
2137 data.m_T = aStream.
ReadU8();
2138 data.m_T2 = aStream.
ReadU16();
2139 data.m_Key = aStream.
ReadU32();
2141 ReadCond( aStream, aVer, data.m_Unknown );
2143 data.m_NumEntries = aStream.
ReadU32();
2145 if( data.m_NumEntries > 1000000 )
2148 "Block 0x3C entry count %u exceeds limit at offset %#010zx",
2149 data.m_NumEntries, aStream.
Position() ) );
2152 data.m_Entries.reserve( data.m_NumEntries );
2153 for( uint32_t i = 0; i < data.m_NumEntries; ++i )
2155 data.m_Entries.push_back( aStream.
ReadU32() );
2164 const size_t offset =
m_stream.Position();
2168 uint8_t type = 0x00;
2171 aEndOfObjectsMarker =
true;
2175 std::unique_ptr<BLOCK_BASE> block;
2331 wxString::Format(
"Current offset %#010zx is at or past the expected end of block 0x27 at %#010zx",
2445 aEndOfObjectsMarker =
true;
2458 const uint32_t magic = aBoard.
m_Header->m_Magic;
2470 auto lastRefresh = std::chrono::steady_clock::now();
2474 const size_t offset =
m_stream.Position();
2477 wxASSERT_MSG( offset % 4 == 0,
2478 wxString::Format(
"Allegro object at %#010zx, offset not aligned to 4 bytes", offset ) );
2483 uint8_t blockTypeByte = 0;
2487 bool endOfObjectsMarker =
false;
2488 std::unique_ptr<BLOCK_BASE> block = blockParser.
ParseBlock( endOfObjectsMarker );
2490 if( endOfObjectsMarker )
2496 size_t scanPos =
m_stream.Position();
2497 uint8_t nextByte = 0;
2499 while(
m_stream.GetU8( nextByte ) && nextByte == 0x00 )
2502 if( nextByte > 0x00 && nextByte <= 0x3C )
2504 size_t blockStart = scanPos;
2506 if( blockStart % 4 != 0 )
2507 blockStart -= ( blockStart % 4 );
2512 uint8_t alignedByte = 0;
2517 if( alignedByte == 0x00 || alignedByte > 0x3C )
2521 wxString::Format(
"V18 zero gap from %#010zx to %#010zx, "
2522 "continuing at block type %#04x",
2523 offset, blockStart, nextByte ) );
2531 wxString::Format(
"End of objects marker (0x00) at index %zu, offset %#010zx",
2543 "Do not have parser for block index %zu type %#02x available at offset %#010zx",
2549 wxString::Format(
"Ending at unknown block, index %zu type %#04x at offset %#010zx",
2552 wxFAIL_MSG(
"Failed to create block" );
2561 wxString::Format(
"Added block %zu, type %#04x from %#010zx to %#010zx",
2574 auto now = std::chrono::steady_clock::now();
2576 if( now - lastRefresh >= std::chrono::milliseconds( 100 ) )
2588template <
typename T>
2596 if constexpr( std::is_same_v<T, FILE_HEADER::LINKED_LIST> )
2600 else if constexpr( std::is_same_v<T, COND_FIELD_BASE<FILE_HEADER::LINKED_LIST>> )
2602 if( ll.has_value() )
2610 std::unique_ptr<BRD_DB> board = std::make_unique<BRD_DB>();
2625 if( !board->m_Header )
2634 board->m_Header->m_Magic );
2636 dumpLL(
"V18_1", board->m_Header->m_LL_V18_1 );
2637 dumpLL(
"V18_2", board->m_Header->m_LL_V18_2 );
2638 dumpLL(
"V18_3", board->m_Header->m_LL_V18_3 );
2639 dumpLL(
"V18_4", board->m_Header->m_LL_V18_4 );
2640 dumpLL(
"V18_5", board->m_Header->m_LL_V18_5 );
2642 dumpLL(
"0x04", board->m_Header->m_LL_0x04 );
2643 dumpLL(
"0x06", board->m_Header->m_LL_0x06 );
2644 dumpLL(
"0x0C", board->m_Header->m_LL_0x0C );
2645 dumpLL(
"Shapes", board->m_Header->m_LL_Shapes );
2646 dumpLL(
"0x14", board->m_Header->m_LL_0x14 );
2647 dumpLL(
"0x1B_Nets", board->m_Header->m_LL_0x1B_Nets );
2648 dumpLL(
"0x1C", board->m_Header->m_LL_0x1C );
2649 dumpLL(
"0x24_0x28", board->m_Header->m_LL_0x24_0x28 );
2650 dumpLL(
"Unknown1", board->m_Header->m_LL_Unknown1 );
2651 dumpLL(
"0x2B", board->m_Header->m_LL_0x2B );
2652 dumpLL(
"0x03_0x30", board->m_Header->m_LL_0x03_0x30 );
2653 dumpLL(
"0x0A", board->m_Header->m_LL_0x0A );
2654 dumpLL(
"0x1D_0x1E_0x1F", board->m_Header->m_LL_0x1D_0x1E_0x1F );
2655 dumpLL(
"Unknown2", board->m_Header->m_LL_Unknown2 );
2656 dumpLL(
"0x38", board->m_Header->m_LL_0x38 );
2657 dumpLL(
"0x2C", board->m_Header->m_LL_0x2C );
2658 dumpLL(
"0x0C_2", board->m_Header->m_LL_0x0C_2 );
2659 dumpLL(
"Unknown3", board->m_Header->m_LL_Unknown3 );
2660 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_preV18 );
2661 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_V18 );
2662 dumpLL(
"0x36", board->m_Header->m_LL_0x36 );
2663 dumpLL(
"Unknown6", board->m_Header->m_LL_Unknown6 );
2664 dumpLL(
"0x0A_2", board->m_Header->m_LL_0x0A_2 );
2666 dumpLL(
"V18_6", board->m_Header->m_LL_V18_6 );
2672 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2673 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2675 if( board->m_Header )
2676 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2678 s += wxString::Format(
"File magic: Unknown\n" );
2687 wxString verStr( board->m_Header->m_AllegroVersion.data(), 60 );
2691 _(
"This file was created with %s, which uses a binary format that "
2692 "predates Allegro 16.0 and is not supported by this importer.\n\n"
2693 "To import this design, open it in Cadence Allegro PCB Editor "
2694 "version 16.0 or later and re-save, then import the resulting file." ),
2698 const uint32_t stringsCount = board->m_Header->GetStringsCount();
2699 board->ReserveCapacity( board->m_Header->m_ObjectCount, stringsCount );
2703 board->SetLeanMode(
true );
2709 wxLogTrace(
traceAllegroPerf, wxT(
" ReadStringMap (%u strings): %.3f ms" ),
2710 stringsCount, parseTimer.
msecs(
true ) );
2714 wxLogTrace(
traceAllegroPerf, wxT(
" readObjects (%zu objects): %.3f ms" ),
2715 board->GetObjectCount(), parseTimer.
msecs(
true ) );
2720 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2721 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2723 if( board->m_Header )
2724 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2726 s += wxString::Format(
"File magic: Unknown\n" );
2732 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)
static FILE_HEADER::LINKED_LIST ReadLL(FILE_STREAM &aStream, FMT_VER aVer)
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 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)
void dumpLL(const char *name, const T &ll)
static void ReadStringMap(FILE_STREAM &stream, DB &aDb, uint32_t count)
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 database that represents a .brd file (amd presumably .dra)
std::unique_ptr< FILE_HEADER > m_Header
void InsertBlock(std::unique_ptr< BLOCK_BASE > aBlock) override
An ALLEGRO::DB is the represention of the actual data stored within an Allegro file,...
void AddString(uint32_t aKey, wxString &&aStr)
size_t GetObjectCount() const
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)
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
FMT_VER
The format of an Allego 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
std::array< uint32_t, 4 > m_Xs
COND_GE< FMT_VER::V_172, std::array< uint32_t, 8 > > m_Ys
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_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.
static const size_t STRING_TABLE_OFFSET
FMT_VER m_FmtVer
What version is this file?
A type that is always false.
wxString result
Test unit parsing edge cases and error handling.
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.