3DSync
Homebrew for the Nintendo 3DS/2DS family that synchronises saves and files with cloud storage.
Bidirectional sync with Google Drive and Dropbox, plus
experimental support for an SMB2/3 file server, FTP/FTPS
and WebDAV.
Quick Start
- Open the configurator and follow the three steps.
- Place the downloaded
3DSync.inion the SD card at/3ds/3DSync/3DSync.ini. - Install
output/3ds-arm/3DSync.ciaor run3DSync.3dsxfrom the Homebrew Launcher. - Launch 3DSync. It will sync all configured paths — press START to exit.
Configuration
The INI file lives at /3ds/3DSync/3DSync.ini.
Dropbox
[Dropbox]
AppKey=<app key from configurator>
RefreshToken=<refresh token from configurator>
Path= ; optional folder inside the account
Configs with a bare Token= still work, but Dropbox access tokens expire after about
four hours — re-run the configurator to get a refresh token instead.
add_to_driveGoogle Drive
[GoogleDrive]
ClientId=<OAuth client ID>
ClientSecret=<OAuth client secret>
RefreshToken=<refresh token from configurator>
FolderId=<optional root folder ID>
FolderId restricts all Drive operations to one folder. Leave it out to use Drive root.
storageSMB file server (NAS, Windows share)EXPERIMENTAL
[SMB]
Server=192.168.1.10
Share=3ds
User=<username>
Password=<password>
Domain= ; optional, for a Windows domain
Path= ; optional folder inside the share
Speaks SMB2/SMB3, the dialects modern NAS boxes and Windows accept by default. SMB1 does not need to be re-enabled.
folder_sharedFTP / FTPSEXPERIMENTAL
[FTP]
Host=192.168.1.10
Port= ; optional, 21 (990 for TLS=implicit)
User=<username>
Password=<password>
Path= ; optional base directory
TLS=try ; none | try | require | implicit
Mode=passive ; passive | active
TLS=try encrypts the session when the server offers AUTH TLS and falls back
to plaintext otherwise. SFTP is not supported — the 3DS build of libcurl has no libssh2.
cloud_queueWebDAVEXPERIMENTAL
[WebDAV]
Url=https://nas.example/remote.php/dav/files/username/
User=<username>
Password=<app password>
Works with Nextcloud/ownCloud and any NAS with WebDAV enabled. Prefer an app password over your account password.
Configure as many remotes as you like — each is synced in turn against the same set of paths, and each keeps its own state in the manifest. The configurator only writes the Dropbox and Google Drive sections; add the others by hand.
About the EXPERIMENTAL badge
Google Drive and Dropbox have seen wide use. The other backends work, but have had far less testing against real servers — keep a backup of your saves, and please report anything that goes wrong at github.com/vllni/3DSync/issues. Bug reports and feedback are what move a backend off this list. 3DSync also prints this notice on the 3DS before it syncs.
Sync Paths
Four INI sections control which local paths to sync and how:
| Section | Direction | Subdirs |
|---|---|---|
[Paths] |
Bidirectional | Yes |
[ShallowPaths] |
Bidirectional | No |
[UploadPaths] |
Upload only | Yes |
[UploadShallowPaths] |
Upload only | No |
Each entry has the form RemoteName=LocalPath:
[Paths]
Checkpoint=/3ds/Checkpoint/saves
roms/nds/saves=/roms/nds/saves
[UploadPaths]
Backup=/3ds/MyGame
- RemoteName is the Drive folder path (use
/for nesting, e.g.roms/nds). - LocalPath is the absolute path on the SD card.
- Bidirectional entries use a manifest (
/3ds/3DSync/manifest.json) to detect which side changed. - Upload-only entries always push the local file to Drive and never download.
Bidirectional Sync Logic
Bidirectional paths ([Paths] / [ShallowPaths]) compare each file against
the local mtime, the Drive MD5 checksum, and the manifest from the last successful sync.
| Local changed? | Drive changed? | Action |
|---|---|---|
| No | No | Skip (up to date) |
| Yes | No | Upload local → Drive, update manifest |
| No | Yes | Download from Drive → local, update manifest |
| Yes | Yes | Conflict — press A to keep 3DS version (upload) or B to keep Drive version (download) |
| Local missing | Drive exists | Download from Drive |
| Local exists | Drive missing | Upload to Drive |
| Both missing | — | Remove stale manifest entry |
"Changed" means the mtime (local) or MD5 (Drive) differs from the last manifest entry. On first run (no manifest entry yet), the local file is uploaded and the manifest is initialised.
Manifest file
/3ds/3DSync/manifest.json is stored only on the SD card.
Delete it to force a full re-upload on the next run.
{
"/3ds/Checkpoint/saves/TitleA/001.sav": {"mtime": 1716905520, "md5": "abc123", "id": "driveFileId"},
"/roms/nds/saves/game.sav": {"mtime": 1716910000, "md5": "def456", "id": "anotherFileId"}
}
add_to_driveGoogle Drive App Setup
- Go to Google Cloud Console.
- Create a project and enable the Google Drive API.
- Create an OAuth 2.0 Web application credential (Client ID + Client Secret).
- Add the redirect URI:
https://3dsync.villani-ulm.de/configurator.html - Use the configurator to authenticate; it performs PKCE and stores the refresh token.