Gvas: add support for UE5 saves.

Fuckers at Epic added four more bytes to the file header, and not
even equivalent Rust libraries know what those bytes are for.
This commit is contained in:
Guillaume Jacquemin 2024-07-13 15:03:30 +02:00
parent 3e0c0bb7a4
commit a290542f6e
Signed by: williamjcm
SSH key fingerprint: SHA256:AYLOg+iTV0ElElnlu4vqM4edFazVdRiuQB0Y5LoKc4A
2 changed files with 78 additions and 17 deletions

View file

@ -95,16 +95,39 @@ File::saveToFile() {
return false; return false;
} }
if(!writer.writeArray(arrayView(_magicBytes)) || if(!writer.writeArray(arrayView(_magicBytes))) {
!writer.writeUint32(_saveVersion) || _lastError = "Couldn't write the magic bytes."_s;
!writer.writeUint32(_packageVersion) || LOG_ERROR(_lastError);
!writer.writeUint16(_engineVersion.major) || return false;
!writer.writeUint16(_engineVersion.minor) || }
!writer.writeUint16(_engineVersion.patch) ||
!writer.writeUint32(_engineVersion.build) || if(!writer.writeUint32(_saveVersion)) {
_lastError = "Couldn't write the save version."_s;
LOG_ERROR(_lastError);
return false;
}
if(!writer.writeUint32(_packageVersion)) {
_lastError = "Couldn't write the package version."_s;
LOG_ERROR(_lastError);
return false;
}
if(_saveVersion == 3) {
if(!writer.writeUint32(_unknown)) {
_lastError = "Couldn't write some unknown bytes."_s;
LOG_ERROR(_lastError);
return false;
}
}
if(!writer.writeUint16(_engineVersion.major) ||
!writer.writeUint16(_engineVersion.minor) ||
!writer.writeUint16(_engineVersion.patch) ||
!writer.writeUint32(_engineVersion.build) ||
!writer.writeUEString(_engineVersion.buildId)) !writer.writeUEString(_engineVersion.buildId))
{ {
_lastError = "Couldn't write the header."_s; _lastError = "Couldn't write the engine version."_s;
LOG_ERROR(_lastError); LOG_ERROR(_lastError);
return false; return false;
} }
@ -198,15 +221,53 @@ File::loadData() {
return; return;
} }
if(!reader.readUint32(_saveVersion) || if(!reader.readUint32(_saveVersion)) {
!reader.readUint32(_packageVersion) || _lastError = "Couldn't read save version.";
!reader.readUint16(_engineVersion.major) || LOG_ERROR(_lastError);
!reader.readUint16(_engineVersion.minor) || return;
!reader.readUint16(_engineVersion.patch) || }
!reader.readUint32(_engineVersion.build) ||
!reader.readUEString(_engineVersion.buildId)) if(!reader.readUint32(_packageVersion)) {
_lastError = "Couldn't read package version.";
LOG_ERROR(_lastError);
return;
}
if(_saveVersion == 3) {
if(!reader.readUint32(_unknown)) {
_lastError = "Couldn't read some unknown bytes.";
LOG_ERROR(_lastError);
return;
}
}
if(!reader.readUint16(_engineVersion.major)) {
_lastError = "Couldn't read major engine version.";
LOG_ERROR(_lastError);
return;
}
if(!reader.readUint16(_engineVersion.minor)) {
_lastError = "Couldn't read minor engine version.";
LOG_ERROR(_lastError);
return;
}
if(!reader.readUint16(_engineVersion.patch)) {
_lastError = "Couldn't read patch engine version.";
LOG_ERROR(_lastError);
return;
}
if(!reader.readUint32(_engineVersion.build)) {
_lastError = "Couldn't read engine build.";
LOG_ERROR(_lastError);
return;
}
if(!reader.readUEString(_engineVersion.buildId))
{ {
_lastError = "Couldn't read version data."; _lastError = "Couldn't read engine build ID string.";
LOG_ERROR(_lastError); LOG_ERROR(_lastError);
return; return;
} }

View file

@ -17,7 +17,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Reference.h> #include <Corrade/Containers/Reference.h>
#include <Corrade/Containers/StaticArray.h> #include <Corrade/Containers/StaticArray.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
@ -73,6 +72,7 @@ class File {
std::uint32_t _saveVersion = 0; std::uint32_t _saveVersion = 0;
std::uint32_t _packageVersion = 0; std::uint32_t _packageVersion = 0;
std::uint32_t _unknown = 0;
struct { struct {
std::uint16_t major = 0; std::uint16_t major = 0;
std::uint16_t minor = 0; std::uint16_t minor = 0;