unfortunately he isn't around anymore.. :/HI khong would you happen to have teh tactics ogre reborn ending with ABC build ID?
unfortunately he isn't around anymore.. :/HI khong would you happen to have teh tactics ogre reborn ending with ABC build ID?
hello i am just curiouse if you have had chance to look at the dof no blur cheat for EOW its ok if you havent yet i know your busy and i really appreciate your work so thank you again for everything you have doneunfortunately he isn't around anymore.. :/
i did and its the instruction didnt change internally. i have no issue with it showing up 100% of the time. idk what to say :/ sorry.hello i am just curiouse if you have had chance to look at the dof no blur cheat for EOW its ok if you havent yet i know your busy and i really appreciate your work so thank you again for everything you have done
Dragon ball Z : kakarot V1.60 . Title id : 010051C0134F8000 . Build id : BC99D4D0A9474360
So I made oneI am not aware of any that would support that
ok no worries thank you for looking you are awesomei did and its the instruction didnt change internally. i have no issue with it showing up 100% of the time. idk what to say :/ sorry.
so full credit to Tom on his script https://github.com/tomvita/Breeze-Beta/blob/master/disassemble_cheats.pycan it be used with emulator? i want to make the code but since i have no console only emu
import sys
from enum import Enum
try:
from capstone import Cs, CS_ARCH_ARM64, CS_MODE_ARM
CAPSTONE_AVAILABLE = True
except ImportError:
CAPSTONE_AVAILABLE = False
# Based on source/opcode.hpp
class CheatVmOpcodeType(Enum):
StoreStatic = 0
BeginConditionalBlock = 1
EndConditionalBlock = 2
ControlLoop = 3
LoadRegisterStatic = 4
LoadRegisterMemory = 5
StoreStaticToAddress = 6
PerformArithmeticStatic = 7
BeginKeypressConditionalBlock = 8
PerformArithmeticRegister = 9
StoreRegisterToAddress = 10
Reserved11 = 11
ExtendedWidth = 12
BeginRegisterConditionalBlock = 0xC0
SaveRestoreRegister = 0xC1
SaveRestoreRegisterMask = 0xC2
ReadWriteStaticRegister = 0xC3
BeginExtendedKeypressConditionalBlock = 0xC4
DoubleExtendedWidth = 0xF0
PauseProcess = 0xFF0
ResumeProcess = 0xFF1
DebugLog = 0xFFF
class MemoryAccessType(Enum):
MainNso = 0
Heap = 1
Alias = 2
Aslr = 3
Blank = 4
class ConditionalComparisonType(Enum):
GT = 1
GE = 2
LT = 3
LE = 4
EQ = 5
NE = 6
class RegisterArithmeticType(Enum):
Addition = 0
Subtraction = 1
Multiplication = 2
LeftShift = 3
RightShift = 4
LogicalAnd = 5
LogicalOr = 6
LogicalNot = 7
LogicalXor = 8
None_ = 9
FloatAddition = 10
FloatMultiplication = 11
DoubleAddition = 12
DoubleMultiplication = 13
class StoreRegisterOffsetType(Enum):
None_ = 0
Reg = 1
Imm = 2
MemReg = 3
MemImm = 4
MemImmReg = 5
class CompareRegisterValueType(Enum):
MemoryRelAddr = 0
MemoryOfsReg = 1
RegisterRelAddr = 2
RegisterOfsReg = 3
StaticValue = 4
OtherRegister = 5
OffsetValue = 6
class SaveRestoreRegisterOpType(Enum):
Restore = 0
Save = 1
ClearSaved = 2
ClearRegs = 3
class DebugLogValueType(Enum):
MemoryRelAddr = 0
MemoryOfsReg = 1
RegisterRelAddr = 2
RegisterOfsReg = 3
RegisterValue = 4
CONDITION_STR = {
ConditionalComparisonType.GT: ">",
ConditionalComparisonType.GE: ">=",
ConditionalComparisonType.LT: "<",
ConditionalComparisonType.LE: "<=",
ConditionalComparisonType.EQ: "==",
ConditionalComparisonType.NE: "!=",
}
MATH_STR = {
RegisterArithmeticType.Addition: "+",
RegisterArithmeticType.Subtraction: "-",
RegisterArithmeticType.Multiplication: "*",
RegisterArithmeticType.LeftShift: "<<",
RegisterArithmeticType.RightShift: ">>",
RegisterArithmeticType.LogicalAnd: "&",
RegisterArithmeticType.LogicalOr: "|",
RegisterArithmeticType.LogicalNot: "!",
RegisterArithmeticType.LogicalXor: "^",
RegisterArithmeticType.None_: "",
RegisterArithmeticType.FloatAddition: "+f",
RegisterArithmeticType.FloatMultiplication: "*f",
RegisterArithmeticType.DoubleAddition: "+d",
RegisterArithmeticType.DoubleMultiplication: "*d",
}
OPERAND_STR = {
SaveRestoreRegisterOpType.Restore: "Restore",
SaveRestoreRegisterOpType.Save: "Save",
SaveRestoreRegisterOpType.ClearSaved: "ClearSaved",
SaveRestoreRegisterOpType.ClearRegs: "ClearRegs",
}
class VmInt:
def __init__(self, value=0):
self.value = value
class CheatVmOpcode:
def __init__(self):
self.opcode = None
self.size = 0
self.str = ""
def get_next_dword(opcodes, instruction_ptr):
if instruction_ptr >= len(opcodes):
return None, instruction_ptr + 1
return opcodes[instruction_ptr], instruction_ptr + 1
def get_next_vm_int(opcodes, instruction_ptr, bit_width):
val = VmInt()
first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if first_dword is None:
return None, instruction_ptr
if bit_width == 1:
val.value = first_dword & 0xFF
elif bit_width == 2:
val.value = first_dword & 0xFFFF
elif bit_width == 4:
val.value = first_dword
elif bit_width == 8:
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if second_dword is None:
return None, instruction_ptr
val.value = (first_dword << 32) | second_dword
else:
# Invalid bit_width, but I'll assign the dword to avoid crashing.
val.value = first_dword
return val, instruction_ptr
def mem_type_str(mem_type):
if mem_type == MemoryAccessType.MainNso: return "Main"
if mem_type == MemoryAccessType.Heap: return "Heap"
if mem_type == MemoryAccessType.Alias: return "Alias"
if mem_type == MemoryAccessType.Aslr: return "Aslr"
return ""
def arm64_disassemble(value, bit_width, address):
if not CAPSTONE_AVAILABLE:
return ""
md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
code = value.to_bytes(bit_width, byteorder='little')
disassembled = []
try:
for i in md.disasm(code, address):
disassembled.append(f"{i.mnemonic} {i.op_str}")
return "; ".join(disassembled).strip()
except Exception:
return "" # Return empty string if Capstone fails
def decode_next_opcode(opcodes, index):
instruction_ptr = index
first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if first_dword is None:
return None
out = CheatVmOpcode()
opcode_val = (first_dword >> 28) & 0xF
if opcode_val >= CheatVmOpcodeType.ExtendedWidth.value:
opcode_val = (opcode_val << 4) | ((first_dword >> 24) & 0xF)
if opcode_val >= CheatVmOpcodeType.DoubleExtendedWidth.value:
opcode_val = (opcode_val << 4) | ((first_dword >> 20) & 0xF)
try:
out.opcode = CheatVmOpcodeType(opcode_val)
except ValueError:
out.str = f"Unknown opcode: {hex(opcode_val)}"
out.size = 1
return out
if out.opcode == CheatVmOpcodeType.StoreStatic:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
offset_register = (first_dword >> 16) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
rel_address = ((first_dword & 0xFF) << 32) | second_dword
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
out.str = f"[{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] = 0x{value.value:X}"
value_for_disasm = value.value
if bit_width == 8:
# The 64-bit value is read as (high_dword << 32 | low_dword).
# For little-endian disassembly, the byte stream needs to be
# ordered by the dwords as they appear in the file (high then low).
# value.to_bytes(..., 'little') would produce bytes(low) then bytes(high).
# To fix this, swap the dwords before converting to bytes.
high_dw = value.value >> 32
low_dw = value.value & 0xFFFFFFFF
value_for_disasm = (low_dw << 32) | high_dw
if CAPSTONE_AVAILABLE and (bit_width == 4 or bit_width == 8):
asm = arm64_disassemble(value_for_disasm, bit_width, rel_address)
if asm:
out.str += f" {asm}"
else:
out.str += " (Disassembly skipped - Capstone not available or invalid bit_width)"
elif out.opcode == CheatVmOpcodeType.BeginConditionalBlock:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF)
include_ofs_reg = ((first_dword >> 12) & 0xF) != 0
ofs_reg_index = (first_dword >> 8) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
rel_address = ((first_dword & 0xFF) << 32) | second_dword
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
ofs_reg_str = f"R{ofs_reg_index}+" if include_ofs_reg else ""
out.str = f"If [{mem_type_str(mem_type)}+{ofs_reg_str}0x{rel_address:010X}] {CONDITION_STR.get(cond_type, '?')} 0x{value.value:X}"
elif out.opcode == CheatVmOpcodeType.EndConditionalBlock:
end_type = (first_dword >> 24) & 0xF
out.str = "Else" if end_type == 1 else "Endif"
elif out.opcode == CheatVmOpcodeType.ControlLoop:
start_loop = ((first_dword >> 24) & 0xF) == 0
reg_index = (first_dword >> 16) & 0xF
if start_loop:
num_iters, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
out.str = f"Loop Start R{reg_index} = {num_iters}"
else:
out.str = "Loop stop"
elif out.opcode == CheatVmOpcodeType.LoadRegisterStatic:
reg_index = (first_dword >> 16) & 0xF
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit value
out.str = f"R{reg_index} = 0x{value.value:016X}"
elif out.opcode == CheatVmOpcodeType.LoadRegisterMemory:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
reg_index = (first_dword >> 16) & 0xF
load_from_reg = (first_dword >> 12) & 0xF
offset_register = (first_dword >> 8) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
rel_address = ((first_dword & 0xFF) << 32) | second_dword
if load_from_reg == 3:
out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] W={bit_width}"
elif load_from_reg:
src_reg = reg_index if load_from_reg == 1 else offset_register
out.str = f"R{reg_index} = [R{src_reg}+0x{rel_address:010X}] W={bit_width}"
else:
out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+0x{rel_address:010X}] W={bit_width}"
elif out.opcode == CheatVmOpcodeType.StoreStaticToAddress:
bit_width = (first_dword >> 24) & 0xF
reg_index = (first_dword >> 16) & 0xF
increment_reg = ((first_dword >> 12) & 0xF) != 0
add_offset_reg = ((first_dword >> 8) & 0xF) != 0
offset_reg_index = (first_dword >> 4) & 0xF
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit
if add_offset_reg:
out.str = f"[R{reg_index}+R{offset_reg_index}] = 0x{value.value:016X} W={bit_width}"
else:
out.str = f"[R{reg_index}] = 0x{value.value:016X} W={bit_width}"
if increment_reg:
out.str += f" R{reg_index} += {bit_width}"
elif out.opcode == CheatVmOpcodeType.PerformArithmeticStatic:
bit_width = (first_dword >> 24) & 0xF
reg_index = (first_dword >> 16) & 0xF
math_type = RegisterArithmeticType((first_dword >> 12) & 0xF)
value, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
out.str = f"R{reg_index} = R{reg_index} {MATH_STR.get(math_type, '?')} 0x{value:X} W={bit_width}"
elif out.opcode == CheatVmOpcodeType.BeginKeypressConditionalBlock:
key_mask = first_dword & 0x0FFFFFFF
out.str = f"If keyheld 0x{key_mask:X}"
elif out.opcode == CheatVmOpcodeType.PerformArithmeticRegister:
bit_width = (first_dword >> 24) & 0xF
math_type = RegisterArithmeticType((first_dword >> 20) & 0xF)
dst_reg_index = (first_dword >> 16) & 0xF
src_reg_1_index = (first_dword >> 12) & 0xF
has_immediate = ((first_dword >> 8) & 0xF) != 0
if has_immediate:
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} 0x{value.value:X} W={bit_width}"
else:
src_reg_2_index = (first_dword >> 4) & 0xF
out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} R{src_reg_2_index} W={bit_width}"
elif out.opcode == CheatVmOpcodeType.StoreRegisterToAddress:
bit_width = (first_dword >> 24) & 0xF
str_reg_index = (first_dword >> 20) & 0xF
addr_reg_index = (first_dword >> 16) & 0xF
increment_reg = ((first_dword >> 12) & 0xF) != 0
ofs_type = StoreRegisterOffsetType((first_dword >> 8) & 0xF)
ofs_reg_index = (first_dword >> 4) & 0xF
addr_str = ""
if ofs_type == StoreRegisterOffsetType.None_:
addr_str = f"[R{addr_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.Reg:
addr_str = f"[R{addr_reg_index}+R{ofs_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.Imm:
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]"
elif ofs_type == StoreRegisterOffsetType.MemReg:
mem_type = MemoryAccessType(ofs_reg_index)
addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.MemImm:
mem_type = MemoryAccessType(ofs_reg_index)
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]"
elif ofs_type == StoreRegisterOffsetType.MemImmReg:
mem_type = MemoryAccessType(ofs_reg_index)
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}+0x{rel_address.value:X}]"
out.str = f"{addr_str} = R{str_reg_index} W={bit_width}"
if increment_reg:
out.str += f" R{addr_reg_index} += {bit_width}"
elif out.opcode == CheatVmOpcodeType.BeginRegisterConditionalBlock:
bit_width = (first_dword >> 20) & 0xF
cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF)
val_reg_index = (first_dword >> 12) & 0xF
comp_type = CompareRegisterValueType((first_dword >> 8) & 0xF)
comp_str = ""
if comp_type == CompareRegisterValueType.StaticValue:
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
comp_str = f"0x{value.value:X}"
elif comp_type == CompareRegisterValueType.OtherRegister:
other_reg_index = (first_dword >> 4) & 0xF
comp_str = f"R{other_reg_index}"
else: # Memory access
mem_type = MemoryAccessType((first_dword >> 4) & 0xF)
if comp_type in [CompareRegisterValueType.MemoryRelAddr, CompareRegisterValueType.RegisterRelAddr]:
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4)
if comp_type == CompareRegisterValueType.MemoryRelAddr:
comp_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]"
else: # RegisterRelAddr
addr_reg_index = (first_dword >> 4) & 0xF
comp_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]"
else: # MemoryOfsReg, RegisterOfsReg
ofs_reg_index = first_dword & 0xF
if comp_type == CompareRegisterValueType.MemoryOfsReg:
comp_str = f"[{mem_type_str(mem_type)}+R{ofs_reg_index}]"
else: # RegisterOfsReg
addr_reg_index = (first_dword >> 4) & 0xF
comp_str = f"[R{addr_reg_index}+R{ofs_reg_index}]"
out.str = f"If R{val_reg_index} {CONDITION_STR.get(cond_type, '?')} {comp_str}"
elif out.opcode == CheatVmOpcodeType.SaveRestoreRegister:
dst_index = (first_dword >> 16) & 0xF
src_index = (first_dword >> 8) & 0xF
op_type = SaveRestoreRegisterOpType((first_dword >> 4) & 0xF)
out.str = f"SaveRestoreRegister dst={dst_index} src={src_index} {OPERAND_STR.get(op_type, '?')}"
elif out.opcode == CheatVmOpcodeType.SaveRestoreRegisterMask:
op_type = SaveRestoreRegisterOpType((first_dword >> 20) & 0xF)
mask = first_dword & 0xFFFF
out.str = f"SaveRestoreRegisterMask {OPERAND_STR.get(op_type, '?')} mask=0x{mask:04X}"
elif out.opcode == CheatVmOpcodeType.ReadWriteStaticRegister:
static_idx = (first_dword >> 4) & 0xFF
idx = first_dword & 0xF
out.str = f"ReadWriteStaticRegister static_idx=0x{static_idx:X} idx={idx}"
elif out.opcode == CheatVmOpcodeType.BeginExtendedKeypressConditionalBlock:
auto_repeat = ((first_dword >> 20) & 0xF) != 0
key_mask, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8)
out.str = f"If {'keyheld' if auto_repeat else 'keydown'} 0x{key_mask.value:X}"
elif out.opcode == CheatVmOpcodeType.PauseProcess:
out.str = "PauseProcess"
elif out.opcode == CheatVmOpcodeType.ResumeProcess:
out.str = "ResumeProcess"
elif out.opcode == CheatVmOpcodeType.DebugLog:
out.str = "DebugLog" # Simplified
else:
out.str = f"Opcode {out.opcode.name} not implemented in this script."
out.size = instruction_ptr - index
return out
def disassemble_cheat(opcodes):
"""Disassembles a list of opcodes for a single cheat."""
index = 0
while index < len(opcodes):
opcode_info = decode_next_opcode(opcodes, index)
if not opcode_info:
break
raw_opcodes_list = opcodes[index : index + opcode_info.size]
raw_opcodes_str = " ".join([f"{opc:08X}" for opc in raw_opcodes_list])
print(f"{raw_opcodes_str:<40} {opcode_info.str}")
index += opcode_info.size
def disassemble_opcodes_from_file(file_path):
try:
with open(file_path, 'r') as f:
cheat_opcodes = []
for line in f:
stripped_line = line.strip()
if not stripped_line:
continue
if (stripped_line.startswith('[') and stripped_line.endswith(']')) or \
(stripped_line.startswith('{') and stripped_line.endswith('}')):
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
cheat_opcodes = []
print(f"\n{stripped_line}")
else:
parts = stripped_line.split()
for part in parts:
if part:
try:
cheat_opcodes.append(int(part, 16))
except ValueError:
# Ignore non-hex parts, could be comments
pass
# After the loop, process any remaining opcodes
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
except FileNotFoundError:
print(f"Error: The file '{file_path}' was not found.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
def disassemble_opcodes_from_string(opcodes_str):
cheat_opcodes = []
for line in opcodes_str.splitlines():
line = line.strip()
if not line:
continue
if line.startswith('[') and line.endswith(']'):
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
cheat_opcodes = []
print(f"\n{line}")
else:
parts = line.split()
for part in parts:
try:
cheat_opcodes.append(int(part, 16))
except ValueError:
pass # Ignore non-hex parts
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
def main():
"""Main function to handle command-line arguments or interactive mode."""
if not CAPSTONE_AVAILABLE:
print("Capstone library not found. Please install it with 'pip install capstone'")
sys.exit(1)
# If a command-line argument is provided, treat it as a file path
if len(sys.argv) > 1:
file_path = sys.argv[1]
print(f"--- Disassembling from file: {file_path} ---")
disassemble_opcodes_from_file(file_path)
input("\nPress Enter to exit...")
else:
if len(sys.argv) != 2:
print("Usage: python disassemble_cheats.py <path_to_opcode_file>")
example_file = 'asm.txt'
print(f"\nNo file provided. Trying with example file: '{example_file}'")
try:
with open(example_file, 'r'):
disassemble_opcodes_from_file(example_file)
except FileNotFoundError:
print(f"Example file '{example_file}' not found.")
print("--- Interactive Mode ---")
while True:
print("\nPaste your opcodes (type 'done' on a new line to finish):")
opcodes_str = ""
while True:
try:
line = input()
if line.strip().lower() == 'done':
break
opcodes_str += line + "\n"
except EOFError:
break
if opcodes_str.strip():
disassemble_opcodes_from_string(opcodes_str)
choice = input("\nDisassemble more? (yes/no): ")
if choice.strip().lower() != 'yes':
break
if __name__ == "__main__":
main()
import sys
from enum import Enum
try:
from capstone import Cs, CS_ARCH_ARM64, CS_ARCH_ARM, CS_MODE_ARM, CS_MODE_THUMB
CAPSTONE_AVAILABLE = True
except ImportError:
CAPSTONE_AVAILABLE = False
# Global variable to store the target architecture chosen by the user
TARGET_ARCH = None
# Based on source/opcode.hpp
class CheatVmOpcodeType(Enum):
StoreStatic = 0
BeginConditionalBlock = 1
EndConditionalBlock = 2
ControlLoop = 3
LoadRegisterStatic = 4
LoadRegisterMemory = 5
StoreStaticToAddress = 6
PerformArithmeticStatic = 7
BeginKeypressConditionalBlock = 8
PerformArithmeticRegister = 9
StoreRegisterToAddress = 10
Reserved11 = 11
ExtendedWidth = 12
BeginRegisterConditionalBlock = 0xC0
SaveRestoreRegister = 0xC1
SaveRestoreRegisterMask = 0xC2
ReadWriteStaticRegister = 0xC3
BeginExtendedKeypressConditionalBlock = 0xC4
DoubleExtendedWidth = 0xF0
PauseProcess = 0xFF0
ResumeProcess = 0xFF1
DebugLog = 0xFFF
class MemoryAccessType(Enum):
MainNso = 0
Heap = 1
Alias = 2
Aslr = 3
Blank = 4
class ConditionalComparisonType(Enum):
GT = 1
GE = 2
LT = 3
LE = 4
EQ = 5
NE = 6
class RegisterArithmeticType(Enum):
Addition = 0
Subtraction = 1
Multiplication = 2
LeftShift = 3
RightShift = 4
LogicalAnd = 5
LogicalOr = 6
LogicalNot = 7
LogicalXor = 8
None_ = 9
FloatAddition = 10
FloatMultiplication = 11
DoubleAddition = 12
DoubleMultiplication = 13
class StoreRegisterOffsetType(Enum):
None_ = 0
Reg = 1
Imm = 2
MemReg = 3
MemImm = 4
MemImmReg = 5
class CompareRegisterValueType(Enum):
MemoryRelAddr = 0
MemoryOfsReg = 1
RegisterRelAddr = 2
RegisterOfsReg = 3
StaticValue = 4
OtherRegister = 5
OffsetValue = 6
class SaveRestoreRegisterOpType(Enum):
Restore = 0
Save = 1
ClearSaved = 2
ClearRegs = 3
class DebugLogValueType(Enum):
MemoryRelAddr = 0
MemoryOfsReg = 1
RegisterRelAddr = 2
RegisterOfsReg = 3
RegisterValue = 4
CONDITION_STR = {
ConditionalComparisonType.GT: ">",
ConditionalComparisonType.GE: ">=",
ConditionalComparisonType.LT: "<",
ConditionalComparisonType.LE: "<=",
ConditionalComparisonType.EQ: "==",
ConditionalComparisonType.NE: "!=",
}
MATH_STR = {
RegisterArithmeticType.Addition: "+",
RegisterArithmeticType.Subtraction: "-",
RegisterArithmeticType.Multiplication: "*",
RegisterArithmeticType.LeftShift: "<<",
RegisterArithmeticType.RightShift: ">>",
RegisterArithmeticType.LogicalAnd: "&",
RegisterArithmeticType.LogicalOr: "|",
RegisterArithmeticType.LogicalNot: "!",
RegisterArithmeticType.LogicalXor: "^",
RegisterArithmeticType.None_: "",
RegisterArithmeticType.FloatAddition: "+f",
RegisterArithmeticType.FloatMultiplication: "*f",
RegisterArithmeticType.DoubleAddition: "+d",
RegisterArithmeticType.DoubleMultiplication: "*d",
}
OPERAND_STR = {
SaveRestoreRegisterOpType.Restore: "Restore",
SaveRestoreRegisterOpType.Save: "Save",
SaveRestoreRegisterOpType.ClearSaved: "ClearSaved",
SaveRestoreRegisterOpType.ClearRegs: "ClearRegs",
}
class VmInt:
def __init__(self, value=0):
self.value = value
class CheatVmOpcode:
def __init__(self):
self.opcode = None
self.size = 0
self.str = ""
def get_next_dword(opcodes, instruction_ptr):
if instruction_ptr >= len(opcodes):
return None, instruction_ptr + 1
return opcodes[instruction_ptr], instruction_ptr + 1
def get_next_vm_int(opcodes, instruction_ptr, bit_width):
val = VmInt()
first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if first_dword is None:
return None, instruction_ptr
if bit_width == 1:
val.value = first_dword & 0xFF
elif bit_width == 2:
val.value = first_dword & 0xFFFF
elif bit_width == 4:
val.value = first_dword
elif bit_width == 8:
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if second_dword is None:
return None, instruction_ptr
val.value = (first_dword << 32) | second_dword
else:
# Invalid bit_width, but we'll assign the dword to avoid crashing.
val.value = first_dword
return val, instruction_ptr
def mem_type_str(mem_type):
if mem_type == MemoryAccessType.MainNso: return "Main"
if mem_type == MemoryAccessType.Heap: return "Heap"
if mem_type == MemoryAccessType.Alias: return "Alias"
if mem_type == MemoryAccessType.Aslr: return "Aslr"
return ""
def arm64_disassemble(value, address):
"""
Disassembles a 4-byte value as an ARM64 instruction.
ARM64 instructions are always 4 bytes.
"""
if not CAPSTONE_AVAILABLE:
return ""
md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
# Ensure we always convert to 4 bytes for ARM64 instruction disassembly
code = (value & 0xFFFFFFFF).to_bytes(4, byteorder='little')
disassembled = []
try:
for i in md.disasm(code, address):
disassembled.append(f"{i.mnemonic} {i.op_str}")
return "; ".join(disassembled).strip()
except Exception:
return "" # Return empty string if Capstone fails
def arm32_disassemble(value, address):
"""
Disassembles a 4-byte value as an ARM32 instruction (trying ARM then Thumb).
ARM32/Thumb instructions are 2 or 4 bytes. I provide 4 bytes and let Capstone handle it.
"""
if not CAPSTONE_AVAILABLE:
return ""
code = value.to_bytes(4, byteorder='little') # ARM32 instructions are 4 bytes (or 2 for Thumb, but provide 4)
# Try ARM mode first
md_arm = Cs(CS_ARCH_ARM, CS_MODE_ARM)
disassembled = []
try:
for i in md_arm.disasm(code, address):
disassembled.append(f"{i.mnemonic} {i.op_str}")
if disassembled:
return "; ".join(disassembled).strip()
except Exception:
pass # Fall through to Thumb mode if ARM disassembly fails or produces nothing
# If ARM mode didn't work or produced no output, try Thumb mode
md_thumb = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
disassembled = []
try:
for i in md_thumb.disasm(code, address):
disassembled.append(f"{i.mnemonic} {i.op_str}")
if disassembled:
return "; ".join(disassembled).strip()
except Exception:
pass
return "" # Return empty string if neither ARM nor Thumb can disassemble
def decode_next_opcode(opcodes, index):
instruction_ptr = index
first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
if first_dword is None:
return None
out = CheatVmOpcode()
opcode_val = (first_dword >> 28) & 0xF
if opcode_val >= CheatVmOpcodeType.ExtendedWidth.value:
opcode_val = (opcode_val << 4) | ((first_dword >> 24) & 0xF)
if opcode_val >= CheatVmOpcodeType.DoubleExtendedWidth.value:
opcode_val = (opcode_val << 4) | ((first_dword >> 20) & 0xF)
try:
out.opcode = CheatVmOpcodeType(opcode_val)
except ValueError:
out.str = f"Unknown opcode: {hex(opcode_val)}"
out.size = 1
return out
if out.opcode == CheatVmOpcodeType.StoreStatic:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
offset_register = (first_dword >> 16) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
# Assuming rel_address high 24 bits are from first_dword & 0xFFFFFF
# and low 32 bits from second_dword.
rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
out.str = f"[{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] = 0x{value.value:X}"
# Determine disassembly based on bit_width and global TARGET_ARCH
if CAPSTONE_AVAILABLE:
if bit_width == 8: # 8-byte value: Disassemble both halves based on TARGET_ARCH
high_32_bits = (value.value >> 32) & 0xFFFFFFFF
low_32_bits = value.value & 0xFFFFFFFF
combined_asm = []
if TARGET_ARCH == "ARM64":
asm_low = arm64_disassemble(low_32_bits, rel_address)
asm_high = arm64_disassemble(high_32_bits, rel_address + 4)
arch_label = "ARM64"
elif TARGET_ARCH == "ARM32":
asm_low = arm32_disassemble(low_32_bits, rel_address)
asm_high = arm32_disassemble(high_32_bits, rel_address + 4)
arch_label = "ARM32"
else: # Should not happen if TARGET_ARCH is set correctly
asm_low = ""
asm_high = ""
arch_label = "UNKNOWN ARCH"
if asm_low:
combined_asm.append(f"[{hex(rel_address)}] {asm_low}")
if asm_high:
combined_asm.append(f"[{hex(rel_address + 4)}] {asm_high}")
if combined_asm:
out.str += f" ({arch_label}: {'; '.join(combined_asm)})"
else:
out.str += f" ({arch_label}: No disassembly)"
elif bit_width == 4: # 4-byte value: Use TARGET_ARCH to decide
if TARGET_ARCH == "ARM64":
asm = arm64_disassemble(value.value, rel_address)
if asm:
out.str += f" (ARM64: {asm})"
elif TARGET_ARCH == "ARM32":
asm = arm32_disassemble(value.value, rel_address)
if asm:
out.str += f" (ARM32: {asm})"
else: # Should not happen if TARGET_ARCH is set correctly
out.str += " (Disassembly type not determined)"
else:
out.str += " (Disassembly skipped - Capstone not available)"
elif out.opcode == CheatVmOpcodeType.BeginConditionalBlock:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF)
include_ofs_reg = ((first_dword >> 12) & 0xF) != 0
ofs_reg_index = (first_dword >> 8) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword # Adjusted to mask 24 bits
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
ofs_reg_str = f"R{ofs_reg_index}+" if include_ofs_reg else ""
out.str = f"If [{mem_type_str(mem_type)}+{ofs_reg_str}0x{rel_address:010X}] {CONDITION_STR.get(cond_type, '?')} 0x{value.value:X}"
elif out.opcode == CheatVmOpcodeType.EndConditionalBlock:
end_type = (first_dword >> 24) & 0xF
out.str = "Else" if end_type == 1 else "Endif"
elif out.opcode == CheatVmOpcodeType.ControlLoop:
start_loop = ((first_dword >> 24) & 0xF) == 0
reg_index = (first_dword >> 16) & 0xF
if start_loop:
num_iters, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
out.str = f"Loop Start R{reg_index} = {num_iters}"
else:
out.str = "Loop stop"
elif out.opcode == CheatVmOpcodeType.LoadRegisterStatic:
reg_index = (first_dword >> 16) & 0xF
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit value
out.str = f"R{reg_index} = 0x{value.value:016X}"
elif out.opcode == CheatVmOpcodeType.LoadRegisterMemory:
bit_width = (first_dword >> 24) & 0xF
mem_type = MemoryAccessType((first_dword >> 20) & 0xF)
reg_index = (first_dword >> 16) & 0xF
load_from_reg = (first_dword >> 12) & 0xF
offset_register = (first_dword >> 8) & 0xF
second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword # Adjusted to mask 24 bits
if load_from_reg == 3:
out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] W={bit_width}"
elif load_from_reg:
src_reg = reg_index if load_from_reg == 1 else offset_register
out.str = f"R{reg_index} = [R{src_reg}+0x{rel_address:010X}] W={bit_width}"
else:
out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+0x{rel_address:010X}] W={bit_width}"
elif out.opcode == CheatVmOpcodeType.StoreStaticToAddress:
bit_width = (first_dword >> 24) & 0xF
reg_index = (first_dword >> 16) & 0xF
increment_reg = ((first_dword >> 12) & 0xF) != 0
add_offset_reg = ((first_dword >> 8) & 0xF) != 0
offset_reg_index = (first_dword >> 4) & 0xF
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit
if add_offset_reg:
out.str = f"[R{reg_index}+R{offset_reg_index}] = 0x{value.value:016X} W={bit_width}"
else:
out.str = f"[R{reg_index}] = 0x{value.value:016X} W={bit_width}"
if increment_reg:
out.str += f" R{reg_index} += {bit_width}"
elif out.opcode == CheatVmOpcodeType.PerformArithmeticStatic:
bit_width = (first_dword >> 24) & 0xF
reg_index = (first_dword >> 16) & 0xF
math_type = RegisterArithmeticType((first_dword >> 12) & 0xF)
value, instruction_ptr = get_next_dword(opcodes, instruction_ptr)
out.str = f"R{reg_index} = R{reg_index} {MATH_STR.get(math_type, '?')} 0x{value:X} W={bit_width}"
elif out.opcode == CheatVmOpcodeType.BeginKeypressConditionalBlock:
key_mask = first_dword & 0x0FFFFFFF
out.str = f"If keyheld 0x{key_mask:X}"
elif out.opcode == CheatVmOpcodeType.PerformArithmeticRegister:
bit_width = (first_dword >> 24) & 0xF
math_type = RegisterArithmeticType((first_dword >> 20) & 0xF)
dst_reg_index = (first_dword >> 16) & 0xF
src_reg_1_index = (first_dword >> 12) & 0xF
has_immediate = ((first_dword >> 8) & 0xF) != 0
if has_immediate:
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} 0x{value.value:X} W={bit_width}"
else:
src_reg_2_index = (first_dword >> 4) & 0xF
out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} R{src_reg_2_index} W={bit_width}"
elif out.opcode == CheatVmOpcodeType.StoreRegisterToAddress:
bit_width = (first_dword >> 24) & 0xF
str_reg_index = (first_dword >> 20) & 0xF
addr_reg_index = (first_dword >> 16) & 0xF
increment_reg = ((first_dword >> 12) & 0xF) != 0
ofs_type = StoreRegisterOffsetType((first_dword >> 8) & 0xF)
ofs_reg_index = (first_dword >> 4) & 0xF
addr_str = ""
if ofs_type == StoreRegisterOffsetType.None_:
addr_str = f"[R{addr_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.Reg:
addr_str = f"[R{addr_reg_index}+R{ofs_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.Imm:
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]"
elif ofs_type == StoreRegisterOffsetType.MemReg:
mem_type = MemoryAccessType(ofs_reg_index)
addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}]"
elif ofs_type == StoreRegisterOffsetType.MemImm:
mem_type = MemoryAccessType(ofs_reg_index)
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]"
elif ofs_type == StoreRegisterOffsetType.MemImmReg:
mem_type = MemoryAccessType(ofs_reg_index)
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit
addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}+0x{rel_address.value:X}]"
out.str = f"{addr_str} = R{str_reg_index} W={bit_width}"
if increment_reg:
out.str += f" R{addr_reg_index} += {bit_width}"
elif out.opcode == CheatVmOpcodeType.BeginRegisterConditionalBlock:
bit_width = (first_dword >> 20) & 0xF
cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF)
val_reg_index = (first_dword >> 12) & 0xF
comp_type = CompareRegisterValueType((first_dword >> 8) & 0xF)
comp_str = ""
if comp_type == CompareRegisterValueType.StaticValue:
value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width)
comp_str = f"0x{value.value:X}"
elif comp_type == CompareRegisterValueType.OtherRegister:
other_reg_index = (first_dword >> 4) & 0xF
comp_str = f"R{other_reg_index}"
else: # Memory access
mem_type = MemoryAccessType((first_dword >> 4) & 0xF)
if comp_type in [CompareRegisterValueType.MemoryRelAddr, CompareRegisterValueType.RegisterRelAddr]:
rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4)
if comp_type == CompareRegisterValueType.MemoryRelAddr:
comp_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]"
else: # RegisterRelAddr
addr_reg_index = (first_dword >> 4) & 0xF
comp_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]"
else: # MemoryOfsReg, RegisterOfsReg
ofs_reg_index = first_dword & 0xF
if comp_type == CompareRegisterValueType.MemoryOfsReg:
comp_str = f"[{mem_type_str(mem_type)}+R{ofs_reg_index}]"
else: # RegisterOfsReg
addr_reg_index = (first_dword >> 4) & 0xF
comp_str = f"[R{addr_reg_index}+R{ofs_reg_index}]"
out.str = f"If R{val_reg_index} {CONDITION_STR.get(cond_type, '?')} {comp_str}"
elif out.opcode == CheatVmOpcodeType.SaveRestoreRegister:
dst_index = (first_dword >> 16) & 0xF
src_index = (first_dword >> 8) & 0xF
op_type = SaveRestoreRegisterOpType((first_dword >> 4) & 0xF)
out.str = f"SaveRestoreRegister dst={dst_index} src={src_index} {OPERAND_STR.get(op_type, '?')}"
elif out.opcode == CheatVmOpcodeType.SaveRestoreRegisterMask:
op_type = SaveRestoreRegisterOpType((first_dword >> 20) & 0xF)
mask = first_dword & 0xFFFF
out.str = f"SaveRestoreRegisterMask {OPERAND_STR.get(op_type, '?')} mask=0x{mask:04X}"
elif out.opcode == CheatVmOpcodeType.ReadWriteStaticRegister:
static_idx = (first_dword >> 4) & 0xFF
idx = first_dword & 0xF
out.str = f"ReadWriteStaticRegister static_idx=0x{static_idx:X} idx={idx}"
elif out.opcode == CheatVmOpcodeType.BeginExtendedKeypressConditionalBlock:
auto_repeat = ((first_dword >> 20) & 0xF) != 0
key_mask, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8)
out.str = f"If {'keyheld' if auto_repeat else 'keydown'} 0x{key_mask.value:X}"
elif out.opcode == CheatVmOpcodeType.PauseProcess:
out.str = "PauseProcess"
elif out.opcode == CheatVmOpcodeType.ResumeProcess:
out.str = "ResumeProcess"
elif out.opcode == CheatVmOpcodeType.DebugLog:
out.str = "DebugLog" # Simplified
else:
out.str = f"Opcode {out.opcode.name} not implemented in this script."
out.size = instruction_ptr - index
return out
def disassemble_cheat(opcodes):
"""Disassembles a list of opcodes for a single cheat."""
index = 0
while index < len(opcodes):
opcode_info = decode_next_opcode(opcodes, index)
if not opcode_info:
break
raw_opcodes_list = opcodes[index : index + opcode_info.size]
raw_opcodes_str = " ".join([f"{opc:08X}" for opc in raw_opcodes_list])
print(f"{raw_opcodes_str:<40} {opcode_info.str}")
index += opcode_info.size
def disassemble_opcodes_from_file(file_path):
global TARGET_ARCH # Declare intent to modify global variable
if TARGET_ARCH is None: # If not set by command line, prompt
TARGET_ARCH = get_target_arch_from_user()
try:
with open(file_path, 'r') as f:
cheat_opcodes = []
for line in f:
stripped_line = line.strip()
if not stripped_line:
continue
if (stripped_line.startswith('[') and stripped_line.endswith(']')) or \
(stripped_line.startswith('{') and stripped_line.endswith('}')):
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
cheat_opcodes = []
print(f"\n{stripped_line}")
else:
parts = stripped_line.split()
for part in parts:
if part:
try:
cheat_opcodes.append(int(part, 16))
except ValueError:
# Ignore non-hex parts, could be comments
pass
# After the loop, process any remaining opcodes
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
except FileNotFoundError:
print(f"Error: The file '{file_path}' was not found.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
def disassemble_opcodes_from_string(opcodes_str):
cheat_opcodes = []
for line in opcodes_str.splitlines():
line = line.strip()
if not line:
continue
if line.startswith('[') and line.endswith(']'):
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
cheat_opcodes = []
print(f"\n{line}")
else:
parts = line.split()
for part in parts:
try:
cheat_opcodes.append(int(part, 16))
except ValueError:
pass # Ignore non-hex parts
if cheat_opcodes:
disassemble_cheat(cheat_opcodes)
def get_target_arch_from_user():
while True:
choice = input("Enter target architecture (ARM32/ARM64): ").strip().upper()
if choice in ["ARM32", "ARM64"]:
return choice
else:
print("Invalid choice. Please enter 'ARM32' or 'ARM64'.")
def main():
"""Main function to handle command-line arguments or interactive mode."""
global TARGET_ARCH
if not CAPSTONE_AVAILABLE:
print("Capstone library not found. Please install it with 'pip install capstone'")
sys.exit(1)
file_path_arg = None
for i, arg in enumerate(sys.argv[1:]):
if arg.lower() == "--arch" and i + 1 < len(sys.argv[1:]):
arch_arg = sys.argv[i+2].strip().upper()
if arch_arg in ["ARM32", "ARM64"]:
TARGET_ARCH = arch_arg
print(f"Target architecture set to: {TARGET_ARCH} (from command line)")
else:
print(f"Warning: Invalid architecture '{arch_arg}' provided via --arch. Will prompt.")
sys.argv.pop(i+1)
sys.argv.pop(i+1)
break
if len(sys.argv) > 1:
file_path_arg = sys.argv[1]
if TARGET_ARCH is None:
TARGET_ARCH = get_target_arch_from_user()
print(f"\nDisassembly will target: {TARGET_ARCH}")
if file_path_arg:
print(f"--- Disassembling from file: {file_path_arg} ---")
disassemble_opcodes_from_file(file_path_arg)
input("\nPress Enter to exit...")
else:
if len(sys.argv) != 2:
print("Usage: python ASMdisassemble_cheats.py <path_to_opcode_file>")
example_file = 'asm.txt'
print(f"\nNo file provided. Trying with example file: '{example_file}'")
try:
with open(example_file, 'r'):
disassemble_opcodes_from_file(example_file)
except FileNotFoundError:
print(f"Example file '{example_file}' not found.")
print("--- Interactive Mode ---")
while True:
print("\nPaste your opcodes (type 'done' on a new line to finish):")
opcodes_str = ""
while True:
try:
line = input()
if line.strip().lower() == 'done':
break
opcodes_str += line + "\n"
except EOFError:
break
if opcodes_str.strip():
disassemble_opcodes_from_string(opcodes_str)
choice = input("\nDisassemble more? (yes/no): ")
if choice.strip().lower() != 'yes':
break
if __name__ == "__main__":
main()
tks sir![Star Ptr]
580F0000 0F8FD4B0
580F1000 000001E0
580F1000 000000B0
780F0000 00000010
680F0000 408F3800 00000000



Hi bro, I tried to add them on MK8 3.0.3 but It doesn't detect them for me on mod folder and atmosphere tooThe last days/weeks I tried out to achieve some more cheats for Mario Kart but wasn't easy at least for me
A few were possible
You can add these cheats to the existing ones you already have or find here in the forum.
It is a little bit dirty how I achieved the cheats to work but hadn't much success in finding the player number in the data structure of the items or vice versa.
And the fact that it is ARM32 didn't make it better.
So Feedback is much appreciated also on the solving side of lifeor with the naming, because my two code caves I am not pulling in a master code right now but have to be activated that it works ([Activator Set Item Place 1] and [Activator Set Item Place 2])
Dirty because wasn't able to store the base address of the player into the stack or memory (missing ARM32 knowledge and know how to deal with relative memory addresses) so I did another trick.
With the item buttons combination I save in the next free item slot for a certain player a custom number (50 for 3 Red Shells, 51 for Lightning etc.) and when it comes to storing the item after touching a question mark/item box - this custom number leads to the individual item...
That is the magic... This in done in the first code cave and the second code cave is to avoid a irrelevant store in the item slot in between my custom number is set and the real item is placed into the item slot.
I am not sure if I can also save these global constants for my cheats to work (e.g. 50 for 3 Red Shells) elsewhere. Because now the code caves and the item combination have to be in sync with each other.
So enjoy
[Mario Kart 8 Deluxe 3.0.3 TID: 0100152000022000 BID: 6A85262F21B90364]
[Item]
20000000
[Activator Set Item Place 1]
04000000 000482E0 E5840058
04000000 000482E0 EA2F531E
04000000 00C1CF60 E52D1004
04000000 00C1CF64 E5941058
04000000 00C1CF68 E3510050
04000000 00C1CF6C 1A000000
04000000 00C1CF70 E3A00013
04000000 00C1CF74 E3510051
04000000 00C1CF78 1A000000
04000000 00C1CF7C E3A0000A
04000000 00C1CF80 E3510052
04000000 00C1CF84 1A000000
04000000 00C1CF88 E3A0000B
04000000 00C1CF8C E3510053
04000000 00C1CF90 1A000000
04000000 00C1CF94 E3A00009
04000000 00C1CF98 E5840058
04000000 00C1CF9C E49D1004
04000000 00C1CFA0 EAD0ACCF
[Activator Set Item Place 1 off]
04000000 000482E0 E5840058
[Activator Set Item Place 2]
04000000 00047F7C E5801058
04000000 00047F7C EA2F540B
04000000 00C1CFB0 E52D2004
04000000 00C1CFB4 E5902058
04000000 00C1CFB8 E3520032
04000000 00C1CFBC 3A000000
04000000 00C1CFC0 EA000000
04000000 00C1CFC4 E5801058
04000000 00C1CFC8 E49D2004
04000000 00C1CFCC EAD0ABEB
[Activator Set Item Place 2 off]
04000000 00047F7C E5801058
[P1 Set Next Item 3 Red Shells L+A+DPad Up]
80002041
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000000
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000050
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P1 Set Next Item Lightning L+A+DPad Right]
80004041
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000000
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000051
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P1 Set Next Item Golden Mushroom L+A+DPad Down]
80008041
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000000
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000052
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P1 Set Next Item Bullet Bill L+A+DPad Left]
80001041
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000000
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000053
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P2 Set Next Item 3 Red Shells L+Y+DPad Up]
80002048
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000004
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000050
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P2 Set Next Item Lightning L+Y+DPad Right]
80004048
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000004
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000051
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P2 Set Next Item Golden Mushroom L+Y+DPad Down]
80008048
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000004
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000052
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[P2 Set Next Item Bullet Bill L+Y+DPad Left]
80001048
540F0000 00F4F9DC
540F1000 00000014
540F1000 00000064
540F1000 0000007C
540F1000 00000004
30000000 00000002
9891F000
54011000 00000030
74010000 00000058
98921000
54011000 00000000
C0411400 00000030
64020000 00000000 00000053
40000000 00000000 00000001
20010000
780F0000 00000004
31000000
20010000
[Item Instant Without wait time]
04000000 00047C00 E3A000C8
[Item Instant off]
04000000 00047C00 E2800001
[Item end]
20000001
[Lakitu Stop Pickup Wrong Direction]
04000000 0090C79C E320F000
[Lakitu Stop Pickup Wrong Direction off]
04000000 0090C79C E1C406B4
Your BID of the game is matching? Sounds like a cheat file or recognition problem. Because of course in the mod folder it is not working because it is a cheat but in atmosphere under contents and a folder with the TID of the game and a cheat text file with the correct BID it should workHi bro, I tried to add them on MK8 3.0.3 but It doesn't detect them for me on mod folder and atmosphere too![]()
First of all, thank you for providing such a great tool.
Here is a script to assemble codes to type 0.. a mix of both Tom and I only arm 64. I havent even tried arm32 for this.so full credit to Tom on his script https://github.com/tomvita/Breeze-Beta/blob/master/disassemble_cheats.py
I am just waiting on him to approve more of my bug fix pull request but you can grab from his link.
I do also have one with the pending bug fixes here
This fixes 8 byte write instructions to actually convert rather than leave empty. (you can copy this code then paste into a notepad and save as a .py file to make the script
Python:import sys from enum import Enum try: from capstone import Cs, CS_ARCH_ARM64, CS_MODE_ARM CAPSTONE_AVAILABLE = True except ImportError: CAPSTONE_AVAILABLE = False # Based on source/opcode.hpp class CheatVmOpcodeType(Enum): StoreStatic = 0 BeginConditionalBlock = 1 EndConditionalBlock = 2 ControlLoop = 3 LoadRegisterStatic = 4 LoadRegisterMemory = 5 StoreStaticToAddress = 6 PerformArithmeticStatic = 7 BeginKeypressConditionalBlock = 8 PerformArithmeticRegister = 9 StoreRegisterToAddress = 10 Reserved11 = 11 ExtendedWidth = 12 BeginRegisterConditionalBlock = 0xC0 SaveRestoreRegister = 0xC1 SaveRestoreRegisterMask = 0xC2 ReadWriteStaticRegister = 0xC3 BeginExtendedKeypressConditionalBlock = 0xC4 DoubleExtendedWidth = 0xF0 PauseProcess = 0xFF0 ResumeProcess = 0xFF1 DebugLog = 0xFFF class MemoryAccessType(Enum): MainNso = 0 Heap = 1 Alias = 2 Aslr = 3 Blank = 4 class ConditionalComparisonType(Enum): GT = 1 GE = 2 LT = 3 LE = 4 EQ = 5 NE = 6 class RegisterArithmeticType(Enum): Addition = 0 Subtraction = 1 Multiplication = 2 LeftShift = 3 RightShift = 4 LogicalAnd = 5 LogicalOr = 6 LogicalNot = 7 LogicalXor = 8 None_ = 9 FloatAddition = 10 FloatMultiplication = 11 DoubleAddition = 12 DoubleMultiplication = 13 class StoreRegisterOffsetType(Enum): None_ = 0 Reg = 1 Imm = 2 MemReg = 3 MemImm = 4 MemImmReg = 5 class CompareRegisterValueType(Enum): MemoryRelAddr = 0 MemoryOfsReg = 1 RegisterRelAddr = 2 RegisterOfsReg = 3 StaticValue = 4 OtherRegister = 5 OffsetValue = 6 class SaveRestoreRegisterOpType(Enum): Restore = 0 Save = 1 ClearSaved = 2 ClearRegs = 3 class DebugLogValueType(Enum): MemoryRelAddr = 0 MemoryOfsReg = 1 RegisterRelAddr = 2 RegisterOfsReg = 3 RegisterValue = 4 CONDITION_STR = { ConditionalComparisonType.GT: ">", ConditionalComparisonType.GE: ">=", ConditionalComparisonType.LT: "<", ConditionalComparisonType.LE: "<=", ConditionalComparisonType.EQ: "==", ConditionalComparisonType.NE: "!=", } MATH_STR = { RegisterArithmeticType.Addition: "+", RegisterArithmeticType.Subtraction: "-", RegisterArithmeticType.Multiplication: "*", RegisterArithmeticType.LeftShift: "<<", RegisterArithmeticType.RightShift: ">>", RegisterArithmeticType.LogicalAnd: "&", RegisterArithmeticType.LogicalOr: "|", RegisterArithmeticType.LogicalNot: "!", RegisterArithmeticType.LogicalXor: "^", RegisterArithmeticType.None_: "", RegisterArithmeticType.FloatAddition: "+f", RegisterArithmeticType.FloatMultiplication: "*f", RegisterArithmeticType.DoubleAddition: "+d", RegisterArithmeticType.DoubleMultiplication: "*d", } OPERAND_STR = { SaveRestoreRegisterOpType.Restore: "Restore", SaveRestoreRegisterOpType.Save: "Save", SaveRestoreRegisterOpType.ClearSaved: "ClearSaved", SaveRestoreRegisterOpType.ClearRegs: "ClearRegs", } class VmInt: def __init__(self, value=0): self.value = value class CheatVmOpcode: def __init__(self): self.opcode = None self.size = 0 self.str = "" def get_next_dword(opcodes, instruction_ptr): if instruction_ptr >= len(opcodes): return None, instruction_ptr + 1 return opcodes[instruction_ptr], instruction_ptr + 1 def get_next_vm_int(opcodes, instruction_ptr, bit_width): val = VmInt() first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if first_dword is None: return None, instruction_ptr if bit_width == 1: val.value = first_dword & 0xFF elif bit_width == 2: val.value = first_dword & 0xFFFF elif bit_width == 4: val.value = first_dword elif bit_width == 8: second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if second_dword is None: return None, instruction_ptr val.value = (first_dword << 32) | second_dword else: # Invalid bit_width, but I'll assign the dword to avoid crashing. val.value = first_dword return val, instruction_ptr def mem_type_str(mem_type): if mem_type == MemoryAccessType.MainNso: return "Main" if mem_type == MemoryAccessType.Heap: return "Heap" if mem_type == MemoryAccessType.Alias: return "Alias" if mem_type == MemoryAccessType.Aslr: return "Aslr" return "" def arm64_disassemble(value, bit_width, address): if not CAPSTONE_AVAILABLE: return "" md = Cs(CS_ARCH_ARM64, CS_MODE_ARM) code = value.to_bytes(bit_width, byteorder='little') disassembled = [] try: for i in md.disasm(code, address): disassembled.append(f"{i.mnemonic} {i.op_str}") return "; ".join(disassembled).strip() except Exception: return "" # Return empty string if Capstone fails def decode_next_opcode(opcodes, index): instruction_ptr = index first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if first_dword is None: return None out = CheatVmOpcode() opcode_val = (first_dword >> 28) & 0xF if opcode_val >= CheatVmOpcodeType.ExtendedWidth.value: opcode_val = (opcode_val << 4) | ((first_dword >> 24) & 0xF) if opcode_val >= CheatVmOpcodeType.DoubleExtendedWidth.value: opcode_val = (opcode_val << 4) | ((first_dword >> 20) & 0xF) try: out.opcode = CheatVmOpcodeType(opcode_val) except ValueError: out.str = f"Unknown opcode: {hex(opcode_val)}" out.size = 1 return out if out.opcode == CheatVmOpcodeType.StoreStatic: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) offset_register = (first_dword >> 16) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) rel_address = ((first_dword & 0xFF) << 32) | second_dword value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) out.str = f"[{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] = 0x{value.value:X}" value_for_disasm = value.value if bit_width == 8: # The 64-bit value is read as (high_dword << 32 | low_dword). # For little-endian disassembly, the byte stream needs to be # ordered by the dwords as they appear in the file (high then low). # value.to_bytes(..., 'little') would produce bytes(low) then bytes(high). # To fix this, swap the dwords before converting to bytes. high_dw = value.value >> 32 low_dw = value.value & 0xFFFFFFFF value_for_disasm = (low_dw << 32) | high_dw if CAPSTONE_AVAILABLE and (bit_width == 4 or bit_width == 8): asm = arm64_disassemble(value_for_disasm, bit_width, rel_address) if asm: out.str += f" {asm}" else: out.str += " (Disassembly skipped - Capstone not available or invalid bit_width)" elif out.opcode == CheatVmOpcodeType.BeginConditionalBlock: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF) include_ofs_reg = ((first_dword >> 12) & 0xF) != 0 ofs_reg_index = (first_dword >> 8) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) rel_address = ((first_dword & 0xFF) << 32) | second_dword value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) ofs_reg_str = f"R{ofs_reg_index}+" if include_ofs_reg else "" out.str = f"If [{mem_type_str(mem_type)}+{ofs_reg_str}0x{rel_address:010X}] {CONDITION_STR.get(cond_type, '?')} 0x{value.value:X}" elif out.opcode == CheatVmOpcodeType.EndConditionalBlock: end_type = (first_dword >> 24) & 0xF out.str = "Else" if end_type == 1 else "Endif" elif out.opcode == CheatVmOpcodeType.ControlLoop: start_loop = ((first_dword >> 24) & 0xF) == 0 reg_index = (first_dword >> 16) & 0xF if start_loop: num_iters, instruction_ptr = get_next_dword(opcodes, instruction_ptr) out.str = f"Loop Start R{reg_index} = {num_iters}" else: out.str = "Loop stop" elif out.opcode == CheatVmOpcodeType.LoadRegisterStatic: reg_index = (first_dword >> 16) & 0xF value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit value out.str = f"R{reg_index} = 0x{value.value:016X}" elif out.opcode == CheatVmOpcodeType.LoadRegisterMemory: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) reg_index = (first_dword >> 16) & 0xF load_from_reg = (first_dword >> 12) & 0xF offset_register = (first_dword >> 8) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) rel_address = ((first_dword & 0xFF) << 32) | second_dword if load_from_reg == 3: out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] W={bit_width}" elif load_from_reg: src_reg = reg_index if load_from_reg == 1 else offset_register out.str = f"R{reg_index} = [R{src_reg}+0x{rel_address:010X}] W={bit_width}" else: out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+0x{rel_address:010X}] W={bit_width}" elif out.opcode == CheatVmOpcodeType.StoreStaticToAddress: bit_width = (first_dword >> 24) & 0xF reg_index = (first_dword >> 16) & 0xF increment_reg = ((first_dword >> 12) & 0xF) != 0 add_offset_reg = ((first_dword >> 8) & 0xF) != 0 offset_reg_index = (first_dword >> 4) & 0xF value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit if add_offset_reg: out.str = f"[R{reg_index}+R{offset_reg_index}] = 0x{value.value:016X} W={bit_width}" else: out.str = f"[R{reg_index}] = 0x{value.value:016X} W={bit_width}" if increment_reg: out.str += f" R{reg_index} += {bit_width}" elif out.opcode == CheatVmOpcodeType.PerformArithmeticStatic: bit_width = (first_dword >> 24) & 0xF reg_index = (first_dword >> 16) & 0xF math_type = RegisterArithmeticType((first_dword >> 12) & 0xF) value, instruction_ptr = get_next_dword(opcodes, instruction_ptr) out.str = f"R{reg_index} = R{reg_index} {MATH_STR.get(math_type, '?')} 0x{value:X} W={bit_width}" elif out.opcode == CheatVmOpcodeType.BeginKeypressConditionalBlock: key_mask = first_dword & 0x0FFFFFFF out.str = f"If keyheld 0x{key_mask:X}" elif out.opcode == CheatVmOpcodeType.PerformArithmeticRegister: bit_width = (first_dword >> 24) & 0xF math_type = RegisterArithmeticType((first_dword >> 20) & 0xF) dst_reg_index = (first_dword >> 16) & 0xF src_reg_1_index = (first_dword >> 12) & 0xF has_immediate = ((first_dword >> 8) & 0xF) != 0 if has_immediate: value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} 0x{value.value:X} W={bit_width}" else: src_reg_2_index = (first_dword >> 4) & 0xF out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} R{src_reg_2_index} W={bit_width}" elif out.opcode == CheatVmOpcodeType.StoreRegisterToAddress: bit_width = (first_dword >> 24) & 0xF str_reg_index = (first_dword >> 20) & 0xF addr_reg_index = (first_dword >> 16) & 0xF increment_reg = ((first_dword >> 12) & 0xF) != 0 ofs_type = StoreRegisterOffsetType((first_dword >> 8) & 0xF) ofs_reg_index = (first_dword >> 4) & 0xF addr_str = "" if ofs_type == StoreRegisterOffsetType.None_: addr_str = f"[R{addr_reg_index}]" elif ofs_type == StoreRegisterOffsetType.Reg: addr_str = f"[R{addr_reg_index}+R{ofs_reg_index}]" elif ofs_type == StoreRegisterOffsetType.Imm: rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]" elif ofs_type == StoreRegisterOffsetType.MemReg: mem_type = MemoryAccessType(ofs_reg_index) addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}]" elif ofs_type == StoreRegisterOffsetType.MemImm: mem_type = MemoryAccessType(ofs_reg_index) rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]" elif ofs_type == StoreRegisterOffsetType.MemImmReg: mem_type = MemoryAccessType(ofs_reg_index) rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}+0x{rel_address.value:X}]" out.str = f"{addr_str} = R{str_reg_index} W={bit_width}" if increment_reg: out.str += f" R{addr_reg_index} += {bit_width}" elif out.opcode == CheatVmOpcodeType.BeginRegisterConditionalBlock: bit_width = (first_dword >> 20) & 0xF cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF) val_reg_index = (first_dword >> 12) & 0xF comp_type = CompareRegisterValueType((first_dword >> 8) & 0xF) comp_str = "" if comp_type == CompareRegisterValueType.StaticValue: value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) comp_str = f"0x{value.value:X}" elif comp_type == CompareRegisterValueType.OtherRegister: other_reg_index = (first_dword >> 4) & 0xF comp_str = f"R{other_reg_index}" else: # Memory access mem_type = MemoryAccessType((first_dword >> 4) & 0xF) if comp_type in [CompareRegisterValueType.MemoryRelAddr, CompareRegisterValueType.RegisterRelAddr]: rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) if comp_type == CompareRegisterValueType.MemoryRelAddr: comp_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]" else: # RegisterRelAddr addr_reg_index = (first_dword >> 4) & 0xF comp_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]" else: # MemoryOfsReg, RegisterOfsReg ofs_reg_index = first_dword & 0xF if comp_type == CompareRegisterValueType.MemoryOfsReg: comp_str = f"[{mem_type_str(mem_type)}+R{ofs_reg_index}]" else: # RegisterOfsReg addr_reg_index = (first_dword >> 4) & 0xF comp_str = f"[R{addr_reg_index}+R{ofs_reg_index}]" out.str = f"If R{val_reg_index} {CONDITION_STR.get(cond_type, '?')} {comp_str}" elif out.opcode == CheatVmOpcodeType.SaveRestoreRegister: dst_index = (first_dword >> 16) & 0xF src_index = (first_dword >> 8) & 0xF op_type = SaveRestoreRegisterOpType((first_dword >> 4) & 0xF) out.str = f"SaveRestoreRegister dst={dst_index} src={src_index} {OPERAND_STR.get(op_type, '?')}" elif out.opcode == CheatVmOpcodeType.SaveRestoreRegisterMask: op_type = SaveRestoreRegisterOpType((first_dword >> 20) & 0xF) mask = first_dword & 0xFFFF out.str = f"SaveRestoreRegisterMask {OPERAND_STR.get(op_type, '?')} mask=0x{mask:04X}" elif out.opcode == CheatVmOpcodeType.ReadWriteStaticRegister: static_idx = (first_dword >> 4) & 0xFF idx = first_dword & 0xF out.str = f"ReadWriteStaticRegister static_idx=0x{static_idx:X} idx={idx}" elif out.opcode == CheatVmOpcodeType.BeginExtendedKeypressConditionalBlock: auto_repeat = ((first_dword >> 20) & 0xF) != 0 key_mask, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) out.str = f"If {'keyheld' if auto_repeat else 'keydown'} 0x{key_mask.value:X}" elif out.opcode == CheatVmOpcodeType.PauseProcess: out.str = "PauseProcess" elif out.opcode == CheatVmOpcodeType.ResumeProcess: out.str = "ResumeProcess" elif out.opcode == CheatVmOpcodeType.DebugLog: out.str = "DebugLog" # Simplified else: out.str = f"Opcode {out.opcode.name} not implemented in this script." out.size = instruction_ptr - index return out def disassemble_cheat(opcodes): """Disassembles a list of opcodes for a single cheat.""" index = 0 while index < len(opcodes): opcode_info = decode_next_opcode(opcodes, index) if not opcode_info: break raw_opcodes_list = opcodes[index : index + opcode_info.size] raw_opcodes_str = " ".join([f"{opc:08X}" for opc in raw_opcodes_list]) print(f"{raw_opcodes_str:<40} {opcode_info.str}") index += opcode_info.size def disassemble_opcodes_from_file(file_path): try: with open(file_path, 'r') as f: cheat_opcodes = [] for line in f: stripped_line = line.strip() if not stripped_line: continue if (stripped_line.startswith('[') and stripped_line.endswith(']')) or \ (stripped_line.startswith('{') and stripped_line.endswith('}')): if cheat_opcodes: disassemble_cheat(cheat_opcodes) cheat_opcodes = [] print(f"\n{stripped_line}") else: parts = stripped_line.split() for part in parts: if part: try: cheat_opcodes.append(int(part, 16)) except ValueError: # Ignore non-hex parts, could be comments pass # After the loop, process any remaining opcodes if cheat_opcodes: disassemble_cheat(cheat_opcodes) except FileNotFoundError: print(f"Error: The file '{file_path}' was not found.") except Exception as e: print(f"An unexpected error occurred: {e}") def disassemble_opcodes_from_string(opcodes_str): cheat_opcodes = [] for line in opcodes_str.splitlines(): line = line.strip() if not line: continue if line.startswith('[') and line.endswith(']'): if cheat_opcodes: disassemble_cheat(cheat_opcodes) cheat_opcodes = [] print(f"\n{line}") else: parts = line.split() for part in parts: try: cheat_opcodes.append(int(part, 16)) except ValueError: pass # Ignore non-hex parts if cheat_opcodes: disassemble_cheat(cheat_opcodes) def main(): """Main function to handle command-line arguments or interactive mode.""" if not CAPSTONE_AVAILABLE: print("Capstone library not found. Please install it with 'pip install capstone'") sys.exit(1) # If a command-line argument is provided, treat it as a file path if len(sys.argv) > 1: file_path = sys.argv[1] print(f"--- Disassembling from file: {file_path} ---") disassemble_opcodes_from_file(file_path) input("\nPress Enter to exit...") else: if len(sys.argv) != 2: print("Usage: python disassemble_cheats.py <path_to_opcode_file>") example_file = 'asm.txt' print(f"\nNo file provided. Trying with example file: '{example_file}'") try: with open(example_file, 'r'): disassemble_opcodes_from_file(example_file) except FileNotFoundError: print(f"Example file '{example_file}' not found.") print("--- Interactive Mode ---") while True: print("\nPaste your opcodes (type 'done' on a new line to finish):") opcodes_str = "" while True: try: line = input() if line.strip().lower() == 'done': break opcodes_str += line + "\n" except EOFError: break if opcodes_str.strip(): disassemble_opcodes_from_string(opcodes_str) choice = input("\nDisassemble more? (yes/no): ") if choice.strip().lower() != 'yes': break if __name__ == "__main__": main()
Then this version here i did up is just a test im doing up for him.. this has arm32 support for games that use that like Ty the tasmanian tiger HD, Mario kart 8 D pre 3.0.4, etc. so if you know the codes are arm32 instructions choose that as your architecture...
View attachment 518092Python:import sys from enum import Enum try: from capstone import Cs, CS_ARCH_ARM64, CS_ARCH_ARM, CS_MODE_ARM, CS_MODE_THUMB CAPSTONE_AVAILABLE = True except ImportError: CAPSTONE_AVAILABLE = False # Global variable to store the target architecture chosen by the user TARGET_ARCH = None # Based on source/opcode.hpp class CheatVmOpcodeType(Enum): StoreStatic = 0 BeginConditionalBlock = 1 EndConditionalBlock = 2 ControlLoop = 3 LoadRegisterStatic = 4 LoadRegisterMemory = 5 StoreStaticToAddress = 6 PerformArithmeticStatic = 7 BeginKeypressConditionalBlock = 8 PerformArithmeticRegister = 9 StoreRegisterToAddress = 10 Reserved11 = 11 ExtendedWidth = 12 BeginRegisterConditionalBlock = 0xC0 SaveRestoreRegister = 0xC1 SaveRestoreRegisterMask = 0xC2 ReadWriteStaticRegister = 0xC3 BeginExtendedKeypressConditionalBlock = 0xC4 DoubleExtendedWidth = 0xF0 PauseProcess = 0xFF0 ResumeProcess = 0xFF1 DebugLog = 0xFFF class MemoryAccessType(Enum): MainNso = 0 Heap = 1 Alias = 2 Aslr = 3 Blank = 4 class ConditionalComparisonType(Enum): GT = 1 GE = 2 LT = 3 LE = 4 EQ = 5 NE = 6 class RegisterArithmeticType(Enum): Addition = 0 Subtraction = 1 Multiplication = 2 LeftShift = 3 RightShift = 4 LogicalAnd = 5 LogicalOr = 6 LogicalNot = 7 LogicalXor = 8 None_ = 9 FloatAddition = 10 FloatMultiplication = 11 DoubleAddition = 12 DoubleMultiplication = 13 class StoreRegisterOffsetType(Enum): None_ = 0 Reg = 1 Imm = 2 MemReg = 3 MemImm = 4 MemImmReg = 5 class CompareRegisterValueType(Enum): MemoryRelAddr = 0 MemoryOfsReg = 1 RegisterRelAddr = 2 RegisterOfsReg = 3 StaticValue = 4 OtherRegister = 5 OffsetValue = 6 class SaveRestoreRegisterOpType(Enum): Restore = 0 Save = 1 ClearSaved = 2 ClearRegs = 3 class DebugLogValueType(Enum): MemoryRelAddr = 0 MemoryOfsReg = 1 RegisterRelAddr = 2 RegisterOfsReg = 3 RegisterValue = 4 CONDITION_STR = { ConditionalComparisonType.GT: ">", ConditionalComparisonType.GE: ">=", ConditionalComparisonType.LT: "<", ConditionalComparisonType.LE: "<=", ConditionalComparisonType.EQ: "==", ConditionalComparisonType.NE: "!=", } MATH_STR = { RegisterArithmeticType.Addition: "+", RegisterArithmeticType.Subtraction: "-", RegisterArithmeticType.Multiplication: "*", RegisterArithmeticType.LeftShift: "<<", RegisterArithmeticType.RightShift: ">>", RegisterArithmeticType.LogicalAnd: "&", RegisterArithmeticType.LogicalOr: "|", RegisterArithmeticType.LogicalNot: "!", RegisterArithmeticType.LogicalXor: "^", RegisterArithmeticType.None_: "", RegisterArithmeticType.FloatAddition: "+f", RegisterArithmeticType.FloatMultiplication: "*f", RegisterArithmeticType.DoubleAddition: "+d", RegisterArithmeticType.DoubleMultiplication: "*d", } OPERAND_STR = { SaveRestoreRegisterOpType.Restore: "Restore", SaveRestoreRegisterOpType.Save: "Save", SaveRestoreRegisterOpType.ClearSaved: "ClearSaved", SaveRestoreRegisterOpType.ClearRegs: "ClearRegs", } class VmInt: def __init__(self, value=0): self.value = value class CheatVmOpcode: def __init__(self): self.opcode = None self.size = 0 self.str = "" def get_next_dword(opcodes, instruction_ptr): if instruction_ptr >= len(opcodes): return None, instruction_ptr + 1 return opcodes[instruction_ptr], instruction_ptr + 1 def get_next_vm_int(opcodes, instruction_ptr, bit_width): val = VmInt() first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if first_dword is None: return None, instruction_ptr if bit_width == 1: val.value = first_dword & 0xFF elif bit_width == 2: val.value = first_dword & 0xFFFF elif bit_width == 4: val.value = first_dword elif bit_width == 8: second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if second_dword is None: return None, instruction_ptr val.value = (first_dword << 32) | second_dword else: # Invalid bit_width, but we'll assign the dword to avoid crashing. val.value = first_dword return val, instruction_ptr def mem_type_str(mem_type): if mem_type == MemoryAccessType.MainNso: return "Main" if mem_type == MemoryAccessType.Heap: return "Heap" if mem_type == MemoryAccessType.Alias: return "Alias" if mem_type == MemoryAccessType.Aslr: return "Aslr" return "" def arm64_disassemble(value, address): """ Disassembles a 4-byte value as an ARM64 instruction. ARM64 instructions are always 4 bytes. """ if not CAPSTONE_AVAILABLE: return "" md = Cs(CS_ARCH_ARM64, CS_MODE_ARM) # Ensure we always convert to 4 bytes for ARM64 instruction disassembly code = (value & 0xFFFFFFFF).to_bytes(4, byteorder='little') disassembled = [] try: for i in md.disasm(code, address): disassembled.append(f"{i.mnemonic} {i.op_str}") return "; ".join(disassembled).strip() except Exception: return "" # Return empty string if Capstone fails def arm32_disassemble(value, address): """ Disassembles a 4-byte value as an ARM32 instruction (trying ARM then Thumb). ARM32/Thumb instructions are 2 or 4 bytes. I provide 4 bytes and let Capstone handle it. """ if not CAPSTONE_AVAILABLE: return "" code = value.to_bytes(4, byteorder='little') # ARM32 instructions are 4 bytes (or 2 for Thumb, but provide 4) # Try ARM mode first md_arm = Cs(CS_ARCH_ARM, CS_MODE_ARM) disassembled = [] try: for i in md_arm.disasm(code, address): disassembled.append(f"{i.mnemonic} {i.op_str}") if disassembled: return "; ".join(disassembled).strip() except Exception: pass # Fall through to Thumb mode if ARM disassembly fails or produces nothing # If ARM mode didn't work or produced no output, try Thumb mode md_thumb = Cs(CS_ARCH_ARM, CS_MODE_THUMB) disassembled = [] try: for i in md_thumb.disasm(code, address): disassembled.append(f"{i.mnemonic} {i.op_str}") if disassembled: return "; ".join(disassembled).strip() except Exception: pass return "" # Return empty string if neither ARM nor Thumb can disassemble def decode_next_opcode(opcodes, index): instruction_ptr = index first_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) if first_dword is None: return None out = CheatVmOpcode() opcode_val = (first_dword >> 28) & 0xF if opcode_val >= CheatVmOpcodeType.ExtendedWidth.value: opcode_val = (opcode_val << 4) | ((first_dword >> 24) & 0xF) if opcode_val >= CheatVmOpcodeType.DoubleExtendedWidth.value: opcode_val = (opcode_val << 4) | ((first_dword >> 20) & 0xF) try: out.opcode = CheatVmOpcodeType(opcode_val) except ValueError: out.str = f"Unknown opcode: {hex(opcode_val)}" out.size = 1 return out if out.opcode == CheatVmOpcodeType.StoreStatic: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) offset_register = (first_dword >> 16) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) # Assuming rel_address high 24 bits are from first_dword & 0xFFFFFF # and low 32 bits from second_dword. rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) out.str = f"[{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] = 0x{value.value:X}" # Determine disassembly based on bit_width and global TARGET_ARCH if CAPSTONE_AVAILABLE: if bit_width == 8: # 8-byte value: Disassemble both halves based on TARGET_ARCH high_32_bits = (value.value >> 32) & 0xFFFFFFFF low_32_bits = value.value & 0xFFFFFFFF combined_asm = [] if TARGET_ARCH == "ARM64": asm_low = arm64_disassemble(low_32_bits, rel_address) asm_high = arm64_disassemble(high_32_bits, rel_address + 4) arch_label = "ARM64" elif TARGET_ARCH == "ARM32": asm_low = arm32_disassemble(low_32_bits, rel_address) asm_high = arm32_disassemble(high_32_bits, rel_address + 4) arch_label = "ARM32" else: # Should not happen if TARGET_ARCH is set correctly asm_low = "" asm_high = "" arch_label = "UNKNOWN ARCH" if asm_low: combined_asm.append(f"[{hex(rel_address)}] {asm_low}") if asm_high: combined_asm.append(f"[{hex(rel_address + 4)}] {asm_high}") if combined_asm: out.str += f" ({arch_label}: {'; '.join(combined_asm)})" else: out.str += f" ({arch_label}: No disassembly)" elif bit_width == 4: # 4-byte value: Use TARGET_ARCH to decide if TARGET_ARCH == "ARM64": asm = arm64_disassemble(value.value, rel_address) if asm: out.str += f" (ARM64: {asm})" elif TARGET_ARCH == "ARM32": asm = arm32_disassemble(value.value, rel_address) if asm: out.str += f" (ARM32: {asm})" else: # Should not happen if TARGET_ARCH is set correctly out.str += " (Disassembly type not determined)" else: out.str += " (Disassembly skipped - Capstone not available)" elif out.opcode == CheatVmOpcodeType.BeginConditionalBlock: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF) include_ofs_reg = ((first_dword >> 12) & 0xF) != 0 ofs_reg_index = (first_dword >> 8) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword # Adjusted to mask 24 bits value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) ofs_reg_str = f"R{ofs_reg_index}+" if include_ofs_reg else "" out.str = f"If [{mem_type_str(mem_type)}+{ofs_reg_str}0x{rel_address:010X}] {CONDITION_STR.get(cond_type, '?')} 0x{value.value:X}" elif out.opcode == CheatVmOpcodeType.EndConditionalBlock: end_type = (first_dword >> 24) & 0xF out.str = "Else" if end_type == 1 else "Endif" elif out.opcode == CheatVmOpcodeType.ControlLoop: start_loop = ((first_dword >> 24) & 0xF) == 0 reg_index = (first_dword >> 16) & 0xF if start_loop: num_iters, instruction_ptr = get_next_dword(opcodes, instruction_ptr) out.str = f"Loop Start R{reg_index} = {num_iters}" else: out.str = "Loop stop" elif out.opcode == CheatVmOpcodeType.LoadRegisterStatic: reg_index = (first_dword >> 16) & 0xF value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit value out.str = f"R{reg_index} = 0x{value.value:016X}" elif out.opcode == CheatVmOpcodeType.LoadRegisterMemory: bit_width = (first_dword >> 24) & 0xF mem_type = MemoryAccessType((first_dword >> 20) & 0xF) reg_index = (first_dword >> 16) & 0xF load_from_reg = (first_dword >> 12) & 0xF offset_register = (first_dword >> 8) & 0xF second_dword, instruction_ptr = get_next_dword(opcodes, instruction_ptr) rel_address = ((first_dword & 0xFFFFFF) << 32) | second_dword # Adjusted to mask 24 bits if load_from_reg == 3: out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+R{offset_register}+0x{rel_address:010X}] W={bit_width}" elif load_from_reg: src_reg = reg_index if load_from_reg == 1 else offset_register out.str = f"R{reg_index} = [R{src_reg}+0x{rel_address:010X}] W={bit_width}" else: out.str = f"R{reg_index} = [{mem_type_str(mem_type)}+0x{rel_address:010X}] W={bit_width}" elif out.opcode == CheatVmOpcodeType.StoreStaticToAddress: bit_width = (first_dword >> 24) & 0xF reg_index = (first_dword >> 16) & 0xF increment_reg = ((first_dword >> 12) & 0xF) != 0 add_offset_reg = ((first_dword >> 8) & 0xF) != 0 offset_reg_index = (first_dword >> 4) & 0xF value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) # 64-bit if add_offset_reg: out.str = f"[R{reg_index}+R{offset_reg_index}] = 0x{value.value:016X} W={bit_width}" else: out.str = f"[R{reg_index}] = 0x{value.value:016X} W={bit_width}" if increment_reg: out.str += f" R{reg_index} += {bit_width}" elif out.opcode == CheatVmOpcodeType.PerformArithmeticStatic: bit_width = (first_dword >> 24) & 0xF reg_index = (first_dword >> 16) & 0xF math_type = RegisterArithmeticType((first_dword >> 12) & 0xF) value, instruction_ptr = get_next_dword(opcodes, instruction_ptr) out.str = f"R{reg_index} = R{reg_index} {MATH_STR.get(math_type, '?')} 0x{value:X} W={bit_width}" elif out.opcode == CheatVmOpcodeType.BeginKeypressConditionalBlock: key_mask = first_dword & 0x0FFFFFFF out.str = f"If keyheld 0x{key_mask:X}" elif out.opcode == CheatVmOpcodeType.PerformArithmeticRegister: bit_width = (first_dword >> 24) & 0xF math_type = RegisterArithmeticType((first_dword >> 20) & 0xF) dst_reg_index = (first_dword >> 16) & 0xF src_reg_1_index = (first_dword >> 12) & 0xF has_immediate = ((first_dword >> 8) & 0xF) != 0 if has_immediate: value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} 0x{value.value:X} W={bit_width}" else: src_reg_2_index = (first_dword >> 4) & 0xF out.str = f"R{dst_reg_index} = R{src_reg_1_index} {MATH_STR.get(math_type, '?')} R{src_reg_2_index} W={bit_width}" elif out.opcode == CheatVmOpcodeType.StoreRegisterToAddress: bit_width = (first_dword >> 24) & 0xF str_reg_index = (first_dword >> 20) & 0xF addr_reg_index = (first_dword >> 16) & 0xF increment_reg = ((first_dword >> 12) & 0xF) != 0 ofs_type = StoreRegisterOffsetType((first_dword >> 8) & 0xF) ofs_reg_index = (first_dword >> 4) & 0xF addr_str = "" if ofs_type == StoreRegisterOffsetType.None_: addr_str = f"[R{addr_reg_index}]" elif ofs_type == StoreRegisterOffsetType.Reg: addr_str = f"[R{addr_reg_index}+R{ofs_reg_index}]" elif ofs_type == StoreRegisterOffsetType.Imm: rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]" elif ofs_type == StoreRegisterOffsetType.MemReg: mem_type = MemoryAccessType(ofs_reg_index) addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}]" elif ofs_type == StoreRegisterOffsetType.MemImm: mem_type = MemoryAccessType(ofs_reg_index) rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]" elif ofs_type == StoreRegisterOffsetType.MemImmReg: mem_type = MemoryAccessType(ofs_reg_index) rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) # 32-bit addr_str = f"[{mem_type_str(mem_type)}+R{addr_reg_index}+0x{rel_address.value:X}]" out.str = f"{addr_str} = R{str_reg_index} W={bit_width}" if increment_reg: out.str += f" R{addr_reg_index} += {bit_width}" elif out.opcode == CheatVmOpcodeType.BeginRegisterConditionalBlock: bit_width = (first_dword >> 20) & 0xF cond_type = ConditionalComparisonType((first_dword >> 16) & 0xF) val_reg_index = (first_dword >> 12) & 0xF comp_type = CompareRegisterValueType((first_dword >> 8) & 0xF) comp_str = "" if comp_type == CompareRegisterValueType.StaticValue: value, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, bit_width) comp_str = f"0x{value.value:X}" elif comp_type == CompareRegisterValueType.OtherRegister: other_reg_index = (first_dword >> 4) & 0xF comp_str = f"R{other_reg_index}" else: # Memory access mem_type = MemoryAccessType((first_dword >> 4) & 0xF) if comp_type in [CompareRegisterValueType.MemoryRelAddr, CompareRegisterValueType.RegisterRelAddr]: rel_address, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 4) if comp_type == CompareRegisterValueType.MemoryRelAddr: comp_str = f"[{mem_type_str(mem_type)}+0x{rel_address.value:X}]" else: # RegisterRelAddr addr_reg_index = (first_dword >> 4) & 0xF comp_str = f"[R{addr_reg_index}+0x{rel_address.value:X}]" else: # MemoryOfsReg, RegisterOfsReg ofs_reg_index = first_dword & 0xF if comp_type == CompareRegisterValueType.MemoryOfsReg: comp_str = f"[{mem_type_str(mem_type)}+R{ofs_reg_index}]" else: # RegisterOfsReg addr_reg_index = (first_dword >> 4) & 0xF comp_str = f"[R{addr_reg_index}+R{ofs_reg_index}]" out.str = f"If R{val_reg_index} {CONDITION_STR.get(cond_type, '?')} {comp_str}" elif out.opcode == CheatVmOpcodeType.SaveRestoreRegister: dst_index = (first_dword >> 16) & 0xF src_index = (first_dword >> 8) & 0xF op_type = SaveRestoreRegisterOpType((first_dword >> 4) & 0xF) out.str = f"SaveRestoreRegister dst={dst_index} src={src_index} {OPERAND_STR.get(op_type, '?')}" elif out.opcode == CheatVmOpcodeType.SaveRestoreRegisterMask: op_type = SaveRestoreRegisterOpType((first_dword >> 20) & 0xF) mask = first_dword & 0xFFFF out.str = f"SaveRestoreRegisterMask {OPERAND_STR.get(op_type, '?')} mask=0x{mask:04X}" elif out.opcode == CheatVmOpcodeType.ReadWriteStaticRegister: static_idx = (first_dword >> 4) & 0xFF idx = first_dword & 0xF out.str = f"ReadWriteStaticRegister static_idx=0x{static_idx:X} idx={idx}" elif out.opcode == CheatVmOpcodeType.BeginExtendedKeypressConditionalBlock: auto_repeat = ((first_dword >> 20) & 0xF) != 0 key_mask, instruction_ptr = get_next_vm_int(opcodes, instruction_ptr, 8) out.str = f"If {'keyheld' if auto_repeat else 'keydown'} 0x{key_mask.value:X}" elif out.opcode == CheatVmOpcodeType.PauseProcess: out.str = "PauseProcess" elif out.opcode == CheatVmOpcodeType.ResumeProcess: out.str = "ResumeProcess" elif out.opcode == CheatVmOpcodeType.DebugLog: out.str = "DebugLog" # Simplified else: out.str = f"Opcode {out.opcode.name} not implemented in this script." out.size = instruction_ptr - index return out def disassemble_cheat(opcodes): """Disassembles a list of opcodes for a single cheat.""" index = 0 while index < len(opcodes): opcode_info = decode_next_opcode(opcodes, index) if not opcode_info: break raw_opcodes_list = opcodes[index : index + opcode_info.size] raw_opcodes_str = " ".join([f"{opc:08X}" for opc in raw_opcodes_list]) print(f"{raw_opcodes_str:<40} {opcode_info.str}") index += opcode_info.size def disassemble_opcodes_from_file(file_path): global TARGET_ARCH # Declare intent to modify global variable if TARGET_ARCH is None: # If not set by command line, prompt TARGET_ARCH = get_target_arch_from_user() try: with open(file_path, 'r') as f: cheat_opcodes = [] for line in f: stripped_line = line.strip() if not stripped_line: continue if (stripped_line.startswith('[') and stripped_line.endswith(']')) or \ (stripped_line.startswith('{') and stripped_line.endswith('}')): if cheat_opcodes: disassemble_cheat(cheat_opcodes) cheat_opcodes = [] print(f"\n{stripped_line}") else: parts = stripped_line.split() for part in parts: if part: try: cheat_opcodes.append(int(part, 16)) except ValueError: # Ignore non-hex parts, could be comments pass # After the loop, process any remaining opcodes if cheat_opcodes: disassemble_cheat(cheat_opcodes) except FileNotFoundError: print(f"Error: The file '{file_path}' was not found.") except Exception as e: print(f"An unexpected error occurred: {e}") def disassemble_opcodes_from_string(opcodes_str): cheat_opcodes = [] for line in opcodes_str.splitlines(): line = line.strip() if not line: continue if line.startswith('[') and line.endswith(']'): if cheat_opcodes: disassemble_cheat(cheat_opcodes) cheat_opcodes = [] print(f"\n{line}") else: parts = line.split() for part in parts: try: cheat_opcodes.append(int(part, 16)) except ValueError: pass # Ignore non-hex parts if cheat_opcodes: disassemble_cheat(cheat_opcodes) def get_target_arch_from_user(): while True: choice = input("Enter target architecture (ARM32/ARM64): ").strip().upper() if choice in ["ARM32", "ARM64"]: return choice else: print("Invalid choice. Please enter 'ARM32' or 'ARM64'.") def main(): """Main function to handle command-line arguments or interactive mode.""" global TARGET_ARCH if not CAPSTONE_AVAILABLE: print("Capstone library not found. Please install it with 'pip install capstone'") sys.exit(1) file_path_arg = None for i, arg in enumerate(sys.argv[1:]): if arg.lower() == "--arch" and i + 1 < len(sys.argv[1:]): arch_arg = sys.argv[i+2].strip().upper() if arch_arg in ["ARM32", "ARM64"]: TARGET_ARCH = arch_arg print(f"Target architecture set to: {TARGET_ARCH} (from command line)") else: print(f"Warning: Invalid architecture '{arch_arg}' provided via --arch. Will prompt.") sys.argv.pop(i+1) sys.argv.pop(i+1) break if len(sys.argv) > 1: file_path_arg = sys.argv[1] if TARGET_ARCH is None: TARGET_ARCH = get_target_arch_from_user() print(f"\nDisassembly will target: {TARGET_ARCH}") if file_path_arg: print(f"--- Disassembling from file: {file_path_arg} ---") disassemble_opcodes_from_file(file_path_arg) input("\nPress Enter to exit...") else: if len(sys.argv) != 2: print("Usage: python ASMdisassemble_cheats.py <path_to_opcode_file>") example_file = 'asm.txt' print(f"\nNo file provided. Trying with example file: '{example_file}'") try: with open(example_file, 'r'): disassemble_opcodes_from_file(example_file) except FileNotFoundError: print(f"Example file '{example_file}' not found.") print("--- Interactive Mode ---") while True: print("\nPaste your opcodes (type 'done' on a new line to finish):") opcodes_str = "" while True: try: line = input() if line.strip().lower() == 'done': break opcodes_str += line + "\n" except EOFError: break if opcodes_str.strip(): disassemble_opcodes_from_string(opcodes_str) choice = input("\nDisassemble more? (yes/no): ") if choice.strip().lower() != 'yes': break if __name__ == "__main__": main()
View attachment 518093
View attachment 518094
import sys
import re
import struct
from enum import Enum
try:
from keystone import Ks, KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN
KEYSTONE_AVAILABLE = True
except ImportError:
KEYSTONE_AVAILABLE = False
print("FATAL ERROR: Keystone library not found. Please install it with 'pip install keystone-engine'", file=sys.stderr)
sys.exit(1)
class CheatVmOpcodeType(Enum):
StoreStatic = 0
BeginConditionalBlock = 1
EndConditionalBlock = 2
ControlLoop = 3
LoadRegisterStatic = 4
LoadRegisterMemory = 5
StoreStaticToAddress = 6
PerformArithmeticStatic = 7
BeginKeypressConditionalBlock = 8
PerformArithmeticRegister = 9
StoreRegisterToAddress = 10
Reserved11 = 11
ExtendedWidth = 12
BeginRegisterConditionalBlock = 0xC0
SaveRestoreRegister = 0xC1
SaveRestoreRegisterMask = 0xC2
ReadWriteStaticRegister = 0xC3
BeginExtendedKeypressConditionalBlock = 0xC4
DoubleExtendedWidth = 0xF0
PauseProcess = 0xFF0
ResumeProcess = 0xFF1
DebugLog = 0xFFF
class MemoryAccessType(Enum):
MainNso = 0
Heap = 1
Alias = 2
Aslr = 3
def mem_type_from_str(s):
s_lower = s.lower() if s else ""
if s_lower == "main": return MemoryAccessType.MainNso
if s_lower == "heap": return MemoryAccessType.Heap
if s_lower == "alias": return MemoryAccessType.Alias
if s_lower == "aslr": return MemoryAccessType.Aslr
if not s:
print(f"Warning: No memory type specified in input. Defaulting to MainNso.", file=sys.stderr)
else:
print(f"Warning: Unrecognized memory type string '{s}'. Defaulting to MainNso.", file=sys.stderr)
return MemoryAccessType.MainNso
def assemble_instruction(instruction, addr=0):
try:
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
encoding_raw, count = ks.asm(instruction, addr)
if isinstance(encoding_raw, list):
encoding_bytes = bytes(encoding_raw)
elif isinstance(encoding_raw, bytes):
encoding_bytes = encoding_raw
else:
print(f"Error: Unexpected type for Keystone encoding: {type(encoding_raw)}", file=sys.stderr)
return None, "Keystone returned unexpected type."
if not encoding_bytes and count == 0:
print(f"Warning: Keystone assembled '{instruction}' but returned no bytes (empty encoding list/bytes).", file=sys.stderr)
return None, "Empty encoding returned by Keystone."
return encoding_bytes, None
except Exception as e:
print(f"Error: Exception during Keystone assembly of '{instruction}' at 0x{addr:X}: {e}", file=sys.stderr)
return None, str(e)
def assemble_from_string(input_str):
output_lines = []
current_cheat_name = ""
processed_lines_count = 0
for line_num, line in enumerate(input_str.splitlines(), 1):
line_stripped = line.strip()
if not line_stripped:
continue
if line_stripped.startswith('[') and line_stripped.endswith(']') and not '=' in line_stripped:
if current_cheat_name:
output_lines.append("")
current_cheat_name = line_stripped
output_lines.append(current_cheat_name)
continue
match = re.match(r'\[(?:(\w+)\+)?R(\d+)\+0x([0-9A-Fa-f]+)\]=(.*)', line_stripped)
if not match:
print(f"Warning (Line {line_num}): Line format not recognized, skipping: '{line_stripped}'", file=sys.stderr)
continue
mem_type_str_raw, reg_str, addr_str, value_str_raw = match.groups()
mem_type = mem_type_from_str(mem_type_str_raw)
register_index = int(reg_str)
absolute_address = int(addr_str, 16)
value_to_encode = value_str_raw.strip()
relative_address = absolute_address
val = None
bit_width = 4
if value_to_encode.lower().startswith('flt:'):
float_str = value_to_encode[4:]
try:
float_val = float(float_str)
packed_float_bytes = struct.pack('<f', float_val)
val = int.from_bytes(packed_float_bytes, 'little')
bit_width = 4
except (ValueError, struct.error) as e:
print(f"Error (Line {line_num}): Could not parse float value '{float_str}'. Error: {e}. Skipping line: '{line_stripped}'", file=sys.stderr)
continue
else:
instructions = [i.strip() for i in value_to_encode.split(';') if i.strip()]
if not instructions:
print(f"Warning (Line {line_num}): No instruction found to assemble in line: '{line_stripped}'. Skipping.", file=sys.stderr)
continue
if len(instructions) > 2:
print(f"Warning (Line {line_num}): More than two instructions on a line are not supported for Type 0: '{line_stripped}'. Skipping.", file=sys.stderr)
continue
bit_width = 4 * len(instructions)
assembled_bytes_list = []
current_instr_addr = relative_address
assembly_failed = False
for instr_idx, instr in enumerate(instructions):
encoding_bytes, error = assemble_instruction(instr, current_instr_addr)
if encoding_bytes is None:
assembly_failed = True
break
if len(encoding_bytes) != 4:
print(f"Error (Line {line_num}): Assembled instruction '{instr}' is not 4 bytes ({len(encoding_bytes)} bytes). Keystone might be misbehaving. Skipping line: '{line_stripped}'", file=sys.stderr)
assembly_failed = True
break
assembled_bytes_list.append(encoding_bytes)
current_instr_addr += 4
if assembly_failed:
continue
if len(instructions) == 1:
val = int.from_bytes(assembled_bytes_list[0], 'little')
else:
val1 = int.from_bytes(assembled_bytes_list[0], 'little')
val2 = int.from_bytes(assembled_bytes_list[1], 'little')
val = (val2 << 32) | val1
if val is not None:
if not (bit_width == 4 or bit_width == 8):
print(f"Error (Line {line_num}): Invalid bit_width {bit_width}. Must be 4 or 8. Skipping line: '{line_stripped}'", file=sys.stderr)
continue
if not (0 <= register_index <= 15):
print(f"Error (Line {line_num}): Invalid register index {register_index}. Must be 0-15. Skipping line: '{line_stripped}'", file=sys.stderr)
continue
first_dword_val = 0x00000000
first_dword_val |= (bit_width & 0xF) << 24
first_dword_val |= (mem_type.value & 0xF) << 20
first_dword_val |= (register_index & 0xF) << 16
first_dword_val |= ((relative_address >> 32) & 0xFF)
addr_lower_32 = relative_address & 0xFFFFFFFF
if bit_width == 8:
val_lower_32 = val & 0xFFFFFFFF
val_upper_32 = (val >> 32) & 0xFFFFFFFF
output_lines.append(f"{first_dword_val:08X} {addr_lower_32:08X} {val_upper_32:08X} {val_lower_32:08X}")
else:
output_lines.append(f"{first_dword_val:08X} {addr_lower_32:08X} {val:08X}")
processed_lines_count += 1
if processed_lines_count == 0 and not output_lines:
print("\n--- No valid cheat lines were processed. Check your input format and any errors above. ---", file=sys.stderr)
elif processed_lines_count > 0:
print(f"\n--- Successfully processed {processed_lines_count} lines. ---", file=sys.stderr)
return "\n".join(output_lines)
def main():
try:
ks_test = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
test_instr = "mov x0, #1"
test_encoding_raw, test_count = ks_test.asm(test_instr)
if isinstance(test_encoding_raw, list):
test_encoding_bytes = bytes(test_encoding_raw)
elif isinstance(test_encoding_raw, bytes):
test_encoding_bytes = test_encoding_raw
else:
print(f"FATAL ERROR: Keystone basic test returned unexpected type: {type(test_encoding_raw)}", file=sys.stderr)
sys.exit(1)
if not test_encoding_bytes or test_count == 0:
print(f"FATAL ERROR: Keystone failed basic assembly test for '{test_instr}'. Encoding: {test_encoding_bytes}, Count: {test_count}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"FATAL ERROR: Keystone library initialized but failed basic test with exception: {e}", file=sys.stderr)
sys.exit(1)
if len(sys.argv) > 1:
file_path = sys.argv[1]
try:
with open(file_path, 'r') as f:
input_str = f.read()
output_str = assemble_from_string(input_str)
print(output_str)
except FileNotFoundError:
print(f"Error: File not found '{file_path}'", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"FATAL ERROR: An unexpected error occurred during file processing: {e}", file=sys.stderr)
sys.exit(1)
else:
print("--- Interactive Mode (ARM64 to Type 0 Converter) ---", file=sys.stderr)
print("Enter ARM64 assembly-like cheat lines (e.g., [Main+R0+0x100000000]= mov x0, #0):", file=sys.stderr)
print("Type 'done' on a new line to finish.", file=sys.stderr)
input_lines = []
while True:
try:
line = input()
if line.strip().lower() == 'done':
break
input_lines.append(line)
except EOFError:
break
input_str = "\n".join(input_lines)
if input_str.strip():
output_str = assemble_from_string(input_str)
print("\n--- Converted Type 0 Opcodes ---")
print(output_str)
else:
print("No input provided. Exiting interactive mode.", file=sys.stderr)
if __name__ == "__main__":
main()
input("\nPress Enter to exit...")
