import dnfile, struct
pe = dnfile.dnPE("tuning.exe")
net = pe.net
data = bytes(pe.__data__)
def rva2off(rva):
    for s in pe.sections:
        vs=max(s.Misc_VirtualSize,s.SizeOfRawData)
        if s.VirtualAddress<=rva<s.VirtualAddress+vs:
            return s.PointerToRawData+(rva-s.VirtualAddress)
def sstr(x):
    try: return str(x)
    except: return "?"
# token resolvers
mdef=net.mdtables.MethodDef.rows
mref=net.mdtables.MemberRef.rows if net.mdtables.MemberRef else []
fld=net.mdtables.Field.rows if net.mdtables.Field else []
tref=net.mdtables.TypeRef.rows if net.mdtables.TypeRef else []
def us(tok):
    # #US token 0x70xxxxxx
    idx=tok&0xffffff
    try:
        return '"'+sstr(net.user_strings.get(idx).value)+'"'
    except Exception as e:
        return f"US#{idx:x}"
def resolve(tok):
    t=tok>>24; i=(tok&0xffffff)
    if t==0x0A and i-1<len(mref): return "ref:"+sstr(mref[i-1].Name)
    if t==0x06 and i-1<len(mdef): return "mdef:"+sstr(mdef[i-1].Name)
    if t==0x04 and i-1<len(fld): return "fld:"+sstr(fld[i-1].Name)
    if t==0x0A: return f"memberref#{i}"
    return f"tok0x{tok:08x}"

# opcode table (subset)
OPS={0x00:"nop",0x01:"break",0x02:"ldarg.0",0x03:"ldarg.1",0x04:"ldarg.2",0x05:"ldarg.3",
0x06:"ldloc.0",0x07:"ldloc.1",0x08:"ldloc.2",0x09:"ldloc.3",0x0a:"stloc.0",0x0b:"stloc.1",
0x0c:"stloc.2",0x0d:"stloc.3",0x0e:("ldarg.s",1),0x0f:("ldarga.s",1),0x10:("starg.s",1),
0x11:("ldloc.s",1),0x12:("ldloca.s",1),0x13:("stloc.s",1),0x14:"ldnull",0x15:"ldc.i4.m1",
0x16:"ldc.i4.0",0x17:"ldc.i4.1",0x18:"ldc.i4.2",0x19:"ldc.i4.3",0x1a:"ldc.i4.4",0x1b:"ldc.i4.5",
0x1c:"ldc.i4.6",0x1d:"ldc.i4.7",0x1e:"ldc.i4.8",0x1f:("ldc.i4.s",1),0x20:("ldc.i4",4),
0x21:("ldc.i8",8),0x22:("ldc.r4",4),0x23:("ldc.r8",8),0x25:"dup",0x26:"pop",
0x28:("call",4,"tok"),0x29:("calli",4),0x2a:"ret",
0x2b:("br.s",1,"br"),0x2c:("brfalse.s",1,"br"),0x2d:("brtrue.s",1,"br"),0x2e:("beq.s",1,"br"),
0x2f:("bge.s",1,"br"),0x30:("bgt.s",1,"br"),0x31:("ble.s",1,"br"),0x32:("blt.s",1,"br"),
0x33:("bne.un.s",1,"br"),0x38:("br",4,"br"),0x39:("brfalse",4,"br"),0x3a:("brtrue",4,"br"),
0x3b:("beq",4,"br"),0x58:"add",0x59:"sub",0x5a:"mul",0x5b:"div",0x5f:"and",0x60:"or",
0x61:"xor",0x62:"shl",0x63:"shr",0x65:"neg",0x66:"not",
0x6f:("callvirt",4,"tok"),0x72:("ldstr",4,"us"),0x73:("newobj",4,"tok"),
0x74:("castclass",4,"tok"),0x75:("isinst",4,"tok"),
0x7b:("ldfld",4,"tok"),0x7d:("stfld",4,"tok"),0x7e:("ldsfld",4,"tok"),0x80:("stsfld",4,"tok"),
0x8c:("box",4,"tok"),0x8d:("newarr",4,"tok"),0x8e:"ldlen",
0x91:"ldelem.i1",0x92:"ldelem.u1",0x93:"ldelem.i2",0x94:"ldelem.u2",0x95:"ldelem.i4",
0x9c:"stelem.i1",0x9d:"stelem.i2",0x9e:"stelem.i4",0xa2:"stelem.ref",0x8f:("ldelema",4,"tok"),
0xa3:("ldelem",4,"tok"),0xa4:("stelem",4,"tok"),
0x6a:"conv.i8",0x69:"conv.i4",0x67:"conv.i1",0x68:"conv.i2",0xd1:"conv.u2",0xd2:"conv.u1",
0x20:("ldc.i4",4)}

def disasm(rva, name):
    off=rva2off(rva)
    b0=data[off]
    if (b0&3)==2:
        codesize=b0>>2; ilstart=off+1
    else:
        # fat header 12 bytes
        codesize=struct.unpack_from("<I",data,off+4)[0]; ilstart=off+12
    il=data[ilstart:ilstart+codesize]
    print(f"\n===== {name} (RVA 0x{rva:x}, {codesize} bytes IL) =====")
    p=0
    while p<len(il):
        op=il[p]; p0=p; p+=1
        if op==0xfe:
            op2=il[p]; p+=1
            nm={0x01:"ceq",0x02:"cgt",0x04:"clt",0x09:("ldarg",2),0x0b:("ldloc",2),0x0c:("ldloca",2),0x0d:("stloc",2),0x16:"constrained",0x1e:"readonly"}.get(op2,f"fe{op2:02x}")
            if isinstance(nm,tuple):
                sz=nm[1]; val=int.from_bytes(il[p:p+sz],'little'); p+=sz
                print(f"  {p0:04x}: {nm[0]} {val}")
            else:
                print(f"  {p0:04x}: {nm}")
            continue
        info=OPS.get(op)
        if info is None:
            print(f"  {p0:04x}: .byte 0x{op:02x}"); continue
        if isinstance(info,str):
            print(f"  {p0:04x}: {info}"); continue
        nm=info[0]; sz=info[1]; kind=info[2] if len(info)>2 else None
        raw=il[p:p+sz]; p+=sz
        if kind=="tok":
            tok=int.from_bytes(raw,'little'); print(f"  {p0:04x}: {nm} {resolve(tok)}")
        elif kind=="us":
            tok=int.from_bytes(raw,'little'); print(f"  {p0:04x}: {nm} {us(tok)}")
        elif kind=="br":
            disp=int.from_bytes(raw,'little',signed=True); print(f"  {p0:04x}: {nm} -> {p+disp:04x}")
        else:
            val=int.from_bytes(raw,'little',signed=(nm in('ldc.i4','ldc.i4.s'))); print(f"  {p0:04x}: {nm} {val} (0x{val&0xffffffff:x})")

import sys
for nm,rva in [("btnRead_U_Freq_Click",0x5f330),("btnCal_U_Freq_Click",0x5f53c),
               ("num_U_DigFreq_ValueChanged",0x5f160)]:
    disasm(rva,nm)
