@@ -23,6 +23,18 @@ namespace RC::OutTheShade
2323{
2424 using namespace ::RC::Unreal;
2525
26+ enum class EUsmapVersion : uint8_t
27+ {
28+ Initial = 0 ,
29+ PackageVersioning = 1 ,
30+ LongFName = 2 ,
31+ LargeEnums = 3 ,
32+ ExplicitEnumValues = 4 ,
33+
34+ Latest = ExplicitEnumValues,
35+ LatestPlusOne
36+ };
37+
2638 enum class EPropertyType : uint8_t
2739 {
2840 ByteProperty,
@@ -349,8 +361,8 @@ namespace RC::OutTheShade
349361 NameView = NameView.substr (Find + 2 );
350362 }
351363
352- // Warning: Converting size_t (uint64) to uint8_t.
353- Buffer.Write <uint8_t >(static_cast <uint8_t >(NameView.length ()));
364+ // LongFName support (version >= 2): use uint16 for name lengths
365+ Buffer.Write <uint16_t >(static_cast <uint16_t >(NameView.length ()));
354366 Buffer.WriteString (NameView);
355367
356368 CurrentNameIndex++;
@@ -363,20 +375,19 @@ namespace RC::OutTheShade
363375 {
364376 Buffer.Write (NameMap[Enum->GetNamePrivate ()]);
365377
366- // limit to 255 entries; why is this a byte in the first place?
367- uint8_t EnumNameCount{};
378+ // LargeEnums support (version >= 3): use uint16 for enum member counts
379+ uint16_t EnumNameCount{};
368380 for (auto _ : Enum->ForEachName ())
369381 {
370382 ++EnumNameCount;
371- if (EnumNameCount >= std::numeric_limits<uint8_t >::max ()) break ;
372383 }
373- Buffer.Write <uint8_t >(EnumNameCount);
384+ Buffer.Write <uint16_t >(EnumNameCount);
374385
375- int numSoFar = 0 ;
376- for (auto & [Key, _ ] : Enum->ForEachName ())
386+ // ExplicitEnumValues (version >= 4): write value then name index
387+ for (auto & [Key, Value ] : Enum->ForEachName ())
377388 {
378- Buffer.Write <uint32_t >(NameMap[Key]);
379- if (++numSoFar >= EnumNameCount) break ;
389+ Buffer.Write <int64_t >(Value); // explicit enum value
390+ Buffer. Write < int32_t >(NameMap[Key]); // name index
380391 }
381392 }
382393
@@ -421,7 +432,7 @@ namespace RC::OutTheShade
421432 Buffer.Write <uint32_t >(0x54584543 ); // "CEXT"; magic
422433 Buffer.Write <uint8_t >(0 ); // extensions layout version; 0 (Initial)
423434
424- Buffer.Write <uint32_t >(3 ); // number of extensions, 3 right now
435+ Buffer.Write <uint32_t >(2 ); // number of extensions (ENVP removed - now redundant with ExplicitEnumValues)
425436
426437 // extension 1: PPTH (object paths)
427438 Buffer.Write <uint32_t >(0x48545050 ); // ext id
@@ -490,32 +501,7 @@ namespace RC::OutTheShade
490501 Buffer.Write <uint32_t >(extEndPos - extStartPos);
491502 Buffer.GetBuffer ().seekp (extEndPos);
492503
493- // extension 3: ENVP (enum name/value pairs)
494- Buffer.Write <uint32_t >(0x50564E45 ); // ext id
495- Buffer.Write <uint32_t >(0 ); // size; unknown for now
496-
497- extStartPos = Buffer.GetBuffer ().tellp ();
498- Buffer.Write <uint8_t >(0 ); // ENVP version; 0
499- Buffer.Write <uint32_t >(static_cast <uint32_t >(Enums.size ()));
500- for (auto Enum : Enums)
501- {
502- uint32_t EnumNameCount = 0 ;
503- for (auto _ : Enum->ForEachName ())
504- ++EnumNameCount;
505- Buffer.Write <uint32_t >(EnumNameCount);
506-
507- for (auto & [Key, val] : Enum->ForEachName ())
508- {
509- Buffer.Write <uint32_t >(NameMap[Key]);
510- Buffer.Write <int64_t >(val);
511- }
512- }
513- extEndPos = Buffer.GetBuffer ().tellp ();
514-
515- Buffer.GetBuffer ().seekp (extStartPos);
516- Buffer.GetBuffer ().seekp (-(int32)sizeof (uint32), std::ios_base::cur);
517- Buffer.Write <uint32_t >(extEndPos - extStartPos);
518- Buffer.GetBuffer ().seekp (extEndPos);
504+ // ENVP extension removed - enum values are now written explicitly in the main format (version 4)
519505
520506 // end of extensions //
521507
@@ -528,7 +514,8 @@ namespace RC::OutTheShade
528514 auto FileOutput = FileWriter (filename.c_str ());
529515
530516 FileOutput.Write <uint16_t >(0x30C4 ); // magic
531- FileOutput.Write <uint8_t >(0 ); // version
517+ FileOutput.Write <uint8_t >(static_cast <uint8_t >(EUsmapVersion::Latest)); // version
518+ FileOutput.Write <int32_t >(0 ); // bHasVersionInfo (false, no UE4/UE5 version info)
532519 FileOutput.Write <uint8_t >(0 ); // compression
533520 // Warning: Converting size_t (uint64) to int.
534521 FileOutput.Write <uint32_t >(static_cast <uint32_t >(UsmapData.size ())); // compressed size
0 commit comments