The Outer Worlds from Switch to Deck

By | 7 Nov 2025

Back in June 2020, The Outer Worlds was released for the Nintendo Switch. In September 2021, I’ve bought it and played it every once in a while until I finished it sometime in the middle of 2022. Despite also owning the Expansion Pass, I’ve never completed the additional quests.

Since March 2025, I’m the proud owner of a Steam Deck and slowly making it my only gaming device. Which also means, that I’m buying a few games a second time, if they’re on offer. Just for the convenience of having them available on the Deck. So, I’ve bought The Outer Worlds again.

Now, as I’ve already played the main mission, I wanted to just play the expansions, continuing from where I’ve left 3 years ago. However, getting my Switch savegame to work on the Deck wasn’t that straight-forward.

Recovering the Savegames

Getting the savegame off my Switch was, in fact, the easiest part. Back in the days, as my Switch is an unpatched model, I’ve just used memloader. This is a payload you can boot that will just provide access to the Switch’s internal storage. Nothing more. Using the encryption keys you’ve most probably already extracted, you can use tools like ninfs or HacDiskMount to mount those storage partitions. From there, you’ll need to sift through all those numbered folders and savegames until you find the correct one.

Nowadays, my Switch is running Atmosphere and I can use DBI (build 658 is the last official release with English language support) to just access all the savegames via an FTP client. And they’re conveniently in folders named after the games they’re for.

This is what I’ve got:

Folder structure of the Switch savegame. Top folder is "The Outer Worlds", then a folder with my Switch username "Markus" in it. Below that, folders with random hex strings. Each folder contains a SavedState.dat, SaveGameScreenshot.png and a Metadata.dat.

Where to put them on the Deck?

After copying the savegames from my Switch, I had to identify the correct folders on my Steam Deck. Luckily, there are only 2 places where savegames usually hide. Either the normal savegame folder:

~/.local/share/Steam/userdata/<GameID>/...Code language: JavaScript (javascript)

Or, somewhere inside the Proton emulated Windows’ C: drive:

~/.local/share/Steam/steamapps/compatdata/<GameID>/pfx/drive_c/...Code language: JavaScript (javascript)

There, it’s usually under drive_c/Users/steamuser/My Savegames/ but can also hide inside Program Files or ProgramData.

In the case of The Outer Worlds, it was here:

Original Version (Non-Mandatory Corporate-Sponsored) – Game ID: 578650

~/.local/share/Steam/steamapps/compatdata/578650/pfx/drive_c/users/steamuser/Saved Games/The Outer Worlds/Code language: JavaScript (javascript)

Spacer’s Choice Edition – Game ID: 1920490

~/.local/share/Steam/steamapps/compatdata/1920490/pfx/drive_c/users/steamuser/Saved Games/The Outer Worlds Spacers Choice/<Steam User ID>/Code language: JavaScript (javascript)

A Simple Copy?

Looking into these folders (after playing the opening sequence and saving at least once) on the Deck looked very similar to what I saw from the Switch savegames. But wait, what’s that? Spot the difference!

Folder structure of the Steam Deck savegame. Top folder is "The Outer Worlds", then folders with random hex strings. Each folder contains a SaveGame.dat, SaveGameScreenshot.png and a Metadata.dat.

Instead of a SavedState.dat, the Steam Deck has files called SaveGame.dat. The other two files are named the same as on the Switch, though. This made me try simply renaming the Switch’s file to SaveGame.dat. Worth a try, right?

Opening the loading dialog on the Steam Deck showed these newly added savegames including their screenshots and metadata (e.g. the version of the game, current mission, playing time, etc.). But tapping the A button to load it, didn’t do anything.

From this I deducted that the Metadata.dat and SaveGameScreenshot.png are compatible, but the SavedState.dat – now renamed into SaveGame.dat isn’t.

Deeper Analysis

No time to give up now. So, I’ve opened a Switch file and a Steam Deck file side-by-side in my favourite hex editor HexFiend. Both looked very random which usually means they’re either encrypted or compressed. A quick online search revealed this “converter” tool, which clearly states “unpack” and “repack”. A quick check with file confirmed that:

> file SavedState.dat
SavedState.dat: zlib compressed dataCode language: CSS (css)

While that converter website worked fine and unpacked my 3 MB savegame into a 11.3 MB file, I also found this StackOverflow comment which provides an elegant solution to do it locally. I’ve verified that I get the same result with that.

Now, unpacking both types of savegame and putting them next to each other reveals a slight difference:

Two windows of HexFiend with seemingly garbage in hex and ASCII. However, in the top window you can clearly read e.g. "SGDF", "LSHF" and "Main.dat" whereas in the bottom window there are spaces between each letter of "Main.dat". And no "SGDF", but the "LSHF" is still there.

The obvious difference in the ASCII part: Main.dat in the top file and M a i n . d a t in the bottom one. But also the SGDF is suspiciously absent in the bottom file. Top is Steam Deck, bottom is Switch. So, I need to find a way to make the bottom one look like the top one. Luckily, the other stuff at the bottom seems to be identical in both. So, we don’t need to care about that.

As this is a binary format that needs to be parsed properly, you can’t just overwrite the M a i n . d a t with Main.dat as you would end up with Main.dat. d a t. And filling the rest with spaces wouldn’t work either as that would surely confuse the parser. Similarly, you can’t just delete those additional Bytes as this would change all the offsets further down and might produce even other errors where the parser expects a specific number of Bytes for the string. Inserting a random SGDF wouldn’t work either.

The only way is to try to make sense of the two formats and their differences.

The Man Who Stares At Bytes

One of the basic ways to store data in binary formats is the so-called “TLV” – type, length and value. Another basic way of storing text is a null-terminated string, meaning the end of the text is marked by a 00 Byte. And then, you need to understand that numbers can be stored in differently sized blocks. A single Byte can only hold 256 different states. In terms of numbers, that’s either a number between 0..255 or -128..127. If you need to store larger numbers, you’ll need to increase the number of Bytes you’re using. E.g. 2 Bytes can hold 256*256 different states which is a number between 0..65535 or -32768..32767. For even higher numbers, you just double the amount of Bytes used until it fits your purpose.

Back to the savegame files. We recognise the “Main.dat” which looks very much like a filename. That’s our value of 8 characters (7 letters and a dot). So, we’re looking for a length of either 8 or – if it’s null-terminated – a 9. In the bottom file, it might even be a length of 16 or 18 – as it’s using 2 Bytes for each letter.

Let’s look at the hex block in the left of the top file. Going backwards from the “Main.dat”, we’ll notice a few 00s and then a 09. A promising start, as 09 in hex is also a 9 in decimal. One of the numbers we’re looking for. Assuming, those 00s belong to the length, the whole thing would be 09 00 00 00 in hex. And that’s still a 9 in little-endian decimal. A group of 4 Bytes is called a “double-word” or “d-word”. As this is an integer number stored in 4 Bytes and 4 Bytes have 32 Bits – this can also be called an “int32” value. Also, Bytes that belong together to hold one piece of information are called a “field”.

Let’s double check with the “Player.dat”. Checking the 4 Bytes in front of that, we see 0B 00 00 00. And 0B in hexadecimal is 11 in decimal. “Player.dat” has 10 characters and including the 00 Byte after that, we end up with 11. Great – looks like we found out how the names are recorded.

Now, we need to check the bottom file. Going backwards from the “M a i n . d a t” we see a lot more 00s and then a 08. If we count the 00s and the 08, we get 8 Bytes – so this might be a so-called “quad-word” holding an “int64” value. It still comes out as the number 8 – incidentally the number of characters in “Main.dat”, if we left out the spaces.

Checking it against the “P l a y e r . d a t” we can confirm that there, we get a 0A – which is a decimal 10. And “Player.dat” has 10 characters.

We now know that those filenames use a Length-Value encoding. First, we get a field with the length of the string followed by the string itself. And we’ve also learned that the PC uses an “int32” value for the length and has the string without spaces but followed by a 00 Byte; whereas the Switch uses an “int64” value and has each character followed by a 00 Byte.

Now, let’s go in the other direction. Assuming, it’s the same length-value method. In the top file, we see a “G” directly after “Main.dat”. Staying with “int32” for the lengths, that would be 47 00 00 00. Converted to decimal, we get 71.

Counting 71 Bytes after that field, we end up with this:

Ha! So, we end up directly in front of the length field for the next filename. How convenient! I guess we can safely assume that this is the payload for that record. Verifying that against the “Player.dat”, which has a payload length of E6 30 00 00 = 12,518 Bytes, we find, that after this amount of Bytes we’ll be right in front of a “CharacterCreation.dat”. Looking good!

And it’s the exact same principle with the Switch’s savegame. Even the length field for the payload is an “int32” there, too.

As for the stuff in front of the 09 00 00 00 and Main.dat? When comparing several savegames, we’ll notice that it’s identical for all of them. So, let’s assume that’s a static header information.

Doing the actual conversion

We now have all the puzzle pieces together to be able to create a PC savegame from the data found in a Switch savegame:

  1. Copy the first 15 Bytes from another PC savegame as-is (the stuff with “SGDF” in it)
  2. Skip the first 8 Bytes in the Switch savegame (header)
  3. Get the int64 length from the Switch savegame, add 1 to it (for the 00 Byte following the name, which isn’t there on the Switch) and add it as an int32 to our output file
  4. Get the name and convert from UTF-16 to ASCII and add the trailing 00
  5. Get the int32 payload length and just copy it the output
  6. Read the number of Bytes as indicated by the payload length and copy them as-is to the output
  7. Repeat steps 3-6 until we’ve reached the end of the file

We will end up with a file that looks exactly like a PC savegame but has all the data from the Switch savegame in it. Now, we need to compress it again, so it matches what the game expects:

cat NewSaveGame.dat | perl -MCompress::Zlib -E 'undef $/;print compress(<>)' > SaveGame.datCode language: PHP (php)

Great! Copy it and the accompanying Metadata.dat and SaveGameScreenshot.png to the Steam Deck and …. nothing. The savegame still doesn’t load. But why?

As we’ve stared at the savegame itself long enough, let’s have a look at the Metadata.dat:

There are a lot of 4-Byte groups in the form of xy 00 00 00 – which indicates that these might also be int32 values. After trying various 4-Byte groups and converting the hexadecimal value to decimal, we’ll stumble upon the value marked in the screenshot. FA D5 AB 00 converted to decimal is: 11,261,434. Or roughly 11.3 million. Hmmm … where did we see that number before?

Right, that’s the exact size of the Switch savegame after decompression. But we’ve now rewritten the savegame for the PC version and all the length fields that were 8-Byte int64 before are now 4-Byte int32. And the filenames that were UTF-16 2-Byte complements before are now simple ASCII strings. We’ve basically reduced the size of the savegame by some margin and it’s now only 11,216,304 Bytes before we’ve compressed it.

That number in hexadecimal is B0 25 AB 00. So, let’s update it in the Metadata.dat file.

And that’s it! After copying the modified Metadata.dat into the savegame folder on the Steam Deck, the game finally loads our savegame and we’ll be right at the end of the main story. Success!

Writing a converter

I’ve poured all the stuff described here into a nice Python script that can convert a Switch savegame to PC and also fixes the size in the Metadata.dat file in one single command:

https://git.mbirth.uk/mbirth/convert-tow-switch2pc

I’ve also created a few HexFiend templates to easily navigate the files.

Have fun!

One thought on “The Outer Worlds from Switch to Deck

  1. Broderick Ruiz

    Awesome write-up! The screenshots made everything so clear.

    Reply

Likes

Reposts

Leave a Reply

Your email address will not be published. Required fields are marked *

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)