從舊手機備份中拷貝遊戲的存檔

最近比較閒,把一些以前玩過的 android 遊戲裝回來玩。 很多遊戲都沒有內建存檔轉移機制,所以以前玩的進度沒了。 只好自立自強從以前手機的備份映象檔中, 找回以前遊戲的存檔,放到現在手機的資料目錄中。 這些操作用 root 可以簡單做到, 或用 adb backup 搭配 adb backup extractor 也可以。

老遊戲

最近比較有閒時間來玩遊戲,但個人偏好一些老遊戲, 這些遊戲都沒有備份機制,所以得自己想辦法:

這些遊戲和多數 app 一樣, 都是直接把存檔放在 /data/data/ 裡, 也沒提供存檔轉移機制。

手動複製存檔

每個 app 都有自己唯一的 id, 可以打開 app 後進 android shell 用 top 查, 像 adb shell top ,看佔 cpu 最高的第一個 app 多半就是了。 如果名字太長可以看第一欄的 pid,用 ps -f -ww 1234 查程式全名。 之後該程式的資料就會存在 /data/data/com.nimblebit.nimblequest/ 裡。

不想這麼麻煩也可以直接從 play store 的網址看。 例如 nimble quest 是 https://play.google.com/store/apps/details?id=com.nimblebit.nimblequest , 網址 querystring 的 id 參數就是 app 的 id。 當然,已經被下架的 app 就不適用此方法了。

所以只要找到該資料夾裡哪個檔案是存檔, 然後複製到新裝置上即可。 但對使用者來說,不允許存取 /data 下的資料, 除非你有 root,取得 root 權限後就可以整個系統隨你逛了。

如果有 root,直接進去找出存檔是哪個檔, 複製出來,再傳到新手機,複製到對應的位置蓋掉原本的存檔即可。 例如 nimble quest 的存檔是: /data/data/com.nimblebit.nimblequest/shared_prefs/com.nimblebit.nimblequest.xml ,把舊的蓋掉就好了。 甚至因為他是明文 xml,可以直接改內容, 當然我是不鼓勵這種破壞遊戲體驗的作法。

另外蓋掉時,要注意不要直接用 cp 或 mv 蓋掉, 因為從 sdcard 複製到系統的 data 裡面時,權限可能會錯; android 裡每個 app 都有自己的 uid gid, 存檔的權限不對的話,app 可能會無法讀取、寫入存檔。 建議是用修改的方式,像用 cat /sdcard/com.nimblebit.nimblequest.xml > /data/data/com.nimblebit.nimblequest/shared_prefs/com.nimblebit.nimblequest.xml

用 android 內建的備份功能 adb backup

這是不需要 root 的作法,但需要在電腦裝 adb 與 java 執行環境 (不需要 android 開發環境)。 android 有一個用 adb 執行的備份功能,可以備份和還原 app 的資料; 再加上另一支 java 程式 android backup extractor,可以讀取和製做備份檔。 我是參考一篇 巴哈 alexkeroro 小屋的文章

將手機和電腦連上, adb devices 讀得到後, 一樣先找到 app 的 id, 輸入 adb backup -f my-backup.ab -noshared -noapk -noobb com.nimblebit.nimblequest , 之後 android 手機會跳出畫面向你確認, 並要求輸入密碼加密備份檔。 之後會產生一個名為 my-backup.ab 的備份檔, 其中不含有 app 的 apk 和 obb 資料。

如果想把 apk 和 obb 也包在備份檔裡, 就把 -noapk -noobb 改成 -apk -obb 。 如果想一次備份多個也可以,就把想備份的 app 名稱列在後面即可; 如果想備份所有 app 資料,也可以簡單用 -all 參數: adb backup -f all-backup.ab -noshared -noapk -noobb -all 。 另外備份的密碼請記得,忘了沒人救的了你, 如果你根本不想加密,可以輸入 0 之類的,至少不會忘記。

之後去下載 android backup extractor, 編譯好可以直接用 jre 執行的 jar 檔案可以在 release 找到。 下載下來後可以用 java -jar abe.jar 執行, 會列出簡短的使用說明。 我們首先要把 my-backup.ab 轉換成一般壓縮軟體可以讀的格式: java -jar abe.jar unpack my-backup.ab my-backup.tar 0 , 可以把密碼為 0 的 my-backup.ab 檔案轉換成沒加密的 my-backup.tar 檔案。 如果你的密碼有特殊字元如空白,請自己加上雙引號。

解壓後看到的會和手機內的 data 格式不太一樣, 會是 apps/com.nimblebit.nimblequest/ , 然後會有 apk 和 data 內的資料等。 data 內的資料,如 shared_prefs 會變成 sp , files 變成 f 之類的,子資料夾中的其它檔名就還是一樣。 在修改時一樣要注意保留權限, 但如果是 windows 我不知道會發生什麼事。

之後包回去不是單純用 tar 再壓回去就好, 因為 android backup 對 tar 內的格式要求很高, 像不能包到父資料夾,順序也不能亂, 如果只是簡單包回去很容易壞掉。 可以參考 android backup extractor 的說明 , 最保險的作法是參考原本的 tar 來包:

tar --list --file my-backup.tar |
    tar --files-from - --create --file new-backup.tar

包好後就可以用 pack 打包回去: java -jar abe.jar pack new-backup.tar new-backup.ab , 打包時可以不設密碼,要設一樣打在最後面。 然後用 adb restore new-backup.ab 就可以了。

從 recovery 備份的映象檔還原

但我以前的手機多半是刷成磚了或是電池壞了, 所以也沒辦法用 adb 備份。 但我有留當時刷機前備份的映象檔, 就拿出來看能不能找出當時的存檔。

找了三台手機的備份,第一台是六年前的 zenfone 4, 第二台是紅米,備份都是直接一個 tar,很好處理。 可惜那台手機我沒有裝 pumpkins vs monsters, 所以沒救。 比較有趣是,可能因為 fat32 檔案大小不能超過 4G, 所以該 tar 都有切成幾個, 在解壓時要用 cat 連接起來: cat data.tar.? | tar -t > file.list

再往前翻,是 sone ericsson w8, 這台就比較有趣,當初是用 xrecovery 備份的, 備份檔真的是映象檔。 本來預期應該是 ext2 之類的, 但 file(1)竟然不認識:

$ file data.img 
data.img: data

本以為涼了,碰到 xrecovery 的專有格式。 但還是多少 google 一下 xrecovery data.img format 之類的關鍵字, 才發現早期的 android 似乎不是用 ext2, 而是一個稱 yaffs 的檔案系統。 用 apt 找一下,還給我找到了可以用的工具 unyaffs, 於是就解開來壓縮,拿到 data 分區裡的資料了。

pumpkins vs monsters

pumpkins vs monsters 的存檔是放在 /data/data/com.RunnerGames.game.PumpkinsVsMonster_AD/files/Pumpkins01.ini , 而且是個二進位檔, 這裡就放上我目前的存檔十六進位碼, 用 xxd -p -r 就可以複原回二進位格式了。

e90300000101014a0000001c690200190000001800000019000000020000
00020000000200000002000000020000000200000001000000000000000c
000000080000000700000001000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
00000000040000001000000005000000000b000000cb0000000f000000

這個存檔是打完所有基本關卡, 剩萬聖節的特別關卡還沒過。 不過我記得當年是有全破的,用炸藥炸一炸就過了。 而且這個存檔的錢是超多,因為原本很堅持不用炸藥, 但後來面不用炸藥實在太難,所以還是用了。

我後來用的 atom 螢幕有點小, 造成雙擊來消除南瓜的判定很難達成, 所以我幾乎無法消除南瓜。 這樣用一點炸藥來通關應該還好吧。