set_patchStore or overwrite one patch

fn set_patch(&self, patch: &Patch) -> Result<()>

Fire-and-forget

ParameterTypeDescription
patchPatchIts section, address, offset, and bytes.

Patches are keyed by (section, cfg, index, offset). Setting an existing key overwrites the patch and moves it to the end of the set, unless the patch already holds those bytes. Empty bytes removes it. The set belongs to the attached real device, so a patch stored with none attached is dropped.

The clone serves the set it was presented with, STRING patches included. A stored change reaches the game PC at the next presentation. The limits and wire layout are on the native PATCH command.

EXAMPLE
use medius::{Device, Patch, PatchSection};

let device = Device::find()?;

// Overwrite idVendor in the device descriptor (offset 8, little-endian), then re-present.
device.set_patch(&Patch::new(PatchSection::Device, 8, [0x34, 0x12]))?;
device.allow_imperfect_clones(true)?;
device.apply_patch()?;

apply_patchRe-present the clone with the stored set

fn apply_patch(&self) -> Result<()>

Fire-and-forget

Re-presents the clone with the stored patch set (native APPLY): one unplug/replug to the game PC. Gated on allow_imperfect_clones. With the opt-in off, it returns Error::ImperfectRequired.

EFFECT
Stored setBox action
Differs from the set the clone serves (pending)Re-presents the clone with it: a re-clone that releases the session. An emptied set re-presents the clone unpatched. A set that fails a check is served unpatched, with refused set.
The set the clone servesNothing.
Refused, and unchanged sinceNothing, though it reads pending: change the set, or clear it.
Any, with no real device attachedNothing.
EXAMPLE
device.allow_imperfect_clones(true)?;
device.apply_patch()?; // the clone replugs and re-presents patched

clear_patchErase the stored set

fn clear_patch(&self) -> Result<()>

Fire-and-forget

Erases every patch stored for this real device (VID:PID). With the real device unplugged, it erases the set of the last one attached since boot (native CLEAR).

EFFECT
CloneBox action
Serves patchesErases the set and re-presents the clone unpatched: one unplug/replug to the game PC, and a re-clone that releases the session.
Serves noneErases the set and leaves the clone as is.
EXAMPLE
device.clear_patch()?;

query_patchesStored set and apply state

fn query_patches(&self) -> Result<PatchSet>

Blocks

Returns a PatchSet: the four apply-state flags and a row per stored patch, without its bytes.

EXAMPLE
let set = device.query_patches()?;
println!("{} patches, applied={} pending={}", set.entries.len(), set.applied, set.pending);
if set.refused {
    eprintln!("the set failed a check, so the clone is unpatched; the box log names it");
}

query_patch_entryOne patch in full

fn query_patch_entry(&self, index: u8) -> Result<Patch>

Blocks

ParameterTypeDescription
indexu8The row in the query_patches summary.

Returns one Patch in full, in the shape set_patch takes.

EXAMPLE
let set = device.query_patches()?;
for i in 0..set.entries.len() as u8 {
    let patch = device.query_patch_entry(i)?; // replayable as a set
    let _ = patch;
}

On AsyncDeviceapply_patch and the queries await; set and clear fire

AsyncDevice makes apply_patch, query_patches and query_patch_entry futures (apply_patch awaits the opt-in check). set_patch and clear_patch stay synchronous.

EXAMPLE
use futures::executor::block_on;
use medius::{AsyncDevice, Patch, PatchSection};

let device = AsyncDevice::open("/dev/ttyACM0")?;
device.set_patch(&Patch::new(PatchSection::Device, 8, [0x34, 0x12]))?;  // sync
device.allow_imperfect_clones(true)?;
block_on(device.apply_patch())?;                                        // awaits the opt-in gate
let set = block_on(device.query_patches())?;                            // query awaits