Skip to content

feored/halbu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

160 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Halbu

A Rust library for parsing, editing, and safely re-encoding Diablo II: Resurrected .d2s save files.

It serves as the backend for Halbu Editor.


Features

  • Parse and modify .d2s save files
  • Supports the D2R Legacy and RotW layouts (v99, v105)
  • Editable sections:
    • character data
    • attributes
    • skills
    • quests
    • waypoints
    • mercenary data
  • Partial parsing via summary API
  • Strict or tolerant parsing modes
  • Validation for post-edit sanity checks
  • Compatibility checks for format conversion

Limitations

Some parts of the save format are not yet modeled:

  • Items
  • NPC section

These sections are preserved as raw bytes when possible, but may not round-trip identically after modifications.

Installation

cargo add halbu

Basic usage

Parse, modify, and write a save:

use halbu::{CompatibilityChecks, Save, Strictness};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bytes = std::fs::read("Hero.d2s")?;

    let parsed = Save::parse(&bytes, Strictness::Strict)?;
    let mut save = parsed.save;

    save.character.name = "Halbu".to_string();
    save.skills.set_all(20);

    let encoded = save.encode_for(save.format(), CompatibilityChecks::Enforce)?;
    std::fs::write("Halbu.d2s", encoded)?;

    Ok(())
}

Parsing modes

Strict parsing fails on inconsistencies:

let parsed = Save::parse(&bytes, Strictness::Strict)?;

Lax parsing continues and reports issues:

let parsed = Save::parse(&bytes, Strictness::Lax)?;
if !parsed.issues.is_empty() {
    eprintln!("Parse issues: {:?}", parsed.issues);
}

Validation

Validation is an optional step to check the save for inconsistencies that may prevent the game from loading the save (e.g. invalid character name or mercenary level).

let report = save.validate();
if !report.is_valid() {
    eprintln!("Validation issues: {:?}", report.issues);
}

Compatibility and encoding

Compatibility checks apply when converting between formats during encoding.

use halbu::{CompatibilityChecks, Save, Strictness};
use halbu::format::FormatId;

let parsed = Save::parse(&bytes, Strictness::Strict)?;
let save = parsed.save;

let target = FormatId::V99;
let issues = save.check_compatibility(target);

if !issues.is_empty() {
    eprintln!("Compatibility issues: {issues:?}");
}

// Safe (blocks on incompatibility)
let encoded = save.encode_for(target, CompatibilityChecks::Enforce)?;

// Unsafe (bypasses checks)
let forced = save.encode_for(target, CompatibilityChecks::Ignore)?;

Summary API

Read metadata without fully parsing the file:

let summary = Save::summarize(&bytes, Strictness::Lax)?;

println!(
    "name={:?} class={:?} level={:?} expansion={:?}",
    summary.name,
    summary.class,
    summary.level,
    summary.expansion_type
);

Edition detection

For unknown versions, Halbu can try to guess which edition the save layout matches most closely:

use halbu::format::detect_edition_hint;
use halbu::GameEdition;

let hint = detect_edition_hint(&bytes);

if hint == Some(GameEdition::RotW) {
    // likely RotW (v105-style layout)
}

Model overview

Halbu distinguishes between three related concepts:

  • FormatId - concrete file format (V99, V105, or unknown)
  • GameEdition - edition family (D2RLegacy, RotW)
  • ExpansionType - in-game expansion mode (Classic, Expansion, RotW)

Typical usage:

  • save.format() -> file format
  • save.game_edition() -> edition family
  • save.expansion_type() -> in-game expansion

Compatibility rules (examples)

  • Warlock requires RotW edition and expansion
  • RotW expansion cannot be encoded to non-RotW formats
  • Druid and Assassin cannot be encoded as Classic
  • Unknown class IDs cannot be safely converted

Notes

  • Level is stored in multiple sections; use save.set_level(...) to keep it consistent
  • Additional reverse-engineering notes are available in NOTES.md

Documentation

API docs: https://docs.rs/halbu
Changelog: CHANGELOG.md

References

These resources helped me understand the .d2s format. Many thanks to their authors.

About

.d2s parsing library for Diablo II: Resurrected

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages