1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use BinRead;
use Cursor;
use SqpackFile;
/// SQPK `D` command body: overwrite a contiguous block range in a `.dat` file
/// with empty-block markers, logically freeing that space.
///
/// `DeleteData` is the inverse of [`SqpkAddData`](super::SqpkAddData): where
/// `A` writes live data into a block range, `D` marks that same range as free.
/// After a `D` command the game engine treats the blocks as available for
/// reuse.
///
/// On disk the operation writes a `SqPack` empty-block header at `block_offset`
/// and zeroes the full `block_count * 128` byte range. This is identical to
/// what [`SqpkExpandData`](super::SqpkExpandData) writes; the semantic
/// difference is that `D` clears existing live content while `E` allocates
/// previously non-existent space.
///
/// The apply implementation (`src/apply/sqpk.rs`) handles both `D` and `E`
/// with the same `write_empty_block` helper.
///
/// ## Wire format (all big-endian)
///
/// ```text
/// ┌────────────────────────────────────────────────────────────────────┐
/// │ <padding> : [u8; 3] (reserved, always zero) │ bytes 0–2
/// │ main_id : u16 BE │ bytes 3–4
/// │ sub_id : u16 BE │ bytes 5–6
/// │ file_id : u32 BE │ bytes 7–10
/// │ block_offset_raw : u32 BE multiply by 128 to get byte offset │ bytes 11–14
/// │ block_count : u32 BE number of 128-byte blocks to clear │ bytes 15–18
/// │ <reserved> : u32 (always zero) │ bytes 19–22
/// └────────────────────────────────────────────────────────────────────┘
/// ```
///
/// `block_offset_raw` is in **128-byte `SqPack` block units** and is multiplied
/// by 128 (`<< 7`) during parsing; `block_count` is a direct block count
/// stored as-is.
///
/// The total byte range cleared by this command is `block_count * 128` bytes
/// starting at `block_offset`.
///
/// ## Reference
///
/// See `SqpkDeleteData.cs` in the `XIVLauncher` reference implementation.
///
/// # Errors
///
/// Parsing returns [`crate::ZiPatchError::BinrwError`] if the body is too
/// short to contain all required fields.
pub