Initial public release of JustOneCacophony

This commit is contained in:
2026-09-01 16:31:38 +08:00
commit aa3a519f79
38 changed files with 9073 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
"""解包 EVO MD-set evolution 载荷,返回各 payload ID 的字节数据和位偏移。"""
_MARK = "1001001000000"
# 各子载荷字段: (id, 头部前缀, 同步标记, 后缀常量, 尺寸域位数, 是否有转义)
# 头部前缀 = 5 位 id 的 MSB 二进制(id11 字段前另有 5 位容器前导 00000)
# 尺寸域单位 = nibble(4 位)。id14 有转义:9 位值=0 → 再读 9 位 = 字节数。
_LAYOUT = [
(11, "0000001011", "010000000000000", 8, False),
(14, "01110", "01000000000000", 9, True),
(2, "00010", "000100", 7, False),
(1, "00001", "1110000000000000000000000000", 4, False),
(30, "11110", "1110000000000000000000000000", 4, False),
]
def _msb_bits(data: bytes):
return [(x >> (7 - i)) & 1 for x in data for i in range(8)]
def _val(bits, off, n):
v = 0
for b in bits[off:off + n]:
v = (v << 1) | b
return v
class _LooseSkip(Exception):
def __init__(self, ident):
self.ident = ident
def unpack_evolution(payload: bytes, loose=False):
"""解包 evolution 载荷 → (subs, offsets)。subs 键为 id 整数。
loose=True 时对每个 id 的 (前缀+标记+后缀) 全模式做位流重同步扫描
(不同编码流的子载荷次序/内部常量可有合法差异,如 kanata 的 id11)。"""
bits = _msb_bits(payload)
pos = 0
subs = {}
offsets = {}
for ident, pref, suff, sbits, escape in _LAYOUT:
pat = pref + _MARK + suff
if loose:
hit = -1
for i in range(pos, len(bits) - len(pat)):
if ''.join(map(str, bits[i:i + len(pat)])) == pat:
hit = i
break
if hit < 0:
continue
pos = hit + len(pat)
else:
for name, const, expect in (("前缀", bits[pos:pos + len(pref)], pref),
("标记", bits[pos + len(pref):pos + len(pref) + len(_MARK)], _MARK),
("后缀", bits[pos + len(pref) + len(_MARK):
pos + len(pref) + len(_MARK) + len(suff)], suff)):
got = ''.join(map(str, const))
if got != expect:
raise ValueError(f"id={ident}: {name}常量不匹配 @bit{pos} got={got} want={expect}")
pos += len(pref) + len(_MARK) + len(suff)
n_nib = _val(bits, pos, sbits)
pos += sbits
if escape and n_nib == 1:
n_nib = 512 + _val(bits, pos, sbits)
pos += sbits
n_bits = n_nib * 4
body = bits[pos:pos + n_bits]
pos += n_bits
b = bytearray(len(body) // 8)
for i in range(0, len(body) // 8 * 8, 8):
v = 0
for x in body[i:i + 8]:
v = (v << 1) | x
b[i // 8] = v
subs[ident] = bytes(b)
offsets[ident] = pos
return subs, offsets