15 lines
1.6 KiB
JavaScript
15 lines
1.6 KiB
JavaScript
// Research only: current assembly SHA c5e02e6e984f7e5577c78b995a8efeee2d06ee22e67d484ad5e859c8bf21e144.
|
|
// Wave formation consumer f0c9d50 calls this flat row getter at RVA 1e33bb30.
|
|
// Only that getter and the verified existing serializer run; no battle is created.
|
|
const ids=globalThis.CW_FORMATION_IDS;
|
|
if(!Array.isArray(ids)||!ids.length||ids.length>128||ids.some(x=>!Number.isInteger(x)||x<=0))throw Error('Bounded formation ID plan required');
|
|
const m=Process.getModuleByName('GameAssembly.dll');
|
|
const check=(rva,expected)=>{const b=Array.from(new Uint8Array(m.base.add(rva).readByteArray(expected.length)));if(b.some((x,i)=>x!==expected[i]))throw Error('Entry identity differs');};
|
|
check(0x1e33bb30,[0x56,0x48,0x83,0xec,0x60]);check(0x1d3efb60,[0x56,0x57,0x48,0x83,0xec,0x28]);
|
|
const read=new NativeFunction(m.base.add(0x1e33bb30),'pointer',['uint32','pointer']);
|
|
const serialize=new NativeFunction(m.base.add(0x1d3efb60),'pointer',['pointer','pointer']);
|
|
let index=0,done=false;
|
|
Interceptor.attach(m.base.add(0xdb5f860),{onLeave(){if(done)return;try{for(let n=0;n<4&&index<ids.length;n++){const id=ids[index++],row=read(id,ptr(0));if(row.isNull())throw Error('Missing monster row '+id);const v=serialize(row,ptr(0));if(v.isNull())throw Error('Missing serialization');const length=v.add(0x10).readS32();if(length<2||length>65536)throw Error('Row bound');send({kind:'ROW',id,json:v.add(0x14).readUtf16String(length)});}if(index===ids.length){done=true;send({kind:'END',count:index});}}catch(e){done=true;send({kind:'ERROR',error:String(e)});}}});
|
|
send({kind:'BEGIN',count:ids.length});
|
|
|