A modern reimplementation of darctool in Zig 0.15 for extracting and building 3DS DARC archive files.
DARC (Data ARChive) is an archive format used by Nintendo 3DS. This tool allows you to:
- Extract DARC archives to a directory
- Build DARC archives from a directory
- ✅ Full DARC format support (extraction and building)
- ✅ UTF-16LE filename handling
- ✅ Recursive directory processing
- ✅ Clean, modular codebase following DRY principles
- ✅ Memory-safe implementation in Zig
- ✅ Cross-platform support
The project is organized into several modules for maintainability:
src/
├── main.zig # CLI interface and argument parsing
├── root.zig # Module exports and public API
├── types.zig # Core data structures (DarcHeader, DarcTableEntry)
├── extractor.zig # Archive extraction functionality
├── builder.zig # Archive building functionality
└── utils.zig # Utility functions (UTF conversion, file I/O)
- DarcHeader: Archive header with magic number, BOM, version, and metadata
- DarcTableEntry: File/directory entry with name offset, data offset, and size
- DarcExtractor: Handles archive extraction with recursive directory support
- DarcBuilder: Constructs archives from filesystem directories
- Utils: Common utilities for UTF-16LE conversion and file operations
Requires Zig 0.15.2 or later.
zig buildThe executable will be generated in zig-out/bin/zarc.
zarc --extract <archive.arc> <output_directory>Example:
zarc --extract game.arc extracted/zarc --build <output.arc> <input_directory>Example:
zarc --build modified.arc source_files/The DARC archive format consists of:
-
Header (0x1c bytes):
- Magic: "darc" (0x63726164)
- BOM: 0xfeff (little-endian)
- Header length: 0x1c
- Version: 0x01000000
- File size, table offset/size, filedata offset
-
Table entries (12 bytes each):
- Filename offset (24-bit) + directory flag (bit 24)
- Data offset (for files) or unused (for directories)
- File size (for files) or end index (for directories)
-
Filename table: UTF-16LE null-terminated strings
-
File data: Raw file contents
Run the test suite:
zig build testThis implementation efficiently leverages Zig's standard library:
std.mem.indexOfScalar: Fast null terminator search in UTF-16 datastd.fs.path.join: Proper cross-platform path handlingstd.fs.File.readToEndAlloc: Optimized file reading with proper memory allocationstd.unicode: Built-in UTF-16LE ↔ UTF-8 conversionstd.fs.cwd().makePath: Recursive directory creation
This reimplementation improves upon the original C version:
- Type safety: Zig's strong type system prevents common bugs
- Memory safety: Automatic memory leak detection in debug builds
- Better error handling: Explicit error propagation with Zig's error system
- Modular design: Separated concerns with dedicated modules
- Modern tooling: Built-in build system and package manager
- Standard library usage: Efficient use of built-in path, file I/O, and string utilities
- When building archives, file order may differ from the original due to filesystem iteration order
- Archives may have different sizes due to alignment differences
- Both differences are normal and don't affect functionality
- Compressed archives must be decompressed before extraction
This is a reimplementation of the original darctool. The original tool's files (utils.c/h, types.h) from yellows8/darctool were used as reference.
- Original darctool by yellows8
- Zig reimplementation by the zarc project