# NDS SaveCraftr
A smart, universal Nintendo DS save file craftr that automatically detects whether to expand or trim save files for different platforms.
## Features
🎮 **Universal Compatibility**: Works with save files from R4 flashcarts, TWiLight Menu++, DeSmuME, NO$GBA, and other DS emulators
🧠 **Smart Auto-Detection**:
- Files < 512KB → Automatically expands to 512KB (perfect for TWiLight Menu++)
- Files = 512KB → Automatically trims trailing zeros (perfect for R4/flashcarts)
⚡ **Fast & Reliable**: Uses efficient algorithms with smart rounding to standard DS save sizes
🧠 **Smart Trimming**: Automatically rounds up to standard sizes (64KB, 128KB, 256KB, 512KB) when close
🛠️ **Manual Override**: Force specific sizes when needed
## Installation
### From PyPI (recommended)
```bash
pip install nds-savecraftr
```
### From source
```bash
git clone https://github.com/yourusername/nds-savecraftr
cd nds-savecraftr
pip install .
```
## Usage
### Command Line
```bash
# Auto-detect mode (recommended)
nds-savecraftr game.sav
# Short command alias
savecraftr game.sav
# Custom output file
nds-savecraftr game.sav converted.sav
# Force specific size (128KB example)
nds-savecraftr game.sav converted.sav 128
# Quiet mode
nds-savecraftr -q game.sav
```
### Python API
```python
from nds_savecraftr import convert_save
# Auto-detect conversion
convert_save("game.sav")
# Custom output and size
convert_save("input.sav", "output.sav", target_size_kb=256)
```
## How It Works
The craftr uses a smart algorithm that:
1. **Scans from the end** of the file backwards to find the last non-zero byte
2. **Identifies trailing zeros** as padding (safe to remove)
3. **Preserves legitimate zeros** in the middle of save data
4. **Smart rounding**: If close to standard DS sizes (64KB, 128KB, 256KB, 512KB), rounds up to prevent compatibility issues
5. **Auto-detects the best conversion** based on input file size
### Conversion Modes
| Input Size | Auto Mode | Result | Use Case |
|------------|-----------|---------|----------|
| < 512KB | Expansion | → 512KB | TWiLight Menu++, DeSmuME |
| = 512KB | Smart Trimming | → Actual data size (rounded up if close to standard) | R4, flashcarts |
| Manual | Force size | → Specified size | Custom requirements |
## Supported Formats
✅ Raw .sav files (R4, flashcarts)
✅ DeSmuME .dsv files
✅ NO$GBA save files
✅ TWiLight Menu++ saves
✅ Most DS emulator formats
## Examples
### R4 to TWiLight Menu++
```bash
# Your R4 save (128KB) → TWiLight Menu++ format (512KB)
nds-savecraftr pokemon.sav
# Output: pokemon_converted.sav (512KB)
```
### TWiLight Menu++ to R4
```bash
# Your TWiLight save (512KB) → R4 format (smart-trimmed)
nds-savecraftr pokemon_twilight.sav
# Output: pokemon_twilight_converted.sav
# If data ends at ~127.8KB → rounds to 128KB (safe for R4)
# If data ends at ~120KB → stays 120KB (natural size)
```
### Mario Kart DS Example
```bash
# Convert Mario Kart DS save (256KB) to TWiLight format
nds-savecraftr mario_kart_ds.sav
# Output: mario_kart_ds_converted.sav (512KB)
# Or trim a 512KB version back to minimal size
nds-savecraftr mario_kart_ds_512kb.sav
# Output: mario_kart_ds_512kb_converted.sav (256KB, smart-trimmed)
```
### Manual Size Control
```bash
# Force 256KB output
nds-savecraftr game.sav output.sav 256
```
## Troubleshooting
### Save doesn't load after conversion
- Ensure the output filename exactly matches your ROM name
- Some games require specific save sizes - try the auto-detect mode first
- Check that your emulator/flashcart supports the output file size
### File not found error
- Check the file path is correct
- Ensure you have read permissions for the input file
- Make sure the output directory exists
## Development
### Running Tests
```bash
pip install -e ".[dev]"
pytest
```
### Building
```bash
python -m build
```
## License
MIT License - feel free to use in your projects!
## Contributing
Pull requests welcome! Please ensure tests pass and follow the existing code style.
## Changelog
### v1.0.0
- Initial release
- Smart auto-detection algorithm
- Support for all major DS save formats
- Command line and Python API
- Comprehensive test suite
- Mario Kart DS example save included
Raw data
{
"_id": null,
"home_page": "https://github.com/tcsenpai/nds-savecraftr",
"name": "nds-savecraftr",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "nintendo, ds, save, converter, twilight, menu, r4, flashcart, craftr",
"author": "tcsenpai",
"author_email": "tcsenpai <tcsenpai@discus.sh>",
"download_url": "https://files.pythonhosted.org/packages/29/5d/7d4ea68df5d540757c3be55322de8a9b28ae2573b1c0a43dd19349fb0ab3/nds_savecraftr-1.0.0.tar.gz",
"platform": null,
"description": "# NDS SaveCraftr\n\nA smart, universal Nintendo DS save file craftr that automatically detects whether to expand or trim save files for different platforms.\n\n## Features\n\n\ud83c\udfae **Universal Compatibility**: Works with save files from R4 flashcarts, TWiLight Menu++, DeSmuME, NO$GBA, and other DS emulators\n\n\ud83e\udde0 **Smart Auto-Detection**: \n- Files < 512KB \u2192 Automatically expands to 512KB (perfect for TWiLight Menu++)\n- Files = 512KB \u2192 Automatically trims trailing zeros (perfect for R4/flashcarts)\n\n\u26a1 **Fast & Reliable**: Uses efficient algorithms with smart rounding to standard DS save sizes\n\n\ud83e\udde0 **Smart Trimming**: Automatically rounds up to standard sizes (64KB, 128KB, 256KB, 512KB) when close\n\n\ud83d\udee0\ufe0f **Manual Override**: Force specific sizes when needed\n\n## Installation\n\n### From PyPI (recommended)\n```bash\npip install nds-savecraftr\n```\n\n### From source\n```bash\ngit clone https://github.com/yourusername/nds-savecraftr\ncd nds-savecraftr\npip install .\n```\n\n## Usage\n\n### Command Line\n```bash\n# Auto-detect mode (recommended)\nnds-savecraftr game.sav\n\n# Short command alias\nsavecraftr game.sav\n\n# Custom output file\nnds-savecraftr game.sav converted.sav\n\n# Force specific size (128KB example)\nnds-savecraftr game.sav converted.sav 128\n\n# Quiet mode\nnds-savecraftr -q game.sav\n```\n\n### Python API\n```python\nfrom nds_savecraftr import convert_save\n\n# Auto-detect conversion\nconvert_save(\"game.sav\")\n\n# Custom output and size\nconvert_save(\"input.sav\", \"output.sav\", target_size_kb=256)\n```\n\n## How It Works\n\nThe craftr uses a smart algorithm that:\n\n1. **Scans from the end** of the file backwards to find the last non-zero byte\n2. **Identifies trailing zeros** as padding (safe to remove) \n3. **Preserves legitimate zeros** in the middle of save data\n4. **Smart rounding**: If close to standard DS sizes (64KB, 128KB, 256KB, 512KB), rounds up to prevent compatibility issues\n5. **Auto-detects the best conversion** based on input file size\n\n### Conversion Modes\n\n| Input Size | Auto Mode | Result | Use Case |\n|------------|-----------|---------|----------|\n| < 512KB | Expansion | \u2192 512KB | TWiLight Menu++, DeSmuME |\n| = 512KB | Smart Trimming | \u2192 Actual data size (rounded up if close to standard) | R4, flashcarts |\n| Manual | Force size | \u2192 Specified size | Custom requirements |\n\n## Supported Formats\n\n\u2705 Raw .sav files (R4, flashcarts) \n\u2705 DeSmuME .dsv files \n\u2705 NO$GBA save files \n\u2705 TWiLight Menu++ saves \n\u2705 Most DS emulator formats \n\n## Examples\n\n### R4 to TWiLight Menu++\n```bash\n# Your R4 save (128KB) \u2192 TWiLight Menu++ format (512KB)\nnds-savecraftr pokemon.sav\n# Output: pokemon_converted.sav (512KB)\n```\n\n### TWiLight Menu++ to R4\n```bash\n# Your TWiLight save (512KB) \u2192 R4 format (smart-trimmed)\nnds-savecraftr pokemon_twilight.sav\n# Output: pokemon_twilight_converted.sav \n# If data ends at ~127.8KB \u2192 rounds to 128KB (safe for R4)\n# If data ends at ~120KB \u2192 stays 120KB (natural size)\n```\n\n### Mario Kart DS Example\n```bash\n# Convert Mario Kart DS save (256KB) to TWiLight format\nnds-savecraftr mario_kart_ds.sav\n# Output: mario_kart_ds_converted.sav (512KB)\n\n# Or trim a 512KB version back to minimal size\nnds-savecraftr mario_kart_ds_512kb.sav\n# Output: mario_kart_ds_512kb_converted.sav (256KB, smart-trimmed)\n```\n\n### Manual Size Control\n```bash\n# Force 256KB output\nnds-savecraftr game.sav output.sav 256\n```\n\n## Troubleshooting\n\n### Save doesn't load after conversion\n- Ensure the output filename exactly matches your ROM name\n- Some games require specific save sizes - try the auto-detect mode first\n- Check that your emulator/flashcart supports the output file size\n\n### File not found error\n- Check the file path is correct\n- Ensure you have read permissions for the input file\n- Make sure the output directory exists\n\n## Development\n\n### Running Tests\n```bash\npip install -e \".[dev]\"\npytest\n```\n\n### Building\n```bash\npython -m build\n```\n\n## License\n\nMIT License - feel free to use in your projects!\n\n## Contributing\n\nPull requests welcome! Please ensure tests pass and follow the existing code style.\n\n## Changelog\n\n### v1.0.0\n- Initial release\n- Smart auto-detection algorithm \n- Support for all major DS save formats\n- Command line and Python API\n- Comprehensive test suite\n- Mario Kart DS example save included\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Universal Nintendo DS Save File Craftr",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/tcsenpai/nds-savecraftr",
"Issues": "https://github.com/tcsenpai/nds-savecraftr/issues",
"Repository": "https://github.com/tcsenpai/nds-savecraftr"
},
"split_keywords": [
"nintendo",
" ds",
" save",
" converter",
" twilight",
" menu",
" r4",
" flashcart",
" craftr"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "730cacdc4aea857eb787f2f5a1354ddde00cb4a12a6040f5064ecbcda12542b1",
"md5": "cc3b353c693bd766adf50365e88b1116",
"sha256": "91f8407cac2bf701ab16ec111a2c0de1b8cf967e332559c37c02972b36ca50ad"
},
"downloads": -1,
"filename": "nds_savecraftr-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cc3b353c693bd766adf50365e88b1116",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 8428,
"upload_time": "2025-08-07T18:43:12",
"upload_time_iso_8601": "2025-08-07T18:43:12.754256Z",
"url": "https://files.pythonhosted.org/packages/73/0c/acdc4aea857eb787f2f5a1354ddde00cb4a12a6040f5064ecbcda12542b1/nds_savecraftr-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "295d7d4ea68df5d540757c3be55322de8a9b28ae2573b1c0a43dd19349fb0ab3",
"md5": "3fd161faf765e1cdabdb18f28a738534",
"sha256": "04a16d8a0bcf463e3d8a665512f63740426490427e31866c21af90d6dca74d8d"
},
"downloads": -1,
"filename": "nds_savecraftr-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "3fd161faf765e1cdabdb18f28a738534",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 7815,
"upload_time": "2025-08-07T18:43:14",
"upload_time_iso_8601": "2025-08-07T18:43:14.383950Z",
"url": "https://files.pythonhosted.org/packages/29/5d/7d4ea68df5d540757c3be55322de8a9b28ae2573b1c0a43dd19349fb0ab3/nds_savecraftr-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-07 18:43:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tcsenpai",
"github_project": "nds-savecraftr",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "nds-savecraftr"
}