Skip to content

oscargala/plasma-prp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

plasma-prp

Read, write, inspect, and manipulate Plasma engine PRP files used by Myst Online: Uru Live.

A standalone Rust library (with Python bindings and CLI) for working with the binary .prp, .age, .sdl, and .fni file formats from the H-uru/Plasma engine. Zero engine dependencies — no GPU, audio, or physics required.

Features

  • Parse all object types in PRP files (scenes, materials, textures, physics, audio, animations, responders, Python script mods, and more)
  • Write PRP files back with byte-identical round-trip fidelity
  • Inspect PRP/AGE/SDL files from the command line
  • Diff two PRP files to see what changed
  • Export textures as PNG (DXT1/DXT5 decompression included)
  • Validate PRP files for common issues (missing refs, broken pointers)
  • Python bindings via PyO3 — pip install plasma-prp

Install

Rust

cargo add plasma-prp

Python

pip install plasma-prp

CLI

cargo install plasma-prp --features cli

Rust Usage

Load a PRP and list all objects

use plasma_prp::{PrpPage, ClassIndex};

let page = PrpPage::from_file("Cleft_District_Cleft.prp".as_ref())?;
println!("{} objects in {}", page.keys.len(), page.header.age_name);

for key in &page.keys {
    println!("  [0x{:04X}] {} ({})",
        key.class_type,
        key.object_name,
        ClassIndex::class_name(key.class_type));
}

Extract textures as PNG

use plasma_prp::{PrpPage, ObjectKey};
use plasma_prp::resource::prp::{class_types, MipmapData};

let page = PrpPage::from_file("Cleft_District_Textures.prp".as_ref())?;

for key in page.keys_of_type(class_types::PL_MIPMAP) {
    if let Some(data) = page.object_data(key) {
        let mip = MipmapData::parse(data)?;
        println!("Texture: {} ({}x{}, {} levels)",
            mip.name, mip.width, mip.height, mip.num_levels);
    }
}

Round-trip a PRP file

use plasma_prp::PrpPage;

let page = PrpPage::from_file("input.prp".as_ref())?;
page.save("output.prp".as_ref())?;

// output.prp is byte-identical to input.prp

Diff two PRP files

use plasma_prp::PrpPage;

let a = PrpPage::from_file("before.prp".as_ref())?;
let b = PrpPage::from_file("after.prp".as_ref())?;

for key in &b.keys {
    if !a.keys.iter().any(|k| k.object_name == key.object_name
        && k.class_type == key.class_type)
    {
        println!("+ Added: {}", key.object_name);
    }
}

Read an Age file and its pages

use plasma_prp::AgeDescription;

let age = AgeDescription::from_file("Cleft.age".as_ref())?;
println!("Age: {} (prefix {})", age.age_name, age.sequence_prefix);

for page in age.auto_load_pages() {
    println!("  Auto-load: {} -> {}", page.name, age.prp_filename(page));
}

Access materials and layers

use plasma_prp::resource::prp::{parse_layer_state, class_types};
use plasma_prp::PrpPage;

let page = PrpPage::from_file("Cleft_District_Cleft.prp".as_ref())?;

for key in page.keys_of_type(class_types::PL_LAYER) {
    if let Some(data) = page.object_data(key) {
        let layer = parse_layer_state(data)?;
        println!("Layer '{}': texture={:?}, opacity={:.2}",
            layer.name, layer.texture_name, layer.opacity);
    }
}

Parse SDL descriptors

use plasma_prp::sdl::SdlManager;

let mut mgr = SdlManager::new();
mgr.load_directory("SDL/".as_ref())?;

if let Some(desc) = mgr.find("Cleft", 0) {
    println!("Cleft SDL v{}: {} variables", desc.version, desc.variables.len());
    for var in &desc.variables {
        println!("  {:?} {}[{}]", var.var_type, var.name, var.count);
    }
}

Python Usage

import plasma_prp

# Load a PRP file
prp = plasma_prp.PrpFile.load("Cleft_District_Cleft.prp")
print(f"{len(prp)} objects in {prp.age_name}")

# List objects by type
for class_name, count in sorted(prp.count_by_type().items()):
    print(f"  {count:4d} {class_name}")

# Access specific object types
for obj in prp.objects_by_name("plSceneObject"):
    scene = obj.as_scene_object()
    print(f"SceneObject: {scene.name}")

# Parse materials
for obj in prp.objects_by_name("plLayer"):
    layer = obj.as_layer()
    print(f"Layer '{layer.name}': texture={layer.texture_name}")

# Parse an age file
age = plasma_prp.AgeFile.load("Cleft.age")
for page in age.pages:
    print(f"  {page.name} (auto_load={page.auto_load})")

# Load SDL descriptors
sdl = plasma_prp.SdlFile()
sdl.load_directory("SDL/")
desc = sdl.find("Cleft", 0)
for var in desc.variables:
    print(f"  {var.var_type} {var.name}[{var.count}]")

# Round-trip
prp.save("output.prp")  # byte-identical to input

CLI Usage

# Inspect a PRP file — object inventory grouped by class
plasma-prp inspect Cleft_District_Cleft.prp

# Inspect an age file — page list with auto-load flags
plasma-prp inspect Cleft.age

# Inspect SDL descriptors
plasma-prp inspect avatar.sdl

# Validate a PRP file — check for missing refs, broken pointers
plasma-prp validate Cleft_District_Cleft.prp

# Diff two PRP files — added/removed/modified objects
plasma-prp diff before.prp after.prp

# Export all textures as PNG
plasma-prp export-textures Cleft_District_Textures.prp ./textures/

Supported Object Types

The parser handles all major Plasma object types, including:

Category Types
Scene plSceneObject, plSceneNode, plCoordinateInterface, plDrawInterface
Materials hsGMaterial, plLayer, plLayerAnimation, plLayerSDLAnimation
Textures plMipmap, plCubicEnvironmap, plDynamicTextMap
Animation plATCAnim, plAGMasterMod, plAGModifier, keyframe controllers
Physics plPXPhysical (trimesh, convex hull, box, sphere)
Audio plWin32StaticSound, plWin32StreamingSound, plSoundBuffer
Logic plResponderModifier, plLogicModifier, plOneShotMod
Scripting plPythonFileMod (parameters, receivers)
Volumes plObjectInVolumeDetector, plSoftVolume (simple, union, intersect, invert)
Visibility plVisRegion, plRelevanceRegion
Camera plCameraBrain1, plCameraBrain1_Avatar, plCameraBrain1_Fixed
Lighting plDirectionalLightInfo, plOmniLightInfo, plSpotLightInfo
GUI pfGUIDialogMod, pfGUIButtonMod, pfGUITextBoxMod
Effects plParticleSystem, plWaveSet7, plFogEnvironment
Decals plDynaFootMgr, plDynaRippleMgr, plDynaWakeMgr
Reverb plEAXListenerMod
Vegetation plClusterGroup

Related Projects

  • H-uru/Plasma — The open-source Plasma engine (C++)
  • Korman — Blender plugin for creating Plasma ages
  • libhsplasma — C++ library for Plasma file formats

License

This project is licensed under the GNU General Public License v3.0, matching the license used by Korman and the H-uru Plasma community tools.

About

Read, write, inspect, and manipulate Plasma engine PRP files used by Myst Online: Uru Live

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages