Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to read save file for Medieval Dynasty #103

Open
Shoggomo opened this issue Apr 24, 2024 · 7 comments
Open

Unable to read save file for Medieval Dynasty #103

Shoggomo opened this issue Apr 24, 2024 · 7 comments
Labels
enhancement New feature or request

Comments

@Shoggomo
Copy link

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
Copy link
Owner

localcc commented Apr 30, 2024

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

@Shoggomo
Copy link
Author

Shoggomo commented May 5, 2024

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
Copy link
Author

@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 trumank/uesave-rs#41 (comment)

@scottanderson
Copy link
Collaborator

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 scottanderson changed the title Cannot figure out missing hint for Medieval Dynasty Unable to read save file for Medieval Dynasty May 14, 2024
@scottanderson scottanderson reopened this May 14, 2024
@scottanderson scottanderson added the enhancement New feature or request label May 14, 2024
scottanderson added a commit to scottanderson/gvas that referenced this issue May 14, 2024
scottanderson added a commit to scottanderson/gvas that referenced this issue May 14, 2024
@scottanderson
Copy link
Collaborator

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
Copy link
Collaborator

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.

@scottanderson
Copy link
Collaborator

This approach works more reliably:

diff --git a/src/properties/map_property.rs b/src/properties/map_property.rs
index 87faedd..766a336 100644
--- a/src/properties/map_property.rs
+++ b/src/properties/map_property.rs
@@ -453,23 +453,35 @@ impl MapProperty {
         }
     }

-    impl_read_header!(options, key_type, value_type);
+    impl_read_header!(options, length, key_type, value_type);

     #[inline]
     fn read_body<R: Read + Seek>(
         cursor: &mut R,
         options: &mut PropertyOptions,
+        length: u32,
         key_type: String,
         value_type: String,
     ) -> Result<Self, Error> {
         let allocation_flags = cursor.read_u32::<LittleEndian>()?;
         let element_count = cursor.read_u32::<LittleEndian>()?;

+        let suggested_length = match key_type.as_ref() {
+            "ByteProperty" => {
+                if length == 8 + (2 * element_count) {
+                    Some(1)
+                } else {
+                    Some(u32::MAX)
+                }
+            }
+            _ => None,
+        };
+
         let mut map = HashableIndexMap::with_capacity(element_count as usize);
         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 key = Property::new(cursor, &key_type, false, options, suggested_length)?;
             drop(key_stack_entry);

             let properties_stack = &mut options.properties_stack;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants