// Research-only, source assembly SHA256: // c5e02e6e984f7e5577c78b995a8efeee2d06ee22e67d484ad5e859c8bf21e144. // PE exception table proves both entry RVAs. No dictionary/schema writes. // Query one named Excel table on a managed caller's thread, at most two rows // per handbook call. Its native getter can lazily initialize this Excel table; // the verified loader only reads table rows, and no level graph is invoked. const plan = globalThis.CW_CAPTURE_PLAN; if (!plan || !Number.isInteger(plan.maxLevel) || plan.maxLevel <= 0 || plan.maxLevel > 256) { throw new Error('Supply the captured default maximum player level'); } const module = Process.getModuleByName('GameAssembly.dll'); const check = (rva, expected) => { const actual = Array.from(new Uint8Array(module.base.add(rva).readByteArray(expected.length))); if (actual.some((v, i) => v !== expected[i])) throw new Error('Native entry bytes differ from captured assembly'); }; check(0xdb5f860, [0x55,0x41,0x56,0x56,0x57,0x53]); check(0x1e3a7880, [0x56,0x48,0x83,0xec,0x60,0x89,0xce]); // RuntimeMethodHandle.Value + 8 resolved this exact serializer entry; the // earlier metadata-token match was a different function and is not used. check(0x1d3efb60, [0x56,0x57,0x48,0x83,0xec,0x28]); let next = 1, done = false; const readLevel = new NativeFunction(module.base.add(0x1e3a7880), 'pointer', ['uint32', 'pointer']); const serialize = new NativeFunction(module.base.add(0x1d3efb60), 'pointer', ['pointer', 'pointer']); const hook = Interceptor.attach(module.base.add(0xdb5f860), { onLeave() { if (done) return; try { if (next === 1) send({kind:'TABLE_STATE', initiallyLoaded:module.base.add(0x9869370).readU8() === 1}); for (let n = 0; n < 2 && next <= plan.maxLevel; n++) { const level = next++; const row = readLevel(level, ptr(0)); if (row.isNull()) throw new Error('Native player level row is missing: ' + level); const record = { PlayerLevel: row.add(0x2c).readU32(), LevelUpExp: row.add(0x20).readU32(), Rarity1Weight: row.add(0x1c).readU32(), Rarity2Weight: row.add(0x28).readU32(), Rarity3Weight: row.add(0x18).readU32(), Rarity4Weight: row.add(0x30).readU32(), Rarity5Weight: row.add(0x24).readU32(), AvatarMaxNumber: row.add(0x34).readU32() }; if (record.PlayerLevel !== level) throw new Error('Row layout/identity mismatch at level ' + level); const encoded = serialize(row, ptr(0)); if (encoded.isNull()) throw new Error('Native serializer returned null'); const length = encoded.add(0x10).readS32(); if (length < 2 || length > 65536) throw new Error('Serialized level row exceeds capture bound'); const json = encoded.add(0x14).readUtf16String(length); const parsed = JSON.parse(json); for (const key of Object.keys(record)) { if (parsed[key] !== record[key]) throw new Error('Serialized row disagrees with scalar layout: '+key); } send({kind:'ROW', json, thread:Process.getCurrentThreadId()}); } if (next > plan.maxLevel) { done = true; send({kind:'END', count:plan.maxLevel}); } } catch (e) { done = true; send({kind:'ERROR', error:String(e)}); } } }); send({kind:'BEGIN', count:plan.maxLevel, scope:'native player-level full rows serialized on managed caller thread'});