title: How to recover a lost profile file (profile.lua) after a crash in Into The Breach - data recovery slug: into-the-breach-data-recovery
Recently my Steam Deck ran out of battery while I had Into The Breach running, and when I started it again to play it, it told me that my profile file was lost.
The profile file has a one-stage rolling backup, similar to save games. This means normally there will be a file called something like profile.lua.backup, but sometimes that doesn't work out. To be perfectly honest that's some bad programming on part of Subset Games. I got in touch with them to see if they'd like me to walk them through how to run a multi-stage rolling backup on this file, as I'm a dev myself, so who knows, maybe they'll accept it. I was talking to a person called Isla who runs their customer service and is also a forum mod, but I haven't heard back from them yet - but it's only been a few days so far.
Anyways, here's what you want to do if Into The Breach crashes and wipes your profile file. I hope this helps someone who is really attached to their progression.
Don't launch any programs, don't run any operations, updates, file system checks, etc. Don't write to the disk in any way.
Don't even shut down the deck using the menu option, just hold the power long enough that the deck shuts down. Do this as quickly as possible.
On another computer, create a live usb stick that will boot Ubuntu. It needs to be a plain USB stick at least 5 GB size, but I would suggest something that is at least 8GB just in case. Sometimes, usb sticks end up being smaller than advertised. You will also need a little space for the files you recover.
Here are instructions on how to do this on:
If your SD card is in the deck, it will confuse the live usb stick bootloader and you will get a message like grub error: you need to load the kernel first
while trying to load Ubuntu.
Leave it hooked up to a charger to charge the battery up (don't turn it on yet!). When you feel like it's charged up, you can continue.
You can plug the stick in directly if it's a USB C flash drive, or you can plug it in via a USB hub or a dock. It doesn't need to be a Steam Deck dedicated dock. It's preferable to do this in docked mode because you want the Steam Deck to have power while you're doing the next steps.
If you're using a hub or a dock, try using a USB 3 or USB 3.1 port if they're available for the USB stick, as this will make Ubuntu boot faster.
It will be much easier to type all of the stuff you need to type using an actual physical keyboard, but you can also use Ubuntu's on screen keyboard for at least the first few steps. You will absolutely require a keyboard once you're editing files with Vim, but you can get pretty far to where you know if there's any recoverable data with just the on screen keyboard, even if it'll be painful.
Hold the volume down and keep holding it, and press the power button once and release the power button while still holding the volume down button. You will see the Steam Deck logo for a while, keep holding volume down until you see a text-mode boot selection screen. Using your dpad select your usb stick, and press the A button on the right side of the Steam Deck to boot it.
If everything went well, you will see another text screen where you can select what to boot - this time, the program is called grub and looks like this but with other text entries. Just press the A button on the steam deck (which amounts to Enter).
You will be in a graphical installer with buttons that say "Try Ubuntu" on the left and "Install Ubuntu" on the right. You can find a picture of it [here](https://discourse.ubuntu.com/t/install-ubuntu-desktop-18-04/just don't install it!
Select "Try Ubuntu" to run Ubuntu off your USB stick, without installing it.
Ubuntu recognizes the touch pads: the right touchpad is the mouse, clicking is the mouse click, the left touchpad is scrolling up and down, the right trigger is the mouse click and the left trigger is the mouse right click (context menu).
Ubuntu doesn't enable the on screen keyboard by default. Click on the little person icon in the upper right to get the accessibility menu, then click "Screen Keyboard" to enable it.
Move the cursor to the lower left corner of the screen and click on the icon that's 9 little squares arranged in a 3x3 grid. That will bring up the Applications menu, essentially the equivalent of the Windows "Start Menu". In there, one of the icons will be called "Utilities", it has a few smaller icons in it. Inside it, open Disks.
On the left side, select your Steam Deck's internal drive. That's where your "home" file system is, which contains Into The Breach save games. Once a file gets deleted, it isn't immediately removed - instead, a new version is physically written somewhere else, and the old version remains, it just isn't accessible anymore.
In my case, I had three entries:
512 GB Disk
Phison ESMP...KB4C3-E13TS
512 GB Thumb Drive
Kingston DataTraveler Max
2.9 GB Loop Device
/cdrom/casp... tem.squashfs
Click on the one that's your internal drive.
On the right,y ou will be presented with a bunch of rectangles in line. One of them will be selected orange. They will be called "esp", "efi", "efi" again, "rootfs", "rootfs" again, "var", "var", and "home". Click "home", which is usually the largest one, usually to the right.
Below the list of partitions you will have text that goes like
Size: 501 GB -- XX GB free (xx% full)
Contents: Ext4 blah blah blah
Device: /dev/nvmeblahblah
UUID: 104857c-5093-0109-blah-blah
Partition Type: Linux Home Partition
Select the text to the right of "Device", right click it, and copy it to the clipboard. In my case, it's /dev/nvme0n1p8
and it's likely to be the same in your case, but it could be different, so check.
We want to recover our data, so we need a place to store it. The USB stick will have some space.
In the Applications menu, start the Terminal.
Type sudo su
to get a root shell. Now you can do more advanced stuff but you could also lose data - so if you don't know what you're doing, take this to someone who does. Your prompt will now start with a hash character (#
).
Remount the /cdrom
directory so it's writeable:
mount -o remount, rw /cdrom
If you get an error, stop here, and figure out how to make this writeable.
Still in the root shell, go to the /cdrom
directory:
cd /cdrom
create a new directory and go to it:
mkdir recovery
cd recovery
We will now be working inside this directory.
It is important to write the recovered files to a drive different than the drive we're recovering to, or otherwise we might overwrite the data we're trying to recover right now!
All profile.lua
files start like this:
Profile = {
["version"] = 1, ["visible_name"] = "Name", ["opening"] = true, ["hide_tutorials"] = true,
["last_squad"] = 4, ["last_pilot"] = 1,
["timer"] = 101117040.000000,
We'll be searching for the first line.
Run the following command to search for all instances of this text:
grep -oba 'Profile = {' /dev/nvme0n1p8 | tee -a found.log
Make sure to replace /dev/whatever
with what you copied out of the Disks application.
After you press enter, nothing will happen for a long while. It took 15 minutes for a single scan to happen on my 512 GB Steam Deck.
Once you have the bash prompt again, the work is over. If there was no output, either you screwed something up or all instances of profile files have been overwritten and aren't accessible anymore - sorry.
However, it's most likely that you'll have received a bunch of output that looks like this:
2011889664:Profile = {
2012844032:Profile = {
7459569664:Profile = {
7465869312:Profile = {
7466041344:Profile = {
7466995712:Profile = {
10387206132:Profile = {
19323088896:Profile = {
19323125760:Profile = {
92432952938:Profile = {
92444102863:Profile = {
92444105427:Profile = {
92448541384:Profile = {
92468106700:Profile = {
134454104064:Profile = {
134472327168:Profile = {
166502039552:Profile = {
166520430592:Profile = {
166520463360:Profile = {
166520582144:Profile = {
166532780032:Profile = {
166532894720:Profile = {
198663999488:Profile = {
225629884416:Profile = {
274152931328:Profile = {
274153029632:Profile = {
274153172992:Profile = {
352010555392:Profile = {
375396569088:Profile = {
375396667392:Profile = {
375396704256:Profile = {
433314639872:Profile = {
447965614080:Profile = {
450320355328:Profile = {
450320424960:Profile = {
450378604544:Profile = {
450379038720:Profile = {
450379132928:Profile = {
450379223040:Profile = {
450379288576:Profile = {
This is great! That's a lot of potential files to recover.
Run the following command to copy out a bunch of files:
while read i; do skip="$(python3 -c "print($i//1024)")"; dd if=/dev/nvme0n1p8 of="$i".found bs=1K count=100 skip="$skip"; done < <(cat ../found.log | grep 'Profile = {' | cut -f1 -d:)
Note the value right of count
. I currently set it to 100, which means it will copy 100 kilobytes (102400 bytes) of data after the position at which the string "Profile = {" was found. This is because the amount of data is count * bs, and bs is set to 1K, which means 100 * one kilobyte = 100 kilobytes.
Someone sent me their profile.lua file with almost everything unlocked, but not quite everything (I think they were missing one mech squad). Their file as almost 102400 KB, just under that. So if your profile.lua was very large, you might want to increase this number, for example to 200, so that you copy out 200 kilobytes.
You will get output that looks like this:
102+0 records in
102+0 records out
104448 bytes (104 kB, 102 KiB) copied, 0.0409466 s, 2.6 MB/s
102+0 records in
102+0 records out
104448 bytes (104 kB, 102 KiB) copied, 0.00170147 s, 61.4 MB/s
102+0 records in
102+0 records out
104448 bytes (104 kB, 102 KiB) copied, 0.00196664 s, 53.1 MB/s
102+0 records in
102+0 records out
104448 bytes (104 kB, 102 KiB) copied, 0.001776 s, 58.8 MB/s
102+0 records in
102+0 records out
104448 bytes (104 kB, 102 KiB) copied, 0.00136369 s, 76.6 MB/s
etc. (I actually had my count set to 102 here).
Once that's done, running the ls
command will find a bunch of files that might look like this:
# ls
10387206132.found 166520463360.found 19323125760.found 274152931328.found 375396667392.found 450320424960.found 450379288576.found 92432952938.found
134454104064.found 166520582144.found 198663999488.found 274153029632.found 375396704256.found 450378604544.found 7459569664.found 92444102863.found
134472327168.found 166532780032.found 2011889664.found 274153172992.found 433314639872.found 450379038720.found 7465869312.found 92444105427.found
166502039552.found 166532894720.found 2012844032.found 352010555392.found 447965614080.found 450379132928.found 7466041344.found 92448541384.found
166520430592.found 19323088896.found 225629884416.found 375396569088.found 450320355328.found 450379223040.found 7466995712.found 92468106700.found
Run mkdir shortlist
We'll be using Vim. We're using it because these files will contain binary garbage at the end and Vim will display it without errors and let you delete it.
You can install Vim using this command:
apt install vim
At this point you'll want to read a vim tutorial and make sure you know how to edit a file, get into and out of insert mode, how to move the cursor using hjkl, how to delete characters, and how to run commands that start with a colon (:
) like :saveas
.
vim -p *.found
You can cycle through the tabs with the gt command (type g, then t) to go right and gT (type g, then shit and t) to go left.
Find files that look like they have all the data you want. You can move around in the file using h, j, k, l to move the cursor around. You can also use the page up and page down keys on your keyboard.
If you ever get into a weird mode because you pressed the wrong key, you want to type the Esc key a few (say, 5) times, and then press enter.
Don't worry about garbage characters at the end of the file. Just make sure the file isn't truncated.
For example, this file is truncated:
["difficulty"] = 0, ["victory"] = false, ["squad"] = 4, ^@^@["stat_tracker"] = {["games"] = 1, ["travelers"] = 0, ["kills"] = 0, ["islands"] = 0, ["pods"] = 0, ["total"] = 0, ["victories"] = {0, 0, 0, },^@^@^@["trackers"] = {["Global_Pilot_Three"] = 1, ["Global_Pilot_Final"] = 6, ["Global_Pilot_Unlocked"] = 1, },^@^@["achievements"] = {["Global_Pilot_Final"] = 0, },^@^@^@["last_end"] = 2, },^@["pilot"] = {["id"] = "Pilot_Aquatic", ["name"] = "Archimedes", ["name_id"] = "Pilot_Aquatic_Name", ["renamed"] = false, ["skill1"] = 1, ["skill2"] = 0, ["exp"] = 50, ["level"] = 2, ["travel"] = 15, ["final"] = 6, ["starting"] = true, ["power"] = {0, },^@["pilots"] = {"Pilot_Original", },^@^@["squads"] = {true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, },^@^@["tutorials"] = {},^@^@["unlocked_island"] = 0, ^@["timer"] = 115290.828125, ^@["last_squad"] = 0, ["last_pilot"] = 1, ^@["version"] = 1, ["visible_name"] = "Name", ["opening"] = true, ["hide_tutorials"] = true, ^@Profile = {^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
whereas this one isn't (I'm only showing the first screen ful of it)
Profile = {
["version"] = 1, ["visible_name"] = "Name", ["opening"] = true, ["hide_tutorials"] = true,
["last_squad"] = 4, ["last_pilot"] = 1,
["timer"] = 0.000000,
["unlocked_island"] = 0,
["tutorials"] = {},
["squads"] = {true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, },
["pilots"] = {"Pilot_Original", },
["achievements"] = {},
["trackers"] = {["Global_Pilot_Unlocked"] = 1, },
["stat_tracker"] = {["games"] = 0, ["travelers"] = 0, ["kills"] = 0, ["islands"] = 0, ["pods"] = 0, ["total"] = 0, ["victories"] = {0, 0, 0, },
["squad0"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad1"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad2"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad3"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad4"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad5"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad6"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad7"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad8"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad9"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
You can check what's under the visible_name
key, it should be what you entered when you created the profile.
The file is considered "complete" if it ends like it should. Here's an example of what this file ended up like:
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad14"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["squad15"] = {["victories"] = {0, 0, 0, },
["games"] = 0, ["score"] = 0, ["kills"] = 0, },
["pilots"] = {
},
["enemies"] = {
},
},
}
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@0\r§^[mûü^E^@^@^@w^@^@^@^P$^]<9a>^@^@^@^@1/0/https://cdn.steamstatic.com/steamcommunity/public/images/items/1263950/f5a7dffe45c8dc1578053f3ba4723f78729bd4bf.png<89>PNG^M
^Z
^@^@^@^MIHDR^@^@^@à^@^@^@à^H^F^@^@^@^Z-já^@^@^\7iTXtXML:com.adobe.xmp^@^@^@^@^@<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 6.0-c002 79.164360, 2020/02/13-01:07:22 ">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/"
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
xmpMM:InstanceID="xmp.iid:02ffe289-d75d-7d4f-9336-33136d8e7fab"
You can see there were some squad
entries, then pilots
, then enemies
, and finally it ended with a lone right brace }
on a line of its own. After that there was a bunch of binary garbage (^@
is a null character, meaning that the drive physically has 0's in that byte). Then, another completely unrelated file started. That part doesn't matter, it's fine, we'll delete it later.
Always check the garbage at the end of files. Sometimes a complete other profile file can be hiding in there! You'll have to save that out to another file.
When you find a file that looks promising, store it out, using a command like this:
:saveas shortlist/1.lua
obviously increase the number every time you do this.
Once you're done, quit vim using :q
.
Go to the shortlist directory and compare the shortlisted files:
cd shortlist
vim -p *.lua
You will notice that each file has a timer
key. I believe that counts the time you've been playing for. Find the one with the largest timer. Check again if it's complete. Read the file through from beginning to end and see if it follows correct LUA syntax - you need to know something about programming to understand what's going on.
One thing you can do is you can go to the very first line that is Profile = {
and move your cursor so it's over the left brace ({
). Then, on your keyboard, press the %
key (usually shift + 5 on US keyboards). That should take you to the matching brace at the end of the file. If it does that, you know the file you recovered has OK syntax.
If everything is good, save it as last.lua
:
:saveas last.lua
Quit Vim using :quit
.
Open last.lua
with Vim:
vim last.lua
Using the hjkl keys or using the %
key like described in the previous step, navigate to the final closing brace of the lua file, so that the cursor is right on top of it. If there are no more charcters after that, great, you're done! But there will likely be characters there, like in the examples above.
Press the space bar once to move one character to the right. You are now at the very beginning of the garbage data.
Press dG to delete everything until the end of the file. The garbage should now have disappeared. The status bar at the bottom left corner of Vim will tell you something like this:
387 fewer lines
(the number will probably be different)
You can now save the file using the :save
command.
Shut down Ubuntu using the power menu in the top right corner.
Reinstall your SD card if you pulled it out before.
Boot into SteamOS desktop.
Using the file manager, copy the existing file from the USB stick into your home directory, so that it is under the path ~/last.lua
.
In a terminal, go to the directory that holds your profiles:
cd /home/deck/.local/share/IntoTheBreach/
List the files using ls
. It will show you your profile dir.
go into it:
cd profile_Name
Move the existing profile.lua
to something else, eg:
mv profile.lua profile.lua.bad
Move the lua file into place:
mv -iv ~/found.lua profile.lua
You should be done recovering your profile!
A similar process can be used if you lose your Into The Breach save game, but you'll have to search for a different string when using the grep command on the disk drive.
If you want to restore your current pilot, you'll have to restore the save game, too. However, if you only lost your profile and not your save game, then your save game should still exist, and therefore your pilot should still be there as well.