local function rd(self, addr) self.fin:seek(addr * 4) return self.fin:readU32() end local function rdn(self) local r = self:rd(self.PC) self.PC = self.PC + 1 return r end local opcodes_names = { -- 0x.0 0x.1 0x.2 0x.3 0x.4 0x.5 0x.6 0x.7 0x.8 0x.9 0x.a 0x.b 0x.c 0x.d 0x.e 0x.f "SETV", "SETV", nil, nil, nil, nil, nil, nil, "MULG0","ADDG0","PSH", nil, nil, "PSH1?",nil, -- 0x0. nil, nil, "PSH2?","PSHI", "CALL", "JMP", "JMPZ", "RET", "SETD", "PSH3?",nil, nil, nil, nil, nil, nil, -- 0x1. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x2. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x3. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x4. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x5. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x6. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x7. "STTRG",nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "SSTOP",nil, nil, nil, -- 0x8. nil, nil, "TBOX", "TBOX2",nil, nil, nil, nil, "TBOX3",nil, nil, nil, nil, nil, "SETRM","CHGRM",-- 0x9. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xa. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xb. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xc. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xd. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xe. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xf. } local opcodes_imms = { -- 0 1 2 3 4 5 6 7 8 9 a b c d e f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, -- 1 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, -- 2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -- 3 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 0, 2, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7 3, 0, 1, 2, 0, 4, 1, 1, 1, 0, 2, 0, 1, 0, 0, 2, -- 8 0, 0, 3, 3, 3, 0, 0, 0, 3, 0, 0, 0, 0, 1, 1, 2, -- 9 2, 2, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -- a 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- b 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -- c 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -- d 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- e 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f } -- 0 = nothing -- 1 = low8 -- 2 = low16 -- 3 = low23 -- 4 = high8 -- 5 = var_idx -- 6 = var_idx2 -- 7 = low8 + high8 local opcodes_self_vals = { -- 0 1 2 3 4 5 6 7 8 9 a b c d e f 5, 5, 0, 0, 0, 0, 0, 0, 3, 3, 5, 0, 0, 2, 0, -- 0 0, 0, 3, 0, 3, 3, 3, 0, 6, 0, 0, 0, 0, 0, 0, 0, -- 1 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 3 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7 2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 2, 1, 0, -- 8 0, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 7, 2, 0, -- 9 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, -- a 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, -- b 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- c 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- d 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f } local opcodes_nparams = { -- 0 1 2 3 4 5 6 7 8 9 a b c d e f 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 1, 0, -- 0 0, 0, 1, 1, 1, 1, 2, 0, 2, 1, 1, 0, 0, 0, 0, 0, -- 1 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, -- 2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -- 3 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 0, 0, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, -- 7 4, 1, 2, 4, 0, 5, 2, 2, 2, 0, 3, 0, 1, 1, 1, 5, -- 8 0, 0, 7, 7, 6, 0, 0, 0, 7, 0, 0, 0, 0, 3, 2, 4, -- 9 6, 2, 2, 6, 0, 0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 0, -- a 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, -- b 2, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -- c 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 1, 0, 0, -- d 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- e 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f } local opcodes_known = { -- 0 1 2 3 4 5 6 7 8 9 a b c d e f true, true, false, false, false, false, false, false, true, true, true, false, false, true, false, -- 0 false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, -- 1 false, true, true, true, true, true, true, true, true, true, true, false, false, false, true, false, -- 2 false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, -- 3 false, true, true, true, true, true, false, false, false, true, false, false, false, false, false, false, -- 4 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 5 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 6 true, true, true, true, true, true, true, false, true, false, false, true, true, false, true, false, -- 7 true, true, true, true, false, true, true, true, true, true, true, false, true, true, true, true, -- 8 false, true, true, true, true, false, false, false, true, false, false, false, false, true, true, true, -- 9 true, true, true, true, false, false, false, false, true, true, false, true, false, false, false, false, -- a true, false, true, false, false, false, false, false, true, false, false, true, false, false, true, false, -- b true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, -- c false, false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, -- d true, false, false, false, false, false, true, false, false, false, false, true, false, false, false, false, -- e false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- f } local opcodes_fromstack = { -- 0 1 2 3 4 5 6 7 8 9 a b c d e f false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 0 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 1 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 2 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 3 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 4 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 5 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 6 false, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, -- 7 true, true, true, true, false, true, true, true, true, false, true, false, true, false, true, true, -- 8 false, false, true, true, true, false, false, false, true, false, false, false, false, true, true, true, -- 9 true, true, true, true, false, false, false, false, true, true, false, true, false, false, false, false, -- a false, false, true, false, false, false, false, false, false, false, false, true, false, false, false, false, -- b true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, -- c false, false, false, false, false, false, false, false, false, true, true, false, false, true, false, false, -- d false, false, false, false, false, false, true, false, false, false, false, true, false, false, false, false, -- e false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- f } local function disasm_write(self, ...) if self.out then self.out:write(...) end end local function disasm_opcode(self) self.oPC = self.PC self.opcode = self:rdn() self.code = shr(self.opcode, 24) self.imm8 = andB(self.opcode, 0xff) self.imm16 = andB(self.opcode, 0xffff) self.imm23 = andB(self.opcode, 0x7fffff) self.high8 = andB(shr(self.opcode, 8), 0xff) self.idx2 = shr(shl(self.opcode, 9), 12) self.flags = {} self.flags.is_local = andB(self.opcode, 0x800000) ~= 0 self.flags.from_stack = andB(self.opcode, 0x100000) ~= 0 self:write(string.format("%08X %08X ", self.oPC, self.opcode)) if self.code == 0 then self:write("OPCODE00?!") return end local name = opcodes_names[self.code] if name then self:write(string.format("%-8s", name)) elseif opcodes_known[self.code] then self:write(string.format("OP_%02X ", self.code)) else self:write(string.format("UNK%02X ", self.code)) end if self.flags.from_stack and opcodes_fromstack[self.code] then for i = 1, opcodes_nparams[self.code] do self:write("POP()") if i ~= opcodes_nparams[self.code] then self:write(", ") end end else local nargs = opcodes_nparams[self.code] local sv = opcodes_self_vals[self.code] if false then -- 0 = nothing -- 1 = low8 -- 2 = low16 -- 3 = low23 -- 4 = high8 -- 5 = var_idx -- 6 = var_idx2 -- 7 = low8 + high8 elseif sv == 1 then self:write(string.format("%02X", self.imm8)) nargs = nargs - 1 elseif sv == 2 then self:write(string.format("%04X", self.imm16)) nargs = nargs - 1 elseif sv == 3 then self:write(string.format("%08X", self.imm23)) nargs = nargs - 1 elseif sv == 4 then self:write(string.format("%02X", self.high8)) nargs = nargs - 1 elseif sv == 5 then self:write(string.format("%s[%04X]", self.flags.is_local and "locl" or "glbl", self.imm16)) nargs = nargs - 1 elseif sv == 6 then self:write(string.format("%s[%04X]", self.flags.is_local and "locl" or "glbl", self.idx2)) nargs = nargs - 1 elseif sv == 7 then self:write(string.format("%02X, %02X", self.imm8, self.high8)) nargs = nargs - 2 end if sv ~= 0 and nargs ~= 0 then self:write(", ") end for i = 1, opcodes_imms[self.code] do self:write(string.format("%08X", self:rdn())) if i ~= opcodes_imms[self.code] then self:write(", ") end nargs = nargs - 1 end if not opcodes_fromstack[self.code] then for i = 1, nargs do self:write("POP()") if i ~= nargs then self:write(", ") end end end end if self.hooks[self.code] then self.hooks[self.code](self.oPC) end end local function disasm(self) while self.PC ~= self.EPC do self:disasm_opcode() self:write("\n") for padPC = self.oPC + 1, self.PC - 1 do self:write(string.format(" %08X\n", self:rd(padPC))) end end end function logic_disasm(logic, o, hooks) local dobj = { rd = rd, rdn = rdn, disasm_opcode = disasm_opcode, disasm = disasm, PC = 0, fin = logic, out = o, EPC = logic:getsize() / 4, hooks = hooks, write = disasm_write } dobj:disasm() end