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;
180 uint32_t majorVer = ( aMagic >> 16 ) & 0xFFFF;
182 if( majorVer <= 0x0012 )
187 THROW_IO_ERRORF(
_(
"Unknown Allegro file version %#010x (rev %d)" ), aMagic, majorVer - 3 );
193 auto header = std::make_unique<ALLEGRO::FILE_HEADER>();
194 const size_t headerStartPos =
m_stream.Position();
196 uint32_t fileMagic =
m_stream.ReadU32();
199 header->m_Magic = fileMagic;
201 header->m_Unknown1a =
m_stream.ReadU32();
202 header->m_FileRole =
m_stream.ReadU32();
203 header->m_Unknown1b =
m_stream.ReadU32();
204 header->m_WriterProgram =
m_stream.ReadU32();
206 header->m_ObjectCount =
m_stream.ReadU32();
208 header->m_UnknownMagic =
m_stream.ReadU32();
209 header->m_UnknownFlags =
m_stream.ReadU32();
267 wxASSERT(
m_stream.Position() - headerStartPos == 0xF8 );
269 wxASSERT(
m_stream.Position() - headerStartPos == 0x124 );
271 wxASSERT(
m_stream.Position() - headerStartPos == 0x144 );
273 m_stream.ReadBytes( header->m_AllegroVersion.data(), header->m_AllegroVersion.size() );
274 header->m_Unknown4 =
m_stream.ReadU32();
275 header->m_MaxKey =
m_stream.ReadU32();
290 header->m_BoardUnits =
static_cast<BOARD_UNITS>( units );
300 header->m_Unknown6 =
m_stream.ReadU32();
305 header->m_Unknown8 =
m_stream.ReadU32();
311 header->m_Unknown10a =
m_stream.ReadU32();
312 header->m_Unknown10b =
m_stream.ReadU32();
313 header->m_Unknown10c =
m_stream.ReadU32();
315 header->m_UnitsDivisor =
m_stream.ReadU32();
319 for(
size_t i = 0; i < header->m_LayerMap.size(); ++i )
321 header->m_LayerMap[i].m_A =
m_stream.ReadU32();
322 header->m_LayerMap[i].m_LayerList0x2A =
m_stream.ReadU32();
325 wxLogTrace(
traceAllegroParser, wxT(
"Parsed header: %d objects, %d strings" ), header->m_ObjectCount,
326 header->GetStringsCount() );
336 static constexpr size_t STRING_TABLE_OFFSET = 0x1200;
338 stream.
Seek( STRING_TABLE_OFFSET );
340 for( uint32_t i = 0; i < count; ++i )
342 uint32_t
id = stream.
ReadU32();
352 uint8_t classCode = aStream.
ReadU8();
353 uint8_t subclassCode = aStream.
ReadU8();
358 .m_Class = classCode,
359 .m_Subclass = subclassCode,
366 auto block = std::make_unique<BLOCK<BLK_0x01_ARC>>( aStream.
Position() );
368 auto& data = block->GetData();
372 data.m_UnknownByte = aStream.
ReadU8();
373 data.m_SubType = aStream.
ReadU8();
374 data.m_Key = aStream.
ReadU32();
375 block->SetKey( data.m_Key );
376 data.m_Next = aStream.
ReadU32();
377 block->SetNext( data.m_Next );
378 data.m_Parent = aStream.
ReadU32();
379 data.m_Unknown1 = aStream.
ReadU32();
381 ReadCond( aStream, aVer, data.m_Unknown6 );
383 data.m_Width = aStream.
ReadU32();
385 data.m_StartX = aStream.
ReadS32();
386 data.m_StartY = aStream.
ReadS32();
387 data.m_EndX = aStream.
ReadS32();
388 data.m_EndY = aStream.
ReadS32();
394 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
396 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
405 auto block = std::make_unique<BLOCK<BLK_0x03_FIELD>>( aStream.
Position() );
407 auto& data = block->GetData();
411 data.m_Hdr1 = aStream.
ReadU16();
412 data.m_Key = aStream.
ReadU32();
413 block->SetKey( data.m_Key );
414 data.m_Next = aStream.
ReadU32();
415 block->SetNext( data.m_Next );
417 ReadCond( aStream, aVer, data.m_Unknown1 );
419 data.m_SubType = aStream.
ReadU8();
420 data.m_Hdr2 = aStream.
ReadU8();
421 data.m_Size = aStream.
ReadU16();
423 ReadCond( aStream, aVer, data.m_Unknown2 );
428 switch( data.m_SubType )
438 data.m_Substruct = aStream.
ReadU32();
443 data.m_Substruct = std::array<uint32_t, 2>{
468 THROW_IO_ERRORF( wxT(
"Block 0x03 subtype 0x6C entry count %u exceeds limit at offset %#010zx" ),
478 data.m_Substruct = std::move( sub );
489 const size_t numEntries = ( sub.
m_X1 + 4 * sub.
m_X0 );
491 for(
size_t i = 0; i < numEntries; ++i )
495 data.m_Substruct = std::move( sub );
501 for(
size_t i = 0; i < sub.
m_Entries.size(); ++i )
505 data.m_Substruct = std::move( sub );
510 if( data.m_Size == 4 )
512 data.m_Substruct = aStream.
ReadU32();
514 else if( data.m_Size == 8 )
516 std::array<uint32_t, 2> sub;
519 data.m_Substruct = std::move( sub );
523 THROW_IO_ERRORF( wxT(
"Unknown substruct type %#02x with size %d" ), data.m_SubType, data.m_Size );
535 auto block = std::make_unique<BLOCK<BLK_0x04_NET_ASSIGNMENT>>( aStream.
Position() );
537 auto& data = block->GetData();
539 data.m_Type = aStream.
ReadU8();
541 data.m_Key = aStream.
ReadU32();
542 block->SetKey( data.m_Key );
543 data.m_Next = aStream.
ReadU32();
544 block->SetNext( data.m_Next );
545 data.m_Net = aStream.
ReadU32();
546 data.m_ConnItem = aStream.
ReadU32();
548 ReadCond( aStream, aVer, data.m_Unknown );
556 auto block = std::make_unique<BLOCK<BLK_0x05_TRACK>>( aStream.
Position() );
558 auto& data = block->GetData();
563 data.m_Key = aStream.
ReadU32();
564 block->SetKey( data.m_Key );
565 data.m_Next = aStream.
ReadU32();
566 block->SetNext( data.m_Next );
567 data.m_NetAssignment = aStream.
ReadU32();
568 data.m_UnknownPtr1 = aStream.
ReadU32();
569 data.m_Unknown2 = aStream.
ReadU32();
570 data.m_Unknown3 = aStream.
ReadU32();
571 data.m_UnknownPtr2a = aStream.
ReadU32();
572 data.m_UnknownPtr2b = aStream.
ReadU32();
573 data.m_Unknown4 = aStream.
ReadU32();
574 data.m_UnknownPtr3a = aStream.
ReadU32();
575 data.m_UnknownPtr3b = aStream.
ReadU32();
577 ReadCond( aStream, aVer, data.m_Unknown5a );
578 ReadCond( aStream, aVer, data.m_Unknown5b );
580 data.m_FirstSegPtr = aStream.
ReadU32();
581 data.m_UnknownPtr5 = aStream.
ReadU32();
582 data.m_Unknown6 = aStream.
ReadU32();
590 auto block = std::make_unique<BLOCK<BLK_0x06_COMPONENT>>( stream.
Position() );
592 auto& data = block->GetData();
597 block->SetKey( data.m_Key );
598 data.m_Next = stream.
ReadU32();
599 block->SetNext( data.m_Next );
600 data.m_CompDeviceType = stream.
ReadU32();
601 data.m_SymbolName = stream.
ReadU32();
602 data.m_FirstInstPtr = stream.
ReadU32();
603 data.m_PtrFunctionSlot = stream.
ReadU32();
604 data.m_PtrPinNumber = stream.
ReadU32();
605 data.m_Fields = stream.
ReadU32();
607 ReadCond( stream, aVer, data.m_Unknown1 );
615 auto block = std::make_unique<BLOCK<BLK_0x07_COMPONENT_INST>>( stream.
Position() );
617 auto& data = block->GetData();
622 block->SetKey( data.m_Key );
623 data.m_Next = stream.
ReadU32();
624 block->SetNext( data.m_Next );
626 ReadCond( stream, aVer, data.m_UnknownPtr1 );
627 ReadCond( stream, aVer, data.m_Unknown2 );
628 ReadCond( stream, aVer, data.m_Unknown3 );
630 data.m_FpInstPtr = stream.
ReadU32();
632 ReadCond( stream, aVer, data.m_Unknown4 );
634 data.m_RefDesStrPtr = stream.
ReadU32();
635 data.m_FunctionInstPtr = stream.
ReadU32();
636 data.m_X03Ptr = stream.
ReadU32();
637 data.m_Unknown5 = stream.
ReadU32();
638 data.m_FirstPadPtr = stream.
ReadU32();
646 auto block = std::make_unique<BLOCK<BLK_0x08_PIN_NUMBER>>( aStream.
Position() );
648 auto& data = block->GetData();
650 data.m_Type = aStream.
ReadU8();
652 data.m_Key = aStream.
ReadU32();
653 block->SetKey( data.m_Key );
655 ReadCond( aStream, aVer, data.m_Previous );
656 ReadCond( aStream, aVer, data.m_StrPtr16x );
658 data.m_Next = aStream.
ReadU32();
659 block->SetNext( data.m_Next );
661 ReadCond( aStream, aVer, data.m_StrPtr );
663 data.m_PinNamePtr = aStream.
ReadU32();
665 ReadCond( aStream, aVer, data.m_Unknown1 );
667 data.m_Ptr4 = aStream.
ReadU32();
675 auto block = std::make_unique<BLOCK<BLK_0x09_FILL_LINK>>( aStream.
Position() );
677 auto& data = block->GetData();
681 data.m_Key = aStream.
ReadU32();
682 block->SetKey( data.m_Key );
684 for(
size_t i = 0; i < data.m_UnknownArray.size(); ++i )
686 data.m_UnknownArray[i] = aStream.
ReadU32();
689 ReadCond( aStream, aVer, data.m_Unknown1 );
691 data.m_UnknownPtr1 = aStream.
ReadU32();
692 data.m_UnknownPtr2 = aStream.
ReadU32();
693 data.m_Unknown2 = aStream.
ReadU32();
694 data.m_UnknownPtr3 = aStream.
ReadU32();
695 data.m_UnknownPtr4 = aStream.
ReadU32();
697 ReadCond( aStream, aVer, data.m_Unknown3 );
705 auto block = std::make_unique<BLOCK<BLK_0x0A_DRC>>( aStream.
Position() );
707 auto& data = block->GetData();
709 data.m_T = aStream.
ReadU8();
711 data.m_Key = aStream.
ReadU32();
712 block->SetKey( data.m_Key );
713 data.m_Next = aStream.
ReadU32();
714 block->SetNext( data.m_Next );
715 data.m_Unknown1 = aStream.
ReadU32();
717 ReadCond( aStream, aVer, data.m_Unknown2 );
719 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
721 data.m_Coords[i] = aStream.
ReadS32();
727 ReadCond( aStream, aVer, data.m_Unknown6 );
735 auto block = std::make_unique<BLOCK<BLK_0x0C_PIN_DEF>>( aStream.
Position() );
737 auto& data = block->GetData();
739 data.m_T = aStream.
ReadU8();
742 data.m_Key = aStream.
ReadU32();
743 block->SetKey( data.m_Key );
744 data.m_Next = aStream.
ReadU32();
745 block->SetNext( data.m_Next );
747 data.m_Unknown1 = aStream.
ReadU32();
748 data.m_Unknown2 = aStream.
ReadU32();
751 ReadCond( aStream, aVer, data.m_Shape );
752 ReadCond( aStream, aVer, data.m_DrillChar );
753 ReadCond( aStream, aVer, data.m_UnknownPadding );
756 ReadCond( aStream, aVer, data.m_Shape16x );
757 ReadCond( aStream, aVer, data.m_DrillChars );
758 ReadCond( aStream, aVer, data.m_Unknown_16x );
760 data.m_Unknown4 = aStream.
ReadU32();
761 ReadCond( aStream, aVer, data.m_Unknown5 );
763 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
765 data.m_Coords[i] = aStream.
ReadS32();
768 for(
size_t i = 0; i < data.m_Size.size(); ++i )
770 data.m_Size[i] = aStream.
ReadS32();
773 data.m_GroupPtr = aStream.
ReadU32();
774 data.m_Unknown6 = aStream.
ReadU32();
775 data.m_Unknown7 = aStream.
ReadU32();
777 ReadCond( aStream, aVer, data.m_Unknown8 );
785 auto block = std::make_unique<BLOCK<BLK_0x0D_PAD>>( aStream.
Position() );
787 auto& data = block->GetData();
791 data.m_Key = aStream.
ReadU32();
792 block->SetKey( data.m_Key );
793 data.m_NameStrId = aStream.
ReadU32();
794 data.m_Next = aStream.
ReadU32();
795 block->SetNext( data.m_Next );
797 ReadCond( aStream, aVer, data.m_Unknown1 );
799 data.m_CoordsX = aStream.
ReadS32();
800 data.m_CoordsY = aStream.
ReadS32();
802 data.m_PadStack = aStream.
ReadU32();
803 data.m_Unknown2 = aStream.
ReadU32();
805 ReadCond( aStream, aVer, data.m_Unknown3 );
807 data.m_Flags = aStream.
ReadU32();
808 data.m_Rotation = aStream.
ReadU32();
816 auto block = std::make_unique<BLOCK<BLK_0x0E_RECT>>( aStream.
Position() );
818 auto& data = block->GetData();
820 data.m_T = aStream.
ReadU8();
822 data.m_Key = aStream.
ReadU32();
823 block->SetKey( data.m_Key );
824 data.m_Next = aStream.
ReadU32();
825 block->SetNext( data.m_Next );
826 data.m_FpPtr = aStream.
ReadU32();
828 data.m_Unknown1 = aStream.
ReadU32();
829 data.m_Unknown2 = aStream.
ReadU32();
830 data.m_Unknown3 = aStream.
ReadU32();
832 ReadCond( aStream, aVer, data.m_Unknown4 );
833 ReadCond( aStream, aVer, data.m_Unknown5 );
835 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
837 data.m_Coords[i] = aStream.
ReadS32();
840 for(
size_t i = 0; i < data.m_UnknownArr.size(); ++i )
842 data.m_UnknownArr[i] = aStream.
ReadU32();
845 data.m_Rotation = aStream.
ReadU32();
853 auto block = std::make_unique<BLOCK<BLK_0x0F_FUNCTION_SLOT>>( stream.
Position() );
855 auto& data = block->GetData();
860 block->SetKey( data.m_Key );
861 data.m_SlotName = stream.
ReadU32();
863 ReadCond( stream, aVer, data.m_Unknown1 );
866 stream.
ReadBytes( data.m_CompDeviceType.data(), data.m_CompDeviceType.size() );
868 ReadCond( stream, aVer, data.m_CompDeviceTypePtr );
870 ReadCond( stream, aVer, data.m_Next );
871 block->SetNext( data.m_Next.value_or( 0 ) );
873 data.m_Ptr0x06 = stream.
ReadU32();
874 data.m_Ptr0x11 = stream.
ReadU32();
875 data.m_Unknown2 = stream.
ReadU32();
883 auto block = std::make_unique<BLOCK<BLK_0x10_FUNCTION_INST>>( stream.
Position() );
885 auto& data = block->GetData();
890 block->SetKey( data.m_Key );
892 ReadCond( stream, aVer, data.m_Unknown1 );
893 data.m_ComponentInstPtr = stream.
ReadU32();
894 ReadCond( stream, aVer, data.m_Unknown2 );
895 data.m_PtrX12 = stream.
ReadU32();
896 data.m_Unknown3 = stream.
ReadU32();
897 data.m_FunctionName = stream.
ReadU32();
898 data.m_Slots = stream.
ReadU32();
899 data.m_Fields = stream.
ReadU32();
907 auto block = std::make_unique<BLOCK<BLK_0x11_PIN_NAME>>( aStream.
Position() );
909 auto& data = block->GetData();
911 data.m_Type = aStream.
ReadU8();
913 data.m_Key = aStream.
ReadU32();
914 block->SetKey( data.m_Key );
915 data.m_PinNameStrPtr = aStream.
ReadU32();
916 data.m_Next = aStream.
ReadU32();
917 block->SetNext( data.m_Next );
918 data.m_PinNumberPtr = aStream.
ReadU32();
919 data.m_Unknown1 = aStream.
ReadU32();
921 ReadCond( aStream, aVer, data.m_Unknown2 );
929 auto block = std::make_unique<BLOCK<BLK_0x12_XREF>>( aStream.
Position() );
931 auto& data = block->GetData();
933 data.m_Type = aStream.
ReadU8();
935 data.m_Key = aStream.
ReadU32();
936 block->SetKey( data.m_Key );
937 data.m_Ptr1 = aStream.
ReadU32();
938 data.m_Ptr2 = aStream.
ReadU32();
939 data.m_Ptr3 = aStream.
ReadU32();
940 data.m_Unknown1 = aStream.
ReadU32();
942 ReadCond( aStream, aVer, data.m_Unknown2 );
943 ReadCond( aStream, aVer, data.m_Unknown3 );
951 auto block = std::make_unique<BLOCK<BLK_0x14_GRAPHIC>>( aStream.
Position() );
953 auto& data = block->GetData();
955 data.m_Type = aStream.
ReadU8();
957 data.m_Key = aStream.
ReadU32();
958 block->SetKey( data.m_Key );
959 data.m_Next = aStream.
ReadU32();
960 block->SetNext( data.m_Next );
961 data.m_Parent = aStream.
ReadU32();
962 data.m_Flags = aStream.
ReadU32();
964 ReadCond( aStream, aVer, data.m_Unknown2 );
966 data.m_SegmentPtr = aStream.
ReadU32();
967 data.m_Ptr0x03 = aStream.
ReadU32();
968 data.m_Ptr0x26 = aStream.
ReadU32();
976 auto block = std::make_unique<BLOCK<BLK_0x15_16_17_SEGMENT>>( aType, aStream.
Position() );
978 auto& data = block->GetData();
982 data.m_Key = aStream.
ReadU32();
983 block->SetKey( data.m_Key );
984 data.m_Next = aStream.
ReadU32();
985 block->SetNext( data.m_Next );
986 data.m_Parent = aStream.
ReadU32();
987 data.m_Flags = aStream.
ReadU32();
989 ReadCond( aStream, aVer, data.m_Unknown2 );
991 data.m_Width = aStream.
ReadU32();
993 data.m_StartX = aStream.
ReadS32();
994 data.m_StartY = aStream.
ReadS32();
995 data.m_EndX = aStream.
ReadS32();
996 data.m_EndY = aStream.
ReadS32();
1004 auto block = std::make_unique<BLOCK<BLK_0x1B_NET>>( stream.
Position() );
1006 auto& data = block->GetData();
1010 data.m_Key = stream.
ReadU32();
1011 block->SetKey( data.m_Key );
1012 data.m_Next = stream.
ReadU32();
1013 block->SetNext( data.m_Next );
1014 data.m_NetName = stream.
ReadU32();
1015 data.m_Unknown1 = stream.
ReadU32();
1017 ReadCond( stream, aVer, data.m_Unknown2 );
1019 data.m_Type = stream.
ReadU32();
1020 data.m_Assignment = stream.
ReadU32();
1021 data.m_Ratline = stream.
ReadU32();
1022 data.m_FieldsPtr = stream.
ReadU32();
1023 data.m_MatchGroupPtr = stream.
ReadU32();
1024 data.m_ModelPtr = stream.
ReadU32();
1025 data.m_UnknownPtr4 = stream.
ReadU32();
1026 data.m_UnknownPtr5 = stream.
ReadU32();
1027 data.m_UnknownPtr6 = stream.
ReadU32();
1036 switch( (aVal & 0xF0) )
1061 auto block = std::make_unique<BLOCK<BLK_0x1C_PADSTACK>>( aStream.
Position() );
1063 auto& data = block->GetData();
1065 data.m_UnknownByte1 = aStream.
ReadU8();
1066 data.m_N = aStream.
ReadU8();
1067 data.m_StartLayer = aStream.
ReadU8();
1069 data.m_Key = aStream.
ReadU32();
1070 block->SetKey( data.m_Key );
1071 data.m_Next = aStream.
ReadU32();
1072 block->SetNext( data.m_Next );
1073 data.m_PadStr = aStream.
ReadU32();
1116 uint8_t padTypeAndA = aStream.
ReadU8();
1118 hdr.
m_A = ( padTypeAndA & 0x0F );
1158 static const uint16_t MAX_LAYER_COUNT = 256;
1159 if( data.GetLayerCount() > MAX_LAYER_COUNT )
1160 throw std::runtime_error(
"Layer count exceeds maximum of " + std::to_string( MAX_LAYER_COUNT ) );
1164 data.m_NumFixedCompEntries = 10;
1166 data.m_NumFixedCompEntries = 11;
1168 data.m_NumFixedCompEntries = 21;
1173 const size_t nComps = data.m_NumFixedCompEntries + ( data.GetLayerCount() * data.m_NumCompsPerLayer );
1175 data.m_Components.reserve( nComps );
1176 for(
size_t i = 0; i < nComps; ++i )
1211 const size_t nElems = data.m_N * ( ( aVer <
FMT_VER::V_172 ) ? 8 : 10 );
1213 data.m_UnknownArrN.reserve( nElems );
1214 for(
size_t i = 0; i < nElems; ++i )
1216 data.m_UnknownArrN.push_back( aStream.
ReadU32() );
1226 auto block = std::make_unique<BLOCK<BLK_0x1D_CONSTRAINT_SET>>( aStream.
Position() );
1228 auto& data = block->GetData();
1232 data.m_Key = aStream.
ReadU32();
1233 block->SetKey( data.m_Key );
1234 data.m_Next = aStream.
ReadU32();
1235 block->SetNext( data.m_Next );
1236 data.m_NameStrKey = aStream.
ReadU32();
1237 data.m_FieldPtr = aStream.
ReadU32();
1239 data.m_SizeA = aStream.
ReadU16();
1240 data.m_SizeB = aStream.
ReadU16();
1242 data.m_DataB.resize( data.m_SizeB );
1244 for(
auto& item : data.m_DataB )
1245 aStream.
ReadBytes( item.data(), item.size() );
1247 data.m_DataA.resize( data.m_SizeA );
1249 for(
auto& item : data.m_DataA )
1250 aStream.
ReadBytes( item.data(), item.size() );
1252 ReadCond( aStream, aVer, data.m_Unknown4 );
1260 auto block = std::make_unique<BLOCK<BLK_0x1E_SI_MODEL>>( aStream.
Position() );
1262 auto& data = block->GetData();
1264 data.m_Type = aStream.
ReadU8();
1265 data.m_T2 = aStream.
ReadU16();
1266 data.m_Key = aStream.
ReadU32();
1267 block->SetKey( data.m_Key );
1268 data.m_Next = aStream.
ReadU32();
1269 block->SetNext( data.m_Next );
1271 ReadCond( aStream, aVer, data.m_Unknown2 );
1272 ReadCond( aStream, aVer, data.m_Unknown3 );
1274 data.m_StrPtr = aStream.
ReadU32();
1275 data.m_Size = aStream.
ReadU32();
1279 ReadCond( aStream, aVer, data.m_Unknown4 );
1287 auto block = std::make_unique<BLOCK<BLK_0x1F_PADSTACK_DIM>>( aStream.
Position() );
1289 auto& data = block->GetData();
1293 data.m_Key = aStream.
ReadU32();
1294 block->SetKey( data.m_Key );
1296 data.m_Next = aStream.
ReadU32();
1297 block->SetNext( data.m_Next );
1298 data.m_Unknown2 = aStream.
ReadU32();
1299 data.m_Unknown3 = aStream.
ReadU32();
1300 data.m_Unknown4 = aStream.
ReadU32();
1301 data.m_Unknown5 = aStream.
ReadU16();
1303 data.m_Size = aStream.
ReadU16();
1305 size_t substructSize = 0;
1307 substructSize = data.m_Size * 384 + 8;
1309 substructSize = data.m_Size * 280 + 8;
1311 substructSize = data.m_Size * 280 + 4;
1313 substructSize = data.m_Size * 240 + 4;
1315 data.m_Substruct.resize( substructSize );
1316 aStream.
ReadBytes( data.m_Substruct.data(), substructSize );
1324 auto block = std::make_unique<BLOCK<BLK_0x20_UNKNOWN>>( aStream.
Position() );
1326 auto& data = block->GetData();
1328 data.m_Type = aStream.
ReadU8();
1330 data.m_Key = aStream.
ReadU32();
1331 block->SetKey( data.m_Key );
1332 data.m_Next = aStream.
ReadU32();
1333 block->SetNext( data.m_Next );
1336 ReadCond( aStream, aVer, data.m_UnknownArray2 );
1344 auto block = std::make_unique<BLOCK<BLK_0x21_BLOB>>( aStream.
Position() );
1346 auto& data = block->GetData();
1348 data.m_Type = aStream.
ReadU8();
1351 data.m_Size = aStream.
ReadU32();
1353 if( data.m_Size < 12 )
1355 THROW_IO_ERRORF( wxT(
"Block 0x21 size %u too small (minimum 12) at offset %#010zx" ),
1359 data.m_Key = aStream.
ReadU32();
1360 block->SetKey( data.m_Key );
1362 const size_t nBytes = data.m_Size - 12;
1363 data.m_Data.resize( nBytes );
1364 aStream.
ReadBytes( data.m_Data.data(), nBytes );
1372 auto block = std::make_unique<BLOCK<BLK_0x22_UNKNOWN>>( aStream.
Position() );
1374 auto& data = block->GetData();
1376 data.m_Type = aStream.
ReadU8();
1377 data.m_T2 = aStream.
ReadU16();
1378 data.m_Key = aStream.
ReadU32();
1379 block->SetKey( data.m_Key );
1381 ReadCond( aStream, aVer, data.m_Unknown1 );
1391 auto block = std::make_unique<BLOCK<BLK_0x23_RATLINE>>( aStream.
Position() );
1393 auto& data = block->GetData();
1395 data.m_Type = aStream.
ReadU8();
1397 data.m_Key = aStream.
ReadU32();
1398 block->SetKey( data.m_Key );
1399 data.m_Next = aStream.
ReadU32();
1400 block->SetNext( data.m_Next );
1404 data.m_Ptr1 = aStream.
ReadU32();
1405 data.m_Ptr2 = aStream.
ReadU32();
1406 data.m_Ptr3 = aStream.
ReadU32();
1408 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1410 data.m_Coords[i] = aStream.
ReadS32();
1415 ReadCond( aStream, aVer, data.m_Unknown2 );
1416 ReadCond( aStream, aVer, data.m_Unknown3 );
1424 auto block = std::make_unique<BLOCK<BLK_0x24_RECT>>( aStream.
Position() );
1426 auto& data = block->GetData();
1428 data.m_Type = aStream.
ReadU8();
1430 data.m_Key = aStream.
ReadU32();
1431 block->SetKey( data.m_Key );
1432 data.m_Next = aStream.
ReadU32();
1433 block->SetNext( data.m_Next );
1434 data.m_Parent = aStream.
ReadU32();
1435 data.m_Unknown1 = aStream.
ReadU32();
1437 ReadCond( aStream, aVer, data.m_Unknown2 );
1439 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1441 data.m_Coords[i] = aStream.
ReadS32();
1444 data.m_Ptr2 = aStream.
ReadU32();
1446 data.m_Unknown3 = aStream.
ReadU32();
1447 data.m_Unknown4 = aStream.
ReadU32();
1448 data.m_Rotation = aStream.
ReadU32();
1456 auto block = std::make_unique<BLOCK<BLK_0x26_MATCH_GROUP>>( aStream.
Position() );
1458 auto& data = block->GetData();
1460 data.m_Type = aStream.
ReadU8();
1462 data.m_Key = aStream.
ReadU32();
1463 block->SetKey( data.m_Key );
1464 data.m_MemberPtr = aStream.
ReadU32();
1466 ReadCond( aStream, aVer, data.m_Unknown1 );
1468 data.m_GroupPtr = aStream.
ReadU32();
1469 data.m_ConstPtr = aStream.
ReadU32();
1471 ReadCond( aStream, aVer, data.m_Unknown2 );
1479 auto block = std::make_unique<BLOCK<BLK_0x27_CSTRMGR_XREF>>( aStream.
Position() );
1481 auto& data = block->GetData();
1483 const size_t totalBytes = aEndOff - 1 - aStream.
Position();
1486 constexpr size_t kPadding = 3;
1488 if( totalBytes <= kPadding )
1490 aStream.
Skip( totalBytes );
1494 aStream.
Skip( kPadding );
1496 const size_t payloadBytes = totalBytes - kPadding;
1497 const size_t numValues = payloadBytes / 4;
1498 const size_t remainder = payloadBytes % 4;
1500 data.m_Refs.resize( numValues );
1502 for(
size_t i = 0; i < numValues; i++ )
1503 data.m_Refs[i] = aStream.
ReadU32();
1506 aStream.
Skip( remainder );
1514 auto block = std::make_unique<BLOCK<BLK_0x28_SHAPE>>( aStream.
Position() );
1516 auto& data = block->GetData();
1518 data.m_Type = aStream.
ReadU8();
1520 data.m_Key = aStream.
ReadU32();
1521 block->SetKey( data.m_Key );
1522 data.m_Next = aStream.
ReadU32();
1523 block->SetNext( data.m_Next );
1524 data.m_Ptr1 = aStream.
ReadU32();
1525 data.m_Unknown1 = aStream.
ReadU32();
1527 ReadCond( aStream, aVer, data.m_Unknown2 );
1528 ReadCond( aStream, aVer, data.m_Unknown3 );
1530 data.m_Ptr2 = aStream.
ReadU32();
1531 data.m_Ptr3 = aStream.
ReadU32();
1532 data.m_FirstKeepoutPtr = aStream.
ReadU32();
1533 data.m_FirstSegmentPtr = aStream.
ReadU32();
1534 data.m_Unknown4 = aStream.
ReadU32();
1535 data.m_Unknown5 = aStream.
ReadU32();
1537 ReadCond( aStream, aVer, data.m_TablePtr );
1539 data.m_Ptr6 = aStream.
ReadU32();
1541 ReadCond( aStream, aVer, data.m_TablePtr_16x );
1543 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1545 data.m_Coords[i] = aStream.
ReadS32();
1554 auto block = std::make_unique<BLOCK<BLK_0x29_PIN>>( aStream.
Position() );
1556 auto& data = block->GetData();
1558 data.m_Type = aStream.
ReadU8();
1560 data.m_Key = aStream.
ReadU32();
1561 block->SetKey( data.m_Key );
1563 data.m_Ptr1 = aStream.
ReadU32();
1564 data.m_Ptr2 = aStream.
ReadU32();
1566 data.m_Null = aStream.
ReadU32();
1568 data.m_Ptr3 = aStream.
ReadU32();
1570 data.m_Coord1 = aStream.
ReadS32();
1571 data.m_Coord2 = aStream.
ReadS32();
1573 data.m_PtrPadstack = aStream.
ReadU32();
1575 data.m_Unknown1 = aStream.
ReadU32();
1577 data.m_PtrX30 = aStream.
ReadU32();
1579 data.m_Unknown2 = aStream.
ReadU32();
1580 data.m_Unknown3 = aStream.
ReadU32();
1581 data.m_Unknown4 = aStream.
ReadU32();
1589 auto block = std::make_unique<BLOCK<BLK_0x2A_LAYER_LIST>>( aStream.
Position() );
1591 auto& data = block->GetData();
1595 data.m_NumEntries = aStream.
ReadU16();
1597 ReadCond( aStream, aVer, data.m_Unknown );
1599 if( data.m_NonRefEntries.exists( aVer ) )
1601 data.m_NonRefEntries = std::vector<BLK_0x2A_LAYER_LIST::NONREF_ENTRY>();
1602 data.m_NonRefEntries->reserve( data.m_NumEntries );
1603 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1612 data.m_RefEntries = std::vector<BLK_0x2A_LAYER_LIST::REF_ENTRY>();
1613 data.m_RefEntries->reserve( data.m_NumEntries );
1614 for(
size_t i = 0; i < data.m_NumEntries; ++i )
1624 data.m_Key = aStream.
ReadU32();
1625 block->SetKey( data.m_Key );
1633 auto block = std::make_unique<BLOCK<BLK_0x2B_FOOTPRINT_DEF>>( stream.
Position() );
1635 auto& data = block->GetData();
1639 data.m_Key = stream.
ReadU32();
1640 block->SetKey( data.m_Key );
1641 data.m_FpStrRef = stream.
ReadU32();
1642 data.m_Unknown1 = stream.
ReadU32();
1644 data.m_Next = stream.
ReadU32();
1645 block->SetNext( data.m_Next );
1646 data.m_FirstInstPtr = stream.
ReadU32();
1647 data.m_UnknownPtr3 = stream.
ReadU32();
1648 data.m_UnknownPtr4 = stream.
ReadU32();
1649 data.m_UnknownPtr5 = stream.
ReadU32();
1650 data.m_FieldsPtr = stream.
ReadU32();
1651 data.m_UnknownPtr6 = stream.
ReadU32();
1652 data.m_UnknownPtr7 = stream.
ReadU32();
1653 data.m_UnknownPtr8 = stream.
ReadU32();
1655 ReadCond( stream, aVer, data.m_Unknown2 );
1656 ReadCond( stream, aVer, data.m_Unknown3 );
1664 auto block = std::make_unique<BLOCK<BLK_0x2C_TABLE>>( aStream.
Position() );
1666 auto& data = block->GetData();
1668 data.m_Type = aStream.
ReadU8();
1669 data.m_SubType = aStream.
ReadU16();
1670 data.m_Key = aStream.
ReadU32();
1671 block->SetKey( data.m_Key );
1672 data.m_Next = aStream.
ReadU32();
1673 block->SetNext( data.m_Next );
1675 ReadCond( aStream, aVer, data.m_Unknown1 );
1676 ReadCond( aStream, aVer, data.m_Unknown2 );
1677 ReadCond( aStream, aVer, data.m_Unknown3 );
1679 data.m_StringPtr = aStream.
ReadU32();
1681 ReadCond( aStream, aVer, data.m_Unknown4 );
1683 data.m_Ptr1 = aStream.
ReadU32();
1684 data.m_Ptr2 = aStream.
ReadU32();
1685 data.m_Ptr3 = aStream.
ReadU32();
1687 data.m_Flags = aStream.
ReadU32();
1695 auto block = std::make_unique<BLOCK<BLK_0x2D_FOOTPRINT_INST>>( stream.
Position() );
1697 auto& data = block->GetData();
1699 data.m_UnknownByte1 = stream.
ReadU8();
1700 data.m_Layer = stream.
ReadU8();
1701 data.m_UnknownByte2 = stream.
ReadU8();
1703 data.m_Key = stream.
ReadU32();
1704 block->SetKey( data.m_Key );
1705 data.m_Next = stream.
ReadU32();
1706 block->SetNext( data.m_Next );
1708 ReadCond( stream, aVer, data.m_Unknown1 );
1710 ReadCond( stream, aVer, data.m_InstRef16x );
1712 data.m_Unknown2 = stream.
ReadU16();
1713 data.m_Unknown3 = stream.
ReadU16();
1715 ReadCond( stream, aVer, data.m_Unknown4 );
1717 data.m_Flags = stream.
ReadU32();
1719 data.m_Rotation = stream.
ReadU32();
1720 data.m_CoordX = stream.
ReadS32();
1721 data.m_CoordY = stream.
ReadS32();
1723 ReadCond( stream, aVer, data.m_InstRef );
1725 data.m_GraphicPtr = stream.
ReadU32();
1726 data.m_FirstPadPtr = stream.
ReadU32();
1727 data.m_TextPtr = stream.
ReadU32();
1729 data.m_AssemblyPtr = stream.
ReadU32();
1730 data.m_AreasPtr = stream.
ReadU32();
1731 data.m_UnknownPtr1 = stream.
ReadU32();
1732 data.m_UnknownPtr2 = stream.
ReadU32();
1740 auto block = std::make_unique<BLOCK<BLK_0x2E_CONNECTION>>( aStream.
Position() );
1742 auto& data = block->GetData();
1744 data.m_Type = aStream.
ReadU8();
1745 data.m_T2 = aStream.
ReadU16();
1746 data.m_Key = aStream.
ReadU32();
1747 block->SetKey( data.m_Key );
1748 data.m_Next = aStream.
ReadU32();
1749 block->SetNext( data.m_Next );
1750 data.m_NetAssignment = aStream.
ReadU32();
1751 data.m_Unknown1 = aStream.
ReadU32();
1752 data.m_CoordX = aStream.
ReadU32();
1753 data.m_CoordY = aStream.
ReadU32();
1754 data.m_Connection = aStream.
ReadU32();
1755 data.m_Unknown2 = aStream.
ReadU32();
1757 ReadCond( aStream, aVer, data.m_Unknown3 );
1765 auto block = std::make_unique<BLOCK<BLK_0x2F_UNKNOWN>>( aStream.
Position() );
1767 auto& data = block->GetData();
1769 data.m_Type = aStream.
ReadU8();
1770 data.m_T2 = aStream.
ReadU16();
1771 data.m_Key = aStream.
ReadU32();
1772 block->SetKey( data.m_Key );
1787 uint8_t alignment = aStream.
ReadU8();
1799 uint8_t reversal = aStream.
ReadU8();
1816 auto block = std::make_unique<BLOCK<BLK_0x30_STR_WRAPPER>>( aStream.
Position() );
1818 auto& data = block->GetData();
1820 data.m_Type = aStream.
ReadU8();
1822 data.m_Key = aStream.
ReadU32();
1823 block->SetKey( data.m_Key );
1824 data.m_Next = aStream.
ReadU32();
1825 block->SetNext( data.m_Next );
1827 ReadCond( aStream, aVer, data.m_Unknown1 );
1828 ReadCond( aStream, aVer, data.m_Unknown2 );
1830 if( data.m_Font.exists( aVer ) )
1835 ReadCond( aStream, aVer, data.m_Ptr1 );
1836 ReadCond( aStream, aVer, data.m_Unknown3 );
1838 data.m_StrGraphicPtr = aStream.
ReadU32();
1840 ReadCond( aStream, aVer, data.m_PtrGroup_17x );
1841 ReadCond( aStream, aVer, data.m_Unknown4 );
1843 if( data.m_Font16x.exists( aVer ) )
1848 ReadCond( aStream, aVer, data.m_Ptr2 );
1850 data.m_CoordsX = aStream.
ReadU32();
1851 data.m_CoordsY = aStream.
ReadU32();
1853 data.m_Unknown5 = aStream.
ReadU32();
1854 data.m_Rotation = aStream.
ReadU32();
1856 ReadCond( aStream, aVer, data.m_PtrGroup_16x );
1864 auto block = std::make_unique<BLOCK<BLK_0x31_SGRAPHIC>>( aStream.
Position() );
1866 auto& data = block->GetData();
1868 data.m_T = aStream.
ReadU8();
1871 const uint16_t layer = aStream.
ReadU16();
1886 data.m_Key = aStream.
ReadU32();
1887 block->SetKey( data.m_Key );
1888 data.m_StrGraphicWrapperPtr = aStream.
ReadU32();
1890 data.m_CoordsX = aStream.
ReadU32();
1891 data.m_CoordsY = aStream.
ReadU32();
1893 data.m_Unknown = aStream.
ReadU16();
1894 data.m_Len = aStream.
ReadU16();
1896 ReadCond( aStream, aVer, data.m_Un2 );
1906 auto block = std::make_unique<BLOCK<BLK_0x32_PLACED_PAD>>( aStream.
Position() );
1908 auto& data = block->GetData();
1910 data.m_Type = aStream.
ReadU8();
1912 data.m_Key = aStream.
ReadU32();
1913 block->SetKey( data.m_Key );
1914 data.m_Next = aStream.
ReadU32();
1915 block->SetNext( data.m_Next );
1916 data.m_NetPtr = aStream.
ReadU32();
1917 data.m_Flags = aStream.
ReadU32();
1919 ReadCond( aStream, aVer, data.m_Prev );
1921 data.m_NextInFp = aStream.
ReadU32();
1922 data.m_ParentFp = aStream.
ReadU32();
1923 data.m_Track = aStream.
ReadU32();
1924 data.m_PadPtr = aStream.
ReadU32();
1925 data.m_Ptr6 = aStream.
ReadU32();
1926 data.m_Ratline = aStream.
ReadU32();
1927 data.m_PtrPinNumber = aStream.
ReadU32();
1928 data.m_NextInCompInst = aStream.
ReadU32();
1930 ReadCond( aStream, aVer, data.m_Unknown2 );
1932 data.m_NameText = aStream.
ReadU32();
1933 data.m_Ptr11 = aStream.
ReadU32();
1935 for(
size_t i = 0; i < data.m_Coords.size(); ++i )
1937 data.m_Coords[i] = aStream.
ReadS32();
1946 auto block = std::make_unique<BLOCK<BLK_0x33_VIA>>( aStream.
Position() );
1948 auto& data = block->GetData();
1953 data.m_Key = aStream.
ReadU32();
1954 block->SetKey( data.m_Key );
1955 data.m_Next = aStream.
ReadU32();
1956 block->SetNext( data.m_Next );
1957 data.m_NetPtr = aStream.
ReadU32();
1958 data.m_Unknown2 = aStream.
ReadU32();
1960 ReadCond( aStream, aVer, data.m_Unknown3 );
1962 data.m_UnknownPtr1 = aStream.
ReadU32();
1964 ReadCond( aStream, aVer, data.m_UnknownPtr2 );
1966 data.m_CoordsX = aStream.
ReadS32();
1967 data.m_CoordsY = aStream.
ReadS32();
1969 data.m_Connection = aStream.
ReadU32();
1970 data.m_Padstack = aStream.
ReadU32();
1971 data.m_UnknownPtr5 = aStream.
ReadU32();
1972 data.m_UnknownPtr6 = aStream.
ReadU32();
1974 data.m_Unknown4 = aStream.
ReadU32();
1975 data.m_Unknown5 = aStream.
ReadU32();
1977 for(
size_t i = 0; i < data.m_BoundingBoxCoords.size(); ++i )
1979 data.m_BoundingBoxCoords[i] = aStream.
ReadS32();
1988 auto block = std::make_unique<BLOCK<BLK_0x34_KEEPOUT>>( aStream.
Position() );
1990 auto& data = block->GetData();
1992 data.m_T = aStream.
ReadU8();
1994 data.m_Key = aStream.
ReadU32();
1995 block->SetKey( data.m_Key );
1996 data.m_Next = aStream.
ReadU32();
1997 block->SetNext( data.m_Next );
1998 data.m_Ptr1 = aStream.
ReadU32();
2000 ReadCond( aStream, aVer, data.m_Unknown1 );
2002 data.m_Flags = aStream.
ReadU32();
2003 data.m_FirstSegmentPtr = aStream.
ReadU32();
2004 data.m_Ptr3 = aStream.
ReadU32();
2005 data.m_Unknown2 = aStream.
ReadU32();
2013 auto block = std::make_unique<BLOCK<BLK_0x35_FILE_REF>>( aStream.
Position() );
2015 auto& data = block->GetData();
2017 data.m_T2 = aStream.
ReadU8();
2018 data.m_T3 = aStream.
ReadU16();
2019 aStream.
ReadBytes( data.m_Content.data(), data.m_Content.size() );
2027 auto block = std::make_unique<BLOCK<BLK_0x36_DEF_TABLE>>( aStream.
Position() );
2029 auto& data = block->GetData();
2033 data.m_Code = aStream.
ReadU16();
2034 data.m_Key = aStream.
ReadU32();
2035 block->SetKey( data.m_Key );
2036 data.m_Next = aStream.
ReadU32();
2037 block->SetNext( data.m_Next );
2039 ReadCond( aStream, aVer, data.m_Unknown1 );
2041 data.m_NumItems = aStream.
ReadU32();
2042 data.m_Count = aStream.
ReadU32();
2043 data.m_LastIdx = aStream.
ReadU32();
2044 data.m_Unknown2 = aStream.
ReadU32();
2046 ReadCond( aStream, aVer, data.m_Unknown3 );
2048 if( data.m_NumItems > 1000000 )
2050 THROW_IO_ERRORF( wxT(
"Block 0x36 item count %u exceeds limit at offset %#010zx" ),
2055 if( data.m_Count > data.m_NumItems )
2057 THROW_IO_ERRORF( wxT(
"Block 0x36 filled count %u exceeds capacity %u at offset %#010zx" ),
2066 data.m_Items.reserve( data.m_Count );
2067 for( uint32_t i = 0; i < data.m_NumItems; ++i )
2069 const bool keep = i < data.m_Count;
2071 switch( data.m_Code )
2083 data.m_Items.emplace_back( std::move( item ) );
2097 data.m_Items.emplace_back( std::move( item ) );
2108 data.m_Items.emplace_back( std::move( item ) );
2123 data.m_Items.emplace_back( std::move( item ) );
2145 data.m_Items.emplace_back( std::move( item ) );
2153 data.m_Items.emplace_back( std::move( item ) );
2161 data.m_Items.emplace_back( std::move( item ) );
2169 data.m_Items.emplace_back( std::move( item ) );
2180 data.m_Items.emplace_back( std::move( item ) );
2191 data.m_Items.emplace_back( std::move( item ) );
2199 aStream.
Skip( 1052 );
2202 data.m_Items.emplace_back( std::move( item ) );
2206 default:
THROW_IO_ERRORF( wxT(
"Unknown substruct type %#02x in block 0x36" ), data.m_Code );
2216 auto block = std::make_unique<BLOCK<BLK_0x37_PTR_ARRAY>>( aStream.
Position() );
2218 auto& data = block->GetData();
2220 data.m_T = aStream.
ReadU8();
2221 data.m_T2 = aStream.
ReadU16();
2222 data.m_Key = aStream.
ReadU32();
2223 block->SetKey( data.m_Key );
2224 data.m_GroupPtr = aStream.
ReadU32();
2225 data.m_Next = aStream.
ReadU32();
2226 block->SetNext( data.m_Next );
2227 data.m_Capacity = aStream.
ReadU32();
2228 data.m_Count = aStream.
ReadU32();
2229 data.m_Unknown2 = aStream.
ReadU32();
2231 ReadCond( aStream, aVer, data.m_Unknown3 );
2241 auto block = std::make_unique<BLOCK<BLK_0x38_FILM>>( aStream.
Position() );
2243 auto& data = block->GetData();
2247 data.m_Key = aStream.
ReadU32();
2248 block->SetKey( data.m_Key );
2249 data.m_Next = aStream.
ReadU32();
2250 block->SetNext( data.m_Next );
2251 data.m_LayerList = aStream.
ReadU32();
2253 if( data.m_FilmName.exists( aVer ) )
2258 ReadCond( aStream, aVer, data.m_LayerNameStr );
2259 ReadCond( aStream, aVer, data.m_Unknown2 );
2261 for(
size_t i = 0; i < data.m_UnknownArray1.size(); ++i )
2263 data.m_UnknownArray1[i] = aStream.
ReadU32();
2266 ReadCond( aStream, aVer, data.m_Unknown3 );
2274 auto block = std::make_unique<BLOCK<BLK_0x39_FILM_LAYER_LIST>>( aStream.
Position() );
2276 auto& data = block->GetData();
2280 data.m_Key = aStream.
ReadU32();
2281 block->SetKey( data.m_Key );
2282 data.m_Parent = aStream.
ReadU32();
2283 data.m_Head = aStream.
ReadU32();
2285 for(
size_t i = 0; i < data.m_X.size(); ++i )
2287 data.m_X[i] = aStream.
ReadU16();
2296 auto block = std::make_unique<BLOCK<BLK_0x3A_FILM_LIST_NODE>>( aStream.
Position() );
2298 auto& data = block->GetData();
2303 data.m_Key = aStream.
ReadU32();
2304 block->SetKey( data.m_Key );
2305 data.m_Next = aStream.
ReadU32();
2306 block->SetNext( data.m_Next );
2307 data.m_Unknown = aStream.
ReadU32();
2309 ReadCond( aStream, aVer, data.m_Unknown1 );
2317 auto block = std::make_unique<BLOCK<BLK_0x3B_PROPERTY>>( aStream.
Position() );
2319 auto& data = block->GetData();
2321 data.m_T = aStream.
ReadU8();
2322 data.m_SubType = aStream.
ReadU16();
2323 data.m_Len = aStream.
ReadU32();
2328 data.m_Unknown1 = aStream.
ReadU32();
2329 data.m_Unknown2 = aStream.
ReadU32();
2331 ReadCond( aStream, aVer, data.m_Unknown3 );
2341 auto block = std::make_unique<BLOCK<BLK_0x3E>>( aStream.
Position() );
2343 auto& data = block->GetData();
2347 data.m_Key = aStream.
ReadU32();
2348 block->SetKey( data.m_Key );
2350 for( uint32_t& word : data.m_Unknown )
2359 auto block = std::make_unique<BLOCK<BLK_0x3C_KEY_LIST>>( aStream.
Position() );
2361 auto& data = block->GetData();
2363 data.m_T = aStream.
ReadU8();
2364 data.m_T2 = aStream.
ReadU16();
2365 data.m_Key = aStream.
ReadU32();
2366 block->SetKey( data.m_Key );
2368 ReadCond( aStream, aVer, data.m_Unknown );
2370 data.m_NumEntries = aStream.
ReadU32();
2372 if( data.m_NumEntries > 1000000 )
2374 THROW_IO_ERRORF( wxT(
"Block 0x3C entry count %u exceeds limit at offset %#010zx" ),
2379 data.m_Entries.reserve( data.m_NumEntries );
2381 for( uint32_t i = 0; i < data.m_NumEntries; ++i )
2382 data.m_Entries.push_back( aStream.
ReadU32() );
2392 uint8_t type = 0x00;
2395 aEndOfObjectsMarker =
true;
2399 std::unique_ptr<BLOCK_BASE> block;
2554 THROW_IO_ERRORF( wxT(
"Current offset %#010zx is at or past the expected end of block 0x27 at %#010zx" ),
2674 aEndOfObjectsMarker =
true;
2698 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
2702 const size_t offset =
m_stream.Position();
2705 wxASSERT_MSG( offset % 4 == 0,
2706 wxString::Format(
"Allegro object at %#010zx, offset not aligned to 4 bytes", offset ) );
2711 uint8_t blockTypeByte = 0;
2715 bool endOfObjectsMarker =
false;
2716 std::unique_ptr<BLOCK_BASE> block = blockParser.
ParseBlock( endOfObjectsMarker );
2718 if( endOfObjectsMarker )
2724 size_t scanPos =
m_stream.Position();
2725 uint8_t nextByte = 0;
2727 while(
m_stream.GetU8( nextByte ) && nextByte == 0x00 )
2730 if( nextByte > 0x00 && nextByte <= 0x3E )
2732 size_t blockStart = scanPos;
2734 if( blockStart % 4 != 0 )
2735 blockStart -= ( blockStart % 4 );
2740 uint8_t alignedByte = 0;
2745 if( alignedByte == 0x00 || alignedByte > 0x3E )
2749 wxString::Format(
"V18 zero gap from %#010zx to %#010zx, "
2750 "continuing at block type %#04x",
2751 offset, blockStart, nextByte ) );
2759 wxString::Format(
"End of objects marker (0x00) at index %zu, offset %#010zx",
2770 THROW_IO_ERRORF( wxT(
"Do not have parser for block index %zu type %#02x available at offset %#010zx" ),
2778 wxString::Format(
"Ending at unknown block, index %zu type %#04x at offset %#010zx",
2781 wxFAIL_MSG(
"Failed to create block" );
2788 wxString::Format(
"Added block %zu, type %#04x from %#010zx to %#010zx",
2806template <
typename T>
2809 if constexpr( std::is_same_v<T, FILE_HEADER::LINKED_LIST> )
2813 else if constexpr( VERSIONED_COND_FIELD<T> && std::is_same_v<typename T::value_type, FILE_HEADER::LINKED_LIST> )
2815 if( aLL.has_value() )
2823 std::unique_ptr<BRD_DB> board = std::make_unique<BRD_DB>();
2838 if( !board->m_Header )
2844 wxLogTrace(
traceAllegroParser,
"Header linked lists (ver=%#010x):", board->m_Header->m_Magic );
2846 dumpLL(
"V18_1", board->m_Header->m_LL_V18_1 );
2847 dumpLL(
"V18_2", board->m_Header->m_LL_V18_2 );
2848 dumpLL(
"V18_3", board->m_Header->m_LL_V18_3 );
2849 dumpLL(
"V18_4", board->m_Header->m_LL_V18_4 );
2850 dumpLL(
"V18_5", board->m_Header->m_LL_V18_5 );
2852 dumpLL(
"0x04", board->m_Header->m_LL_0x04 );
2853 dumpLL(
"0x06", board->m_Header->m_LL_0x06 );
2854 dumpLL(
"0x0C", board->m_Header->m_LL_0x0C );
2855 dumpLL(
"Shapes", board->m_Header->m_LL_Shapes );
2856 dumpLL(
"0x14", board->m_Header->m_LL_0x14 );
2857 dumpLL(
"0x1B_Nets", board->m_Header->m_LL_0x1B_Nets );
2858 dumpLL(
"0x1C", board->m_Header->m_LL_0x1C );
2859 dumpLL(
"0x24_0x28", board->m_Header->m_LL_0x24_0x28 );
2860 dumpLL(
"Unknown1", board->m_Header->m_LL_Unknown1 );
2861 dumpLL(
"0x2B", board->m_Header->m_LL_0x2B );
2862 dumpLL(
"0x03_0x30", board->m_Header->m_LL_0x03_0x30 );
2863 dumpLL(
"0x0A", board->m_Header->m_LL_0x0A );
2864 dumpLL(
"0x1D_0x1E_0x1F", board->m_Header->m_LL_0x1D_0x1E_0x1F );
2865 dumpLL(
"Unknown2", board->m_Header->m_LL_Unknown2 );
2866 dumpLL(
"0x38", board->m_Header->m_LL_0x38 );
2867 dumpLL(
"0x2C", board->m_Header->m_LL_0x2C );
2868 dumpLL(
"0x0C_2", board->m_Header->m_LL_0x0C_2 );
2869 dumpLL(
"Unknown3", board->m_Header->m_LL_Unknown3 );
2870 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_preV18 );
2871 dumpLL(
"Unknown5", board->m_Header->m_LL_Unknown5_V18 );
2872 dumpLL(
"0x36", board->m_Header->m_LL_0x36 );
2873 dumpLL(
"Unknown6", board->m_Header->m_LL_Unknown6 );
2874 dumpLL(
"0x0A_2", board->m_Header->m_LL_0x0A_2 );
2876 dumpLL(
"V18_6", board->m_Header->m_LL_V18_6 );
2882 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2883 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2885 if( board->m_Header )
2886 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2888 s += wxString::Format(
"File magic: Unknown\n" );
2897 wxString verStr( board->m_Header->m_AllegroVersion.data(), 60 );
2900 THROW_IO_ERRORF(
_(
"This file was created with %s, which uses a binary format that predates Allegro 16.0 "
2901 "and is not supported by this importer.\n\n"
2902 "To import this design, open it in Cadence Allegro PCB Editor version 16.0 or later "
2903 "and re-save, then import the resulting file." ), verStr );
2906 const uint32_t stringsCount = board->m_Header->GetStringsCount();
2907 board->ReserveCapacity( board->m_Header->m_ObjectCount, stringsCount,
m_stream.Size() );
2913 wxLogTrace(
traceAllegroPerf, wxT(
" ReadStringMap (%u strings): %.3f ms" ),
2914 stringsCount, parseTimer.
msecs(
true ) );
2918 wxLogTrace(
traceAllegroPerf, wxT(
" readObjects (%zu objects): %.3f ms" ),
2919 board->GetObjectCount(), parseTimer.
msecs(
true ) );
2924 s += wxString::Format(
"Error parsing Allegro file: %s\n", e.
What() );
2925 s += wxString::Format(
"Stream position: %#010lx\n",
m_stream.Position() );
2927 if( board->m_Header )
2928 s += wxString::Format(
"File magic: %#010x\n", board->m_Header->m_Magic );
2930 s += wxString::Format(
"File magic: Unknown\n" );
2936 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_0x3E(FILE_STREAM &aStream, FMT_VER aVer)
static std::unique_ptr< BLOCK_BASE > ParseBlock_0x30_STR_WRAPPER(FILE_STREAM &aStream, FMT_VER aVer)
The block parser is responsible for parsing individual blocks of data from the file stream.
std::unique_ptr< BLOCK_BASE > ParseBlock(bool &aEndOfObjectsMarker)
Parse one block from the stream, returning a BLOCK_BASE representing the raw data of the block.
const size_t m_x27_end
To parse an 0x27 block, we need to know where the end of the block is in the stream.
An Allegro board database representing the contents of a .brd (and presumably .dra) file.
std::unique_ptr< FILE_HEADER > m_Header
size_t GetObjectCount() const
void InsertBlock(std::unique_ptr< BLOCK_BASE > aBlock)
void AddString(uint32_t aKey, wxString &&aStr)
Stream that reads primitive types from a memory buffer containing Allegro .brd (or ....
void ReadBytes(void *aDest, size_t aSize)
Read a number of bytes from the stream into the destination buffer.
std::string ReadString(bool aRoundToNextU32)
std::string ReadStringFixed(size_t aLen, bool aRoundToNextU32)
PROGRESS_REPORTER * m_progressReporter
void readObjects(BRD_DB &aDb)
std::unique_ptr< BRD_DB > Parse()
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A small class to help profiling.
double msecs(bool aSinceLast=false)
Rate-limiter that fires at most once per interval.
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
#define THROW_IO_ERRORF(msg,...)
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_LT< FMT_VER::V_174, FMT_VER::V_190, uint32_t > m_Unknown2
std::array< uint32_t, 14 > m_Xs
COND_GE< FMT_VER::V_172, std::array< uint32_t, 2 > > m_Zs
COND_GE< FMT_VER::V_164, std::array< uint32_t, 3 > > m_Ys
COND_GE< FMT_VER::V_172, std::string > m_Str
COND_GE< FMT_VER::V_174, uint32_t > m_Unknown1
COND_LT< FMT_VER::V_172, std::string > m_Str16x
std::array< uint8_t, 28 > m_Unknown
COND_GE< FMT_VER::V_175, uint32_t > m_Unknown2
COND_LT< FMT_VER::V_172, std::array< uint32_t, 50 > > m_Unknown2
std::array< uint8_t, 1016 > m_Unknown
std::array< uint8_t, 232 > m_Unknown
std::array< uint8_t, 200 > m_Unknown
std::array< uint32_t, 3 > m_Ptrs
std::array< uint8_t, 108 > m_Unknown
COND_GE< FMT_VER::V_180, uint32_t > m_Unknown2
Substruct in a padstack object.
A type that is always false.
wxString result
Test unit parsing edge cases and error handling.