localcc / gvas

GVAS file format parsing library for rust
MIT License
18 stars 4 forks source link

Unable to read save file for Medieval Dynasty #103

Open Shoggomo opened 2 months ago

Shoggomo commented 2 months ago

I want to build a save editor for Medieval Dynasty and use this library for it.

When trying to load a save I'm missing a hint though and I cannot figure out, how to fix this.

Error: Err(Deserialize(MissingHint("StructProperty", "LandscapeData.MapProperty.Value.StructProperty", 1789)))

This should be the correct section:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000690        0E 00 00 00 4C 61 6E 64 73 63 61 70 65 44    ....LandscapeD
000006A0  61 74 61 00 0C 00 00 00 4D 61 70 50 72 6F 70 65  ata.....MapPrope
000006B0  72 74 79 00 3B CF 00 00 00 00 00 00 0C 00 00 00  rty.;Ï..........
000006C0  53 74 72 50 72 6F 70 65 72 74 79 00 0F 00 00 00  StrProperty.....
000006D0  53 74 72 75 63 74 50 72 6F 70 65 72 74 79 00 00  StructProperty..
000006E0  00 00 00 00 02 00 00 00 11 00 00 00 46 6F 6C 69  ............Foli
000006F0  61 67 65 43 6F 6C 6C 69 73 69 6F 6E 00 2D 00 00  ageCollision.-..
00000700  00 53 74 72 69 6E 67 73 5F 31 31 36 5F 32 44 38  .Strings_116_2D8
00000710  43 31 46 32 32 34 37 34 38 34 34 42 41 37 33 46  C1F22474844BA73F
00000720  45 35 46 42 44 38 41 43 31 41 43 41 46 00        E5FBD8AC1ACAF.

Here's my save file: Autosave.zip

localcc commented 2 months ago

Missing property seems to either be a NameProperty or a StrProperty, most likely StrProperty.

Shoggomo commented 2 months ago

Thanks, that got me further, but it's still not working and this looks weird. I'm getting this error (i added the the start, end and length prints).

panicked at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/gvas-0.9.0/src/properties/map_property.rs:444:5:
assertion `left == right` failed: read_body read 0x6a, expected 0x680
Start: 59364
End: 59470
Length: 1664
Properties { key_type: "ByteProperty", value_type: "BoolProperty", allocation_flags: 0, value: {ByteProperty(ByteProperty { name: None, value: Byte(28) }): BoolProperty(false), ByteProperty(ByteProperty { name: None, value: Byte(0) }): BoolProperty(false), ByteProperty(ByteProperty { name: None, value: Byte(69) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(84) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(116) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(114) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(97) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(115) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(58) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(101) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(117) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(111) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(48) }): BoolProperty(false), ByteProperty(ByteProperty { name: None, value: Byte(95) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(105) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(108) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(78) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(119) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(110) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(109) }): BoolProperty(true), ByteProperty(ByteProperty { name: None, value: Byte(50) }): BoolProperty(false)} }
  left: 106
 right: 1664

Here is the corresponding section from the save file:

Collapsed because of wall of text ``` Offset(d) 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 00059296 0C 00 00 00 4D 61 70 ....Map 00059312 50 72 6F 70 65 72 74 79 00 80 06 00 00 00 00 00 Property.€...... 00059328 00 0D 00 00 00 42 79 74 65 50 72 6F 70 65 72 74 .....BytePropert 00059344 79 00 0D 00 00 00 42 6F 6F 6C 50 72 6F 70 65 72 y.....BoolProper 00059360 74 79 00 00 00 00 00 00 31 00 00 00 1C 00 00 00 ty......1....... 00059376 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00059392 45 6E 75 6D 65 72 61 74 6F 72 30 00 00 1C 00 00 Enumerator0..... 00059408 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 .E_Tutorials::Ne 00059424 77 45 6E 75 6D 65 72 61 74 6F 72 31 00 00 1C 00 wEnumerator1.... 00059440 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00059456 65 77 45 6E 75 6D 65 72 61 74 6F 72 32 00 00 1C ewEnumerator2... 00059472 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A ...E_Tutorials:: 00059488 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 33 00 01 NewEnumerator3.. 00059504 1C 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00059520 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 34 00 :NewEnumerator4. 00059536 01 1C 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 .....E_Tutorials 00059552 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 35 ::NewEnumerator5 00059568 00 01 1C 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00059584 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00059600 36 00 01 1C 00 00 00 45 5F 54 75 74 6F 72 69 61 6......E_Tutoria 00059616 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F ls::NewEnumerato 00059632 72 37 00 01 1C 00 00 00 45 5F 54 75 74 6F 72 69 r7......E_Tutori 00059648 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 als::NewEnumerat 00059664 6F 72 38 00 00 1C 00 00 00 45 5F 54 75 74 6F 72 or8......E_Tutor 00059680 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 ials::NewEnumera 00059696 74 6F 72 39 00 01 1D 00 00 00 45 5F 54 75 74 6F tor9......E_Tuto 00059712 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 rials::NewEnumer 00059728 61 74 6F 72 31 30 00 01 1D 00 00 00 45 5F 54 75 ator10......E_Tu 00059744 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D torials::NewEnum 00059760 65 72 61 74 6F 72 31 31 00 01 1D 00 00 00 45 5F erator11......E_ 00059776 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E Tutorials::NewEn 00059792 75 6D 65 72 61 74 6F 72 31 32 00 00 1D 00 00 00 umerator12...... 00059808 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00059824 45 6E 75 6D 65 72 61 74 6F 72 31 33 00 01 1D 00 Enumerator13.... 00059840 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00059856 65 77 45 6E 75 6D 65 72 61 74 6F 72 31 34 00 01 ewEnumerator14.. 00059872 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00059888 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 31 35 :NewEnumerator15 00059904 00 00 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00059920 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00059936 31 36 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 16......E_Tutori 00059952 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 als::NewEnumerat 00059968 6F 72 31 37 00 00 1D 00 00 00 45 5F 54 75 74 6F or17......E_Tuto 00059984 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 rials::NewEnumer 00060000 61 74 6F 72 31 38 00 01 1D 00 00 00 45 5F 54 75 ator18......E_Tu 00060016 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D torials::NewEnum 00060032 65 72 61 74 6F 72 31 39 00 01 1D 00 00 00 45 5F erator19......E_ 00060048 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E Tutorials::NewEn 00060064 75 6D 65 72 61 74 6F 72 32 30 00 00 1D 00 00 00 umerator20...... 00060080 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00060096 45 6E 75 6D 65 72 61 74 6F 72 32 31 00 00 1D 00 Enumerator21.... 00060112 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00060128 65 77 45 6E 75 6D 65 72 61 74 6F 72 32 32 00 00 ewEnumerator22.. 00060144 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00060160 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 32 33 :NewEnumerator23 00060176 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00060192 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00060208 32 34 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 24......E_Tutori 00060224 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 als::NewEnumerat 00060240 6F 72 32 35 00 01 1D 00 00 00 45 5F 54 75 74 6F or25......E_Tuto 00060256 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 rials::NewEnumer 00060272 61 74 6F 72 32 36 00 01 1D 00 00 00 45 5F 54 75 ator26......E_Tu 00060288 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D torials::NewEnum 00060304 65 72 61 74 6F 72 32 37 00 01 1D 00 00 00 45 5F erator27......E_ 00060320 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E Tutorials::NewEn 00060336 75 6D 65 72 61 74 6F 72 32 38 00 01 1D 00 00 00 umerator28...... 00060352 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00060368 45 6E 75 6D 65 72 61 74 6F 72 32 39 00 00 1D 00 Enumerator29.... 00060384 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00060400 65 77 45 6E 75 6D 65 72 61 74 6F 72 33 30 00 01 ewEnumerator30.. 00060416 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00060432 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 33 31 :NewEnumerator31 00060448 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00060464 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00060480 33 32 00 00 1D 00 00 00 45 5F 54 75 74 6F 72 69 32......E_Tutori 00060496 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 als::NewEnumerat 00060512 6F 72 33 33 00 00 1D 00 00 00 45 5F 54 75 74 6F or33......E_Tuto 00060528 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 rials::NewEnumer 00060544 61 74 6F 72 33 34 00 00 1D 00 00 00 45 5F 54 75 ator34......E_Tu 00060560 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D torials::NewEnum 00060576 65 72 61 74 6F 72 33 35 00 00 1D 00 00 00 45 5F erator35......E_ 00060592 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E Tutorials::NewEn 00060608 75 6D 65 72 61 74 6F 72 33 36 00 00 1D 00 00 00 umerator36...... 00060624 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00060640 45 6E 75 6D 65 72 61 74 6F 72 33 37 00 01 1D 00 Enumerator37.... 00060656 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00060672 65 77 45 6E 75 6D 65 72 61 74 6F 72 33 38 00 01 ewEnumerator38.. 00060688 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00060704 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 33 39 :NewEnumerator39 00060720 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00060736 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00060752 34 30 00 00 1D 00 00 00 45 5F 54 75 74 6F 72 69 40......E_Tutori 00060768 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 als::NewEnumerat 00060784 6F 72 34 31 00 01 1D 00 00 00 45 5F 54 75 74 6F or41......E_Tuto 00060800 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 rials::NewEnumer 00060816 61 74 6F 72 34 32 00 00 1D 00 00 00 45 5F 54 75 ator42......E_Tu 00060832 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E 75 6D torials::NewEnum 00060848 65 72 61 74 6F 72 34 33 00 01 1D 00 00 00 45 5F erator43......E_ 00060864 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 45 6E Tutorials::NewEn 00060880 75 6D 65 72 61 74 6F 72 34 34 00 01 1D 00 00 00 umerator44...... 00060896 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E 65 77 E_Tutorials::New 00060912 45 6E 75 6D 65 72 61 74 6F 72 34 35 00 01 1D 00 Enumerator45.... 00060928 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A 3A 4E ..E_Tutorials::N 00060944 65 77 45 6E 75 6D 65 72 61 74 6F 72 34 36 00 01 ewEnumerator46.. 00060960 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C 73 3A ....E_Tutorials: 00060976 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 34 38 :NewEnumerator48 00060992 00 01 1D 00 00 00 45 5F 54 75 74 6F 72 69 61 6C ......E_Tutorial 00061008 73 3A 3A 4E 65 77 45 6E 75 6D 65 72 61 74 6F 72 s::NewEnumerator 00061024 34 39 00 49. ```

It looks like this should be a map of booleans, but it's clearly not. What's going on there?

Shoggomo commented 2 months ago

@trumank explained to me, that ByteProperties can have an additional label, in case an named Enum is used. More about it can be read here https://github.com/trumank/uesave-rs/issues/41#issuecomment-2105965642

scottanderson commented 2 months ago

This library supports "namespaced" bytes, you could try something like:

diff --git a/src/properties/map_property.rs b/src/properties/map_property.rs
index 203fc9a..7723e06 100644
--- a/src/properties/map_property.rs
+++ b/src/properties/map_property.rs
@@ -457,7 +457,11 @@ impl MapProperty {
         for _ in 0..element_count {
             let properties_stack = &mut options.properties_stack;
             let key_stack_entry = ScopedStackEntry::new(properties_stack, "Key".to_string());
-            let key = Property::new(cursor, &key_type, false, options, None)?;
+            let suggested_length = match key_type.as_ref() {
+                "ByteProperty" => Some(u32::MAX),
+                _ => None,
+            };
+            let key = Property::new(cursor, &key_type, false, options, suggested_length)?;
             drop(key_stack_entry);

             let properties_stack = &mut options.properties_stack;
scottanderson commented 1 month ago

UE5 file format version 1012 (PROPERTY_TAG_COMPLETE_TYPE_NAME) introduces some changes to the format that will need to be considered.

https://github.com/EpicGames/UnrealEngine/commit/9fb9d5f0f12bb2d46fbab507141394680d699d4e

scottanderson commented 3 weeks ago

On closer inspection, the provided save file does not have PROPERTY_TAG_COMPLETE_TYPE_NAME enabled (the UE version is older than this feature), however the ByteProperty objects definitely do contain strings in the attached file. More research is required to understand why this game is using this format, and how to detect which variant of ByteProperty should be used.