Client File Structure¶
This document describes the client-side file structures, encryption specifications, and internal data structures based on analysis of the client.
Save Data Directory (Application.persistentDataPath)¶
The game's save files and cache files are stored within Unity's Application.persistentDataPath and platform-specific internal paths. Depending on the platform (Android or iOS), these map to the following absolute paths:
Platform-Specific Absolute Paths¶
| Platform | File Type | Absolute Path | Details & Access Methods |
|---|---|---|---|
| Android | Secure Data (key.d) |
/data/data/<APK package name>/files/key.d |
Native secure storage located in the Internal Storage. Requires root access or ADB shell access to view directly. |
Normal Data (o.d, a.d, s.d, vc.b) |
/storage/emulated/0/Android/data/<APK package name>/files/ |
External Storage (Unity's default persistentDataPath location for normal files). Accessible via PC (MTP connection) or Android File Manager apps without root. |
|
| iOS | Secure Data (offKey) |
iOS Keychain (offKey item) |
Keychain entry named offKey. Extraction tools (e.g., KRFN iOS Key Dumper) often decrypt and download this item as a file named key.d. |
Normal Data (o.d, a.d, s.d, vc.b) |
Applications/AppDomain-<IPA package name>/Documents |
Secure sandbox Documents folder. Accessible via backup utilities (e.g., iMazing), Xcode Device Manager, or jailbroken environments. |
Save Data Folders¶
| Folder Name | Primary Path | Managing Class | Data Role |
|---|---|---|---|
a.b |
Application.temporaryCachePath + "/a.b" |
Meige.AssetBundles.AssetbundleCache |
Legacy Asset Bundle Cache (Deprecated, cleaned on launch) |
a.b2 |
Application.persistentDataPath + "/a.b2" |
Meige.AssetBundles.Utility |
Active Asset Bundle Cache (iCloud backup excluded) |
c.r |
CriWare.installTargetPath + "/c.r" |
Star.CRIFileInstaller |
CRIWare Sound Cache (Temporary on iOS, Persistent on Android) |
a.b (Legacy Asset Bundle Cache)¶
This directory was used in early-to-mid client versions (e.g., 1.0.3) to cache downloaded asset bundles. Because it was located in temporaryCachePath, the OS could automatically delete its contents when device storage ran low. In later versions, this cache was deprecated and is automatically cleaned up asynchronously on client launch.
a.b2 (Active Asset Bundle Cache)¶
This directory is used in later client versions (e.g., 3.6.0) and the offline version to store all cached asset bundles. Because offline play depends on pre-downloaded assets that cannot be re-downloaded after server termination, the cache location was moved to persistentDataPath to prevent automatic OS deletion. To comply with store guidelines, the client sets the iOS NoBackup flag (Device.SetNoBackupFlag) on this folder.
c.r (CRIWare Sound Cache)¶
This directory stores downloaded CRIWare sound files, including background music (BGM) and character voices (AWB and ACB files). It is managed by CRIFileInstaller. Sound files are downloaded via CriFsWebInstaller and installed into this directory.
The underlying path CriWare.installTargetPath depends on the platform:
- iOS (
RuntimePlatform.IPhonePlayer):Application.temporaryCachePath(Temporary cache, susceptible to automatic OS deletion under low storage conditions). - Android / Other Platforms:
Application.persistentDataPath(Persistent storage, protected from automatic OS cleanup).
Version management for each audio file is stored in custom PlayerPrefs (BundleVersion.bin) using keys prefixed with cri_ (e.g., cri_{filename}).
Save Data Files¶
| Primary File | Backup File | Managing Class | Data Role |
|---|---|---|---|
a.d |
a.d2 |
Star.AccessSaveData |
Account credentials & Access token (Online main save) |
o.d |
o.d2 |
Star.OfflineSaveData |
Local progress, Characters, Story flags (Offline main save) |
key.d |
- | jp.co.meteorise.star.OfflineDataAccessor |
Decryption key for o.d (OfflineSaveData) |
s.d |
s.d2 |
Star.LocalSaveData |
Local settings (Volume, Battle options, UI Filters) |
vc.b |
vc2.b2 |
Meige.AssetBundles.AssetBundleVersionCache |
Asset Bundle version and MD5 cache |
BundleVersion.bin |
- | PreviewLabs.PlayerPrefs |
Custom PlayerPrefs (CRIWare sound versions, legacy asset versions, temporary UI states) |
VFJMb2NhbENhc2g.www |
- | Star.SystemScheduleLinkManager |
Room schedule times and character action queue states |
a.d (AccessSaveData)¶
This is the most critical save file for the online version. It contains account credentials, the device UUID, and the access token used for server-side API communication. Without this file, the client cannot authenticate with the game servers to retrieve or save user progress.
General info¶
| Item | Specification |
|---|---|
| Target Class | Star.AccessSaveData (AccessSaveData.cs) |
| Save Path | Application.persistentDataPath + "/a.d" (Backup: a.d2) |
| File Format | MessagePack (MsgPack) |
| Encryption | AES-256-CBC |
| Encryption Key | Fixed 32-byte key: <ENCRYPTION_KEY from AccessSaveData.cs> |
| Initialization Vector (IV) | Dynamic IV (recovered from the file header) |
Dynamic IV Decryption Algorithm¶
- Read the first 4 bytes of the file as a little-endian
int(header). - Calculate a mask value:
mask = header & 0x7F. - Read the 5th byte (
file_bytes[4]) and subtractmaskto get the password lengthpw_len. - Read the next
pw_lenbytes aspw_bytes. - Recover each byte of the password via:
pw_bytes[i] = (pw_bytes[i] - 0x60 - i) & 0xFF. - Decode
pw_bytesas a UTF-8 string to get the dynamic 16-character AES IV. - Read the next 4 bytes as a little-endian
int(enc_len) representing the length of the encrypted body. - Decrypt the remaining
enc_lenbytes using the fixed key and recovered IV.
Version Mismatch & Data Deletion¶
The save data version (19 / SaveDataVersion._171101) is embedded in the file header via (header & 0xFFFF00FF) | (version << 8). If loaded with a version mismatch, both the primary save file (a.d) and its backup file (a.d2) are automatically deleted.
Internal Data Structure (SaveData Class)¶
| Member Variable | Type | Description |
|---|---|---|
m_UUID |
string |
Device-specific UUID |
m_AccessToken |
string |
Access token used for server authentication |
m_ConfirmedVer |
int |
Version of the agreed terms of service / privacy policy |
m_MyCode |
string |
Player's friend code (My Code) |
o.d (OfflineSaveData)¶
This file is specifically used in the final offline version to store and persist game progress locally without server communication. In the offline version, it becomes the most critical save file containing character details, user profile stats, story completion flags, and sub-offers, keeping the entire gameplay state updated on the client side.
General info¶
| Item | Specification |
|---|---|
| Target Class | Star.OfflineSaveData (OfflineSaveData.cs) |
| Save Path | Application.persistentDataPath + "/o.d" (Backup: o.d2) |
| File Format | MessagePack (MsgPack) |
| Encryption | AES-256-CBC |
| Encryption Key | 32-byte binary key retrieved from key.d |
| Initialization Vector (IV) | The first 16 bytes of the file (the encrypted payload starts from byte offset 16) |
Internal Data Structure (SaveData Class)¶
| Member Variable | Type | Description |
|---|---|---|
UserData |
UserData |
Player's basic profile (name, player level, stamina, etc.) |
UserCharaDatas |
List<UserCharacterData> |
List of all owned character cards (levels, limit breaks, skill levels, etc.) |
UserAdvData |
UserAdvData |
Unlock, progress, and read status of story scenarios (ADV) |
m_SubOffers |
OfferManager.SubOffer[] |
Sub-offer (Job/Work feature) status data |
m_UserNamedDatas |
Dictionary<eCharaNamedType, UserNamedData> |
Character-specific room progress and dedicated weapon management data |
key.d (OfflineKeyData) / offKey (iOS Keychain)¶
This key data decrypts the offline save data (o.d). While stored as a physical file on Android, it is stored in the Keychain on iOS.
General info¶
| Item | Specification |
|---|---|
| Role | Stores the 32-byte AES-256 key for o.d decryption |
| Data Location (Android) | OS Native Secure Storage (/data/data/<APK package name>/files/key.d) |
| Data Location (iOS) | iOS Keychain (Stored under the account/item name offKey) |
Platform-Specific Retrieval Logic¶
- Android:
Generated or retrieved from the native secure storage via the native plugin
jp.co.meteorise.star.OfflineDataAccessoras a physical file namedkey.d. - iOS:
Safely stored in the iOS Keychain under the entry name
offKey(accessible viaStar.OfflineSaveData.getKey()). Note that extraction tools (such as the iOS Key Dumper) decrypt this Keychain item and output it as a file namedkey.dfor convenience.
s.d (LocalSaveData)¶
This file manages local game settings such as volume levels, battle options, UI filters, sorting preferences, and caching metadata.
General info¶
| Item | Specification |
|---|---|
| Target Class | Star.LocalSaveData (LocalSaveData.cs) |
| Save Path | Application.persistentDataPath + "/s.d" (Backup: s.d2) |
| File Format | MessagePack (MsgPack) |
| Encryption | AES-256-CBC |
| Encryption Key | Fixed 32-byte key: <ENCRYPTION_KEY from LocalSaveData.cs> |
| Initialization Vector (IV) | Dynamic IV (recovered from the file header) |
Dynamic IV Decryption Algorithm¶
- Read the first 4 bytes of the file as a little-endian
int(header). - Calculate a mask value:
mask = header & 0xFF. - Read the 5th byte and subtract
maskto get the password lengthpw_len. - Read the next
pw_lenbytes aspw_bytes. - Recover each byte of the password via:
pw_bytes[i] = (pw_bytes[i] - 0x60 - i) & 0xFF. - Decode
pw_bytesas a UTF-8 string to get the dynamic 16-character AES IV. - Read the next 4 bytes as
enc_len(encrypted body size) and decrypt the subsequent bytes.
Note
Version & Automatic Regeneration
Save data version 33 (SaveDataVersion._171130) is embedded into the header. If this file is deleted, it will be automatically regenerated with default settings upon the next game launch.
Internal Data Structure (SaveData Class)¶
| Category | Member Variable | Type | Description |
|---|---|---|---|
| Volume Settings | m_BgmVolume |
float |
BGM volume (0.0 to 1.0) |
m_SeVolume |
float |
SE volume (0.0 to 1.0) | |
m_VoiceVolume |
float |
Voice volume (0.0 to 1.0) | |
m_MovieVolume |
float |
Movie volume (0.0 to 1.0) | |
| Battle Settings | m_BattleEffect |
eAmount |
Battle effect display quality (High / Middle / Low) |
m_BattleSpeedLvs |
int[] |
Battle speed level (Normal = 1.0f, Fast = 2.5f) | |
m_BattleAutoMode |
bool |
Auto-battle enablement flag | |
m_BattleUseSkillInAuto |
bool |
Flag to use skills during auto-battle | |
m_BattleAutoCancel |
eBattleAutoCancelType |
Auto-battle cancellation conditions | |
m_BattleSkipTogetherAttackInput |
bool |
Flag to skip the "Together Attack" (とっておき) animation inputs | |
m_BattleSkipUniqueSkill |
bool |
Flag to skip dedicated weapon skill animations | |
| UI Options | m_UISortParams |
List<UISortParam> |
UI sorting parameters (ascending/descending, sort keys) |
m_UIFilterParams |
List<UIFilterParam> |
Bit flags for various UI filters | |
| Voice Downloads | (Voice download flags) | - | Configuration flags for downloading full voice lines (scenario, event, memorial) |
| Cache Management | m_CacheClearParams |
List<CacheClearParam> |
Version management and cache clearance flags for each content database |
vc.b (VersionCache)¶
This file manages downloaded asset bundle versions, MD5 hashes, sizes, and encryption states.
General info¶
| Item | Specification |
|---|---|
| Target Class | Meige.AssetBundles.AssetBundleVersionCache (Defined in AssetBundleVersionCache.cs & Utility.cs) |
| Save Path | Application.persistentDataPath + "/vc2/vc.b" (Backup: vc2/vc2.b2) |
| File Format | JSON (Newtonsoft.Json) encrypted and base64-encoded |
| Encryption | DES-CBC |
| DES Key | <prefix of VersionCache_key from Utility.cs> + first 4 characters of device unique identifier (SystemInfo.deviceUniqueIdentifier.Substring(0, 4)) |
| DES IV | <prefix of VersionCache_iv from Utility.cs> + first 4 characters of device unique identifier |
Encryption and Serialization¶
The encrypted JSON binary data is Base64 encoded and written using .NET's BinaryWriter.Write(string). As a result, the file begins with an LEB128 (Variable-length integer) byte-length prefix.
Internal Data Structure (VersionCache Class)¶
| Member Variable | Type | Description |
|---|---|---|
m_FileVersion |
string |
Version of the cache file format itself (typically "0.2") |
m_Dictionary |
Dictionary<string, Utility.AssetBundleVersionParam> |
Key: Asset bundle hash name (filename) Value: Asset metadata parameters (detailed below) |
Utility.AssetBundleVersionParam Data Structure¶
| Member Variable | Type | Description |
|---|---|---|
name |
string |
Original asset name (relative asset path, etc.) |
version |
string |
MD5 hash string of the asset |
crc |
uint |
CRC32 checksum |
size |
long |
File size in bytes |
isEncrypt |
bool |
Flag indicating whether the asset is encrypted |
BundleVersion.bin (PlayerPrefs)¶
This file manages various client-side persistent configurations, user preferences, and flags using a custom PlayerPrefs implementation. To prevent tampering by players, it is saved under a deceptive file name that mimics an asset bundle version cache file.
General info¶
| Item | Specification |
|---|---|
| Target Class | PreviewLabs.PlayerPrefs (defined in PlayerPrefs.cs) |
| Save Path | Application.persistentDataPath + "/BundleVersion.bin"(Unencrypted fallback: PlayerPrefs.txt) |
| File Format | Custom serialized key-value pairs formatted as Key : Value : Type |
| Encryption | DES (Data Encryption Standard) |
| DES Key & IV | Fixed 8-byte key/IV: <prefix of secureFileName key from PlayerPrefs.cs> + first 4 characters of device unique identifier (SystemInfo.deviceUniqueIdentifier.Substring(0, 4)) |
Key Storage Areas¶
The following specific parameters and keys are saved within this custom PlayerPrefs file:
- CRIWare Sound Version Cache
- Key Format:
cri_{FileName}(e.g.,cri_bgm_001.awb) - Type:
System.String - Description: Tracks the downloaded/installed versions of CRIWare audio files (BGM, voices). It is managed by
Star.CRIFileInstallerto determine if a sound asset update is required.
- Key Format:
- Asset Bundle Legacy Version Cache
- Key Format:
AssetbundleVersion_{BundleName}(e.g.,AssetbundleVersion_chara/hero_001.muast) - Type:
System.String - Description: Deprecated version tracking used before
vc.b(AssetBundleVersionCache) was implemented. These keys are deleted byMeige.AssetBundles.AssetbundleCachewhen clearing local caches to ensure clean states.
- Key Format:
- UI Dialog Temporary Session State
- Key Format:
Temp_ADVVoiceDownloadWindow_Category_{InstanceID}(e.g.,Temp_ADVVoiceDownloadWindow_Category_-12345) - Type:
System.Int32 - Description: Manages the active category of open dialog instances in
Star.ADVVoiceDownloadWindow(e.g., Story vs Event categories).
- Key Format:
Serialization Format¶
The internal data is stored in a hash table and serialized into a single string. The formatting rules are as follows:
- Key-value-type elements are separated by
:(a space, a colon, and a space). - Different parameters are separated by
;(a space, a semicolon, and a space). - Special characters in keys and values are escaped with a backslash (
\).
Example of raw entry before encryption:
cri_bgm_001.awb : 12 : System.String ; Temp_ADVVoiceDownloadWindow_Category_-12345 : 1 : System.Int32
VFJMb2NhbENhc2g.www (SystemScheduleLinkManager)¶
This file manages Room (My Room) schedule times and character action queue states. To obscure its purpose, the file name is generated by Base64-encoding the string "TRLocalCash" (or "TRLocalCash.dat").
General info¶
| Item | Specification |
|---|---|
| Target Class | Star.SystemScheduleLinkManager (defined in SystemScheduleLinkManager.cs) |
| Save Path | Application.persistentDataPath + "/VFJMb2NhbENhc2g.www" (Base64 of "TRLocalCash") |
| File Format | Binary serialization with custom structure headers |
| Encryption | Custom XOR-based lightweight encryption (BinaryFileUtil.CipherCode) |
Internal Data Structure¶
The binary file is divided into custom headers and serialized key-value blocks:
- File Header (
FileHeader)m_Key(short): Tag key for the record type (1= TimeKey,2= ActionTag,0= End).m_Size(int): Payload block size.
- Time Record (
SystemTimeKey)m_Times(long): The Unix timestamp/schedule time for the Room (UserFieldChara.ScheduleTime).
- Character Action Record (
RoomActionChara)m_ManageID(long): Unique character card identifier.m_ActionKey(int): Current action or movement animation key assigned to the character in the room.
*.d2, *.b2 (BackupFiles)¶
The backup files with a 2 suffix (such as a.d2, o.d2, s.d2, and vc2.b2) serve as robust local backups for the primary save and cache files. They are managed automatically by the client code to prevent data loss due to unexpected app crashes, write corruption, or load failures.
General info¶
| Item | Specification |
|---|---|
| Role | Robust local backup copy to prevent save data loss |
| File Format | Identical to their respective primary files (MsgPack / JSON) |
| Creation Event | Automatically created when writing new primary save data |
| Trigger Conditions | Load failure or decryption exception of the primary file |
Backup Creation Algorithm¶
During a save operation, the client performs the following steps to secure the existing state before writing new data:
- Check if the primary file (e.g.,
a.d) exists on the filesystem. - If it exists, copy the primary file to its backup path (e.g.,
a.d2), overwriting any existing backup file. - Write and encrypt the new data to the primary file path.
// Example backup copy on save (AccessSaveData.cs)
if (File.Exists(SaveFile)) {
File.Copy(SaveFile, SaveFileBak, true);
}
Fallback Restore Algorithm¶
During a load operation, the client attempts a safe recovery if the primary data is corrupted or inaccessible:
- Attempt to load and decrypt the primary file (e.g.,
a.d). - If an exception is caught (indicating decryption failure, header mismatch, or disk read error):
- Check if the backup file (e.g.,
a.d2) exists. - If it exists, attempt to load, decrypt, and deserialize the backup file.
- Check if the backup file (e.g.,
- If the backup file also fails to load or does not exist, return failure (or delete all data if a version mismatch is detected).