安卓PSP模拟器 PPSSPP金手指 您所在的位置:网站首页 psp安卓模拟器金手指 安卓PSP模拟器 PPSSPP金手指

安卓PSP模拟器 PPSSPP金手指

2023-10-19 23:49| 来源: 网络整理| 查看: 265

PPSSPP金手指使用

1,网上找到对应的psp游戏cmf金手指,例如S ULJM-05035 2,粘贴金手指到记事本,保存为UTF-8编码、ini后缀,文件名去掉“S ”和“-”,最终为ULJM05035.ini3,打开安卓机器上PSP文件夹,新建Cheats文件夹,复制ULJM05035.ini进去 3,启动安卓PPSSPP模拟器选“游戏设置”-“系统设置”-“开启金手指”

psp Cw 金手指解析 CheatOperation CWCheatEngine::InterpretNextCwCheat(const CheatCode &cheat, size_t &i) { const CheatLine &line1 = cheat.lines[i++]; const uint32_t &arg = line1.part2; // Filled as needed. u32 addr; int type = line1.part1 >> 28; switch (type) { case 0x0: // Write 8-bit data (up to 4 bytes.) addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (arg & 0xFFFF0000) return { CheatOp::Write, addr, 4, arg }; else if (arg & 0x0000FF00) return { CheatOp::Write, addr, 2, arg }; else return { CheatOp::Write, addr, 1, arg }; case 0x1: // Write 16-bit data. addr = GetAddress(line1.part1 & 0x0FFFFFFF); return { CheatOp::Write, addr, 2, arg }; case 0x2: // Write 32-bit data. addr = GetAddress(line1.part1 & 0x0FFFFFFF); return { CheatOp::Write, addr, 4, arg }; case 0x3: // Increment/decrement data. addr = GetAddress(arg & 0x0FFFFFFF); switch ((line1.part1 >> 20) & 0xF) { case 1: return { CheatOp::Add, addr, 1, line1.part1 & 0xFF }; case 2: return { CheatOp::Subtract, addr, 1, line1.part1 & 0xFF }; case 3: return { CheatOp::Add, addr, 2, line1.part1 & 0xFFFF }; case 4: return { CheatOp::Subtract, addr, 2, line1.part1 & 0xFFFF }; case 5: if (i < cheat.lines.size()) return { CheatOp::Add, addr, 4, cheat.lines[i++].part1 }; return { CheatOp::Invalid }; case 6: if (i < cheat.lines.size()) return { CheatOp::Subtract, addr, 4, cheat.lines[i++].part1 }; return { CheatOp::Invalid }; default: return { CheatOp::Invalid }; } break; case 0x4: // 32-bit multi-write patch data. addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (i < cheat.lines.size()) { const CheatLine &line2 = cheat.lines[i++]; CheatOperation op = { CheatOp::MultiWrite, addr, 4, line2.part1 }; op.multiWrite.count = arg >> 16; op.multiWrite.step = (arg & 0xFFFF) * 4; op.multiWrite.add = line2.part2; return op; } return { CheatOp::Invalid }; case 0x5: // Memcpy command. addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (i < cheat.lines.size()) { const CheatLine &line2 = cheat.lines[i++]; CheatOperation op = { CheatOp::CopyBytesFrom, addr, 0, arg }; op.copyBytesFrom.destAddr = GetAddress(line2.part1 & 0x0FFFFFFF); return op; } return { CheatOp::Invalid }; case 0x6: // Pointer commands. addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (i < cheat.lines.size()) { const CheatLine &line2 = cheat.lines[i++]; int count = (line2.part1 & 0xFFFF) - 1; // Validate lines to process - make sure we stay inside cheat.lines. if (i + count > cheat.lines.size()) return { CheatOp::Invalid }; CheatOperation op = { CheatOp::CwCheatPointerCommands, addr, 0, arg }; op.pointerCommands.offset = (int)line2.part2; // TODO: Verify sign handling. Is this really supposed to sign extend? op.pointerCommands.baseOffset = ((int)line2.part1 >> 20) * 4; op.pointerCommands.count = count; op.pointerCommands.type = (line2.part1 >> 16) & 0xF; return op; } return { CheatOp::Invalid }; case 0x7: // Boolean data operations. addr = GetAddress(line1.part1 & 0x0FFFFFFF); switch (arg >> 16) { case 0x0000: // 8-bit OR. return { CheatOp::Or, addr, 1, arg & 0xFF }; case 0x0001: // 16-bit OR. return { CheatOp::Or, addr, 2, arg & 0xFFFF }; case 0x0002: // 8-bit AND. return { CheatOp::And, addr, 1, arg & 0xFF }; case 0x0003: // 16-bit AND. return { CheatOp::And, addr, 2, arg & 0xFFFF }; case 0x0004: // 8-bit XOR. return { CheatOp::Xor, addr, 1, arg & 0xFF }; case 0x0005: // 16-bit XOR. return { CheatOp::Xor, addr, 2, arg & 0xFFFF }; } return { CheatOp::Invalid }; case 0x8: // 8-bit or 16-bit multi-write patch data. addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (i < cheat.lines.size()) { const CheatLine &line2 = cheat.lines[i++]; const bool is8Bit = (line2.part1 & 0xFFFF0000) == 0; const uint32_t val = is8Bit ? (line2.part1 & 0xFF) : (line2.part1 & 0xFFFF); CheatOperation op = { CheatOp::MultiWrite, addr, is8Bit ? 1 : 2, val }; op.multiWrite.count = arg >> 16; op.multiWrite.step = (arg & 0xFFFF) * (is8Bit ? 1 : 2); op.multiWrite.add = line2.part2; return op; } return { CheatOp::Invalid }; case 0xB: // Delay command. return { CheatOp::Delay, 0, 0, arg }; case 0xC: // 32-bit equal check / code stopper. addr = GetAddress(line1.part1 & 0x0FFFFFFF); return { CheatOp::Assert, addr, 4, arg }; case 0xD: // Line skip tests & joker codes. switch (arg >> 28) { case 0x0: // 16-bit next line skip test. case 0x2: // 8-bit next line skip test. addr = GetAddress(line1.part1 & 0x0FFFFFFF); { const bool is8Bit = (arg >> 28) == 0x2; const uint32_t val = is8Bit ? (arg & 0xFF) : (arg & 0xFFFF); CheatOp opcode; switch ((arg >> 20) & 0xF) { case 0x0: opcode = CheatOp::IfEqual; break; case 0x1: opcode = CheatOp::IfNotEqual; break; case 0x2: opcode = CheatOp::IfLess; break; case 0x3: opcode = CheatOp::IfGreater; break; default: return { CheatOp::Invalid }; } CheatOperation op = { opcode, addr, is8Bit ? 1 : 2, val }; op.ifTypes.skip = 1; return op; } case 0x1: // Joker code - button pressed. case 0x3: // Inverse joker code - button not pressed. { bool pressed = (arg >> 28) == 0x1; CheatOperation op = { pressed ? CheatOp::IfPressed : CheatOp::IfNotPressed, 0, 0, arg & 0x0FFFFFFF }; op.ifTypes.skip = (line1.part1 & 0xFF) + 1; return op; } case 0x4: // Adress equal test. case 0x5: // Address not equal test. case 0x6: // Address less than test. case 0x7: // Address greater than test. addr = GetAddress(line1.part1 & 0x0FFFFFFF); if (i < cheat.lines.size()) { const CheatLine &line2 = cheat.lines[i++]; const int sz = 1 > 28) { case 0x4: opcode = CheatOp::IfAddrEqual; break; case 0x5: opcode = CheatOp::IfAddrNotEqual; break; case 0x6: opcode = CheatOp::IfAddrLess; break; case 0x7: opcode = CheatOp::IfAddrGreater; break; default: return { CheatOp::Invalid }; } CheatOperation op = { opcode, addr, sz, 0 }; op.ifAddrTypes.skip = line2.part1; op.ifAddrTypes.compareAddr = GetAddress(arg & 0x0FFFFFFF); return op; } return { CheatOp::Invalid }; default: return { CheatOp::Invalid }; } case 0xE: // Multiple line skip tests. addr = GetAddress(arg & 0x0FFFFFFF); { const bool is8Bit = (line1.part1 >> 24) == 0xE1; const uint32_t val = is8Bit ? (line1.part1 & 0xFF) : (line1.part1 & 0xFFFF); CheatOp opcode; switch (arg >> 28) { case 0x0: opcode = CheatOp::IfEqual; break; case 0x1: opcode = CheatOp::IfNotEqual; break; case 0x2: opcode = CheatOp::IfLess; break; case 0x3: opcode = CheatOp::IfGreater; break; default: return { CheatOp::Invalid }; } CheatOperation op = { opcode, addr, is8Bit ? 1 : 2, val }; op.ifTypes.skip = (line1.part1 >> 16) & (is8Bit ? 0xFF : 0xFFF); return op; } default: return { CheatOp::Invalid }; } } void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, size_t &i) { switch (op.op) { case CheatOp::Invalid: i = cheat.lines.size(); break; case CheatOp::Noop: break; case CheatOp::Write: if (Memory::IsValidAddress(op.addr)) { InvalidateICache(op.addr, 4); if (op.sz == 1) Memory::Write_U8((u8)op.val, op.addr); else if (op.sz == 2) Memory::Write_U16((u16)op.val, op.addr); else if (op.sz == 4) Memory::Write_U32((u32)op.val, op.addr); } break; case CheatOp::Add: ApplyMemoryOperator(op, [](uint32_t a, uint32_t b) { return a + b; }); break; case CheatOp::Subtract: ApplyMemoryOperator(op, [](uint32_t a, uint32_t b) { return a - b; }); break; case CheatOp::Or: ApplyMemoryOperator(op, [](uint32_t a, uint32_t b) { return a | b; }); break; case CheatOp::And: ApplyMemoryOperator(op, [](uint32_t a, uint32_t b) { return a & b; }); break; case CheatOp::Xor: ApplyMemoryOperator(op, [](uint32_t a, uint32_t b) { return a ^ b; }); break; case CheatOp::MultiWrite: if (Memory::IsValidAddress(op.addr)) { InvalidateICache(op.addr, op.multiWrite.count * op.multiWrite.step + op.sz); uint32_t data = op.val; uint32_t addr = op.addr; for (uint32_t a = 0; a < op.multiWrite.count; a++) { if (Memory::IsValidAddress(addr)) { if (op.sz == 1) Memory::Write_U8((u8)data, addr); else if (op.sz == 2) Memory::Write_U16((u16)data, addr); else if (op.sz == 4) Memory::Write_U32((u32)data, addr); } addr += op.multiWrite.step; data += op.multiWrite.add; } } break; case CheatOp::CopyBytesFrom: if (Memory::IsValidRange(op.addr, op.val) && Memory::IsValidRange(op.copyBytesFrom.destAddr, op.val)) { InvalidateICache(op.addr, op.val); InvalidateICache(op.copyBytesFrom.destAddr, op.val); Memory::MemcpyUnchecked(op.copyBytesFrom.destAddr, op.addr, op.val); } break; case CheatOp::Delay: // TODO: Not supported. break; case CheatOp::Assert: if (Memory::IsValidAddress(op.addr)) { InvalidateICache(op.addr, 4); if (Memory::Read_U32(op.addr) != op.val) { i = cheat.lines.size(); } } break; case CheatOp::IfEqual: if (!TestIf(op, [](int a, int b) { return a == b; })) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::IfNotEqual: if (!TestIf(op, [](int a, int b) { return a != b; })) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::IfLess: if (!TestIf(op, [](int a, int b) { return a < b; })) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::IfGreater: if (!TestIf(op, [](int a, int b) { return a > b; })) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::IfAddrEqual: if (!TestIfAddr(op, [](int a, int b) { return a == b; })) { i += (size_t)op.ifAddrTypes.skip; } break; case CheatOp::IfAddrNotEqual: if (!TestIfAddr(op, [](int a, int b) { return a != b; })) { i += (size_t)op.ifAddrTypes.skip; } break; case CheatOp::IfAddrLess: if (!TestIfAddr(op, [](int a, int b) { return a < b; })) { i += (size_t)op.ifAddrTypes.skip; } break; case CheatOp::IfAddrGreater: if (!TestIfAddr(op, [](int a, int b) { return a > b; })) { i += (size_t)op.ifAddrTypes.skip; } break; case CheatOp::IfPressed: // Button Code // SELECT 0x00000001 // START 0x00000008 // DPAD UP 0x00000010 // DPAD RIGHT 0x00000020 // DPAD DOWN 0x00000040 // DPAD LEFT 0x00000080 // L TRIGGER 0x00000100 // R TRIGGER 0x00000200 // TRIANGLE 0x00001000 // CIRCLE 0x00002000 // CROSS 0x00004000 // SQUARE 0x00008000 // HOME 0x00010000 // HOLD 0x00020000 // WLAN 0x00040000 // REMOTE HOLD 0x00080000 // VOLUME UP 0x00100000 // VOLUME DOWN 0x00200000 // SCREEN 0x00400000 // NOTE 0x00800000 if ((__CtrlPeekButtons() & op.val) != op.val) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::IfNotPressed: if ((__CtrlPeekButtons() & op.val) == op.val) { i += (size_t)op.ifTypes.skip; } break; case CheatOp::CwCheatPointerCommands: { InvalidateICache(op.addr + op.pointerCommands.baseOffset, 4); u32 base = Memory::Read_U32(op.addr + op.pointerCommands.baseOffset); u32 val = op.val; int type = op.pointerCommands.type; for (int a = 0; a < op.pointerCommands.count; ++a) { const CheatLine &line = cheat.lines[i++]; switch (line.part1 >> 28) { case 0x1: // type copy byte { InvalidateICache(op.addr, 4); u32 srcAddr = Memory::Read_U32(op.addr) + op.pointerCommands.offset; u32 dstAddr = Memory::Read_U32(op.addr + op.pointerCommands.baseOffset) + (line.part1 & 0x0FFFFFFF); if (Memory::IsValidRange(dstAddr, val) && Memory::IsValidRange(srcAddr, val)) { InvalidateICache(dstAddr, val); InvalidateICache(srcAddr, val); Memory::MemcpyUnchecked(dstAddr, srcAddr, val); } // Don't perform any further action. type = -1; } break; case 0x2: case 0x3: // type pointer walk { int walkOffset = (int)line.part1 & 0x0FFFFFFF; if ((line.part1 >> 28) == 0x3) { walkOffset = -walkOffset; } InvalidateICache(base + walkOffset, 4); base = Memory::Read_U32(base + walkOffset); switch (line.part2 >> 28) { case 0x2: case 0x3: // type pointer walk walkOffset = line.part2 & 0x0FFFFFFF; if ((line.part2 >> 28) == 0x3) { walkOffset = -walkOffset; } InvalidateICache(base + walkOffset, 4); base = Memory::Read_U32(base + walkOffset); break; default: // Unexpected value in cheat line? break; } } break; case 0x9: // type multi address write base += line.part1 & 0x0FFFFFFF; val += line.part2; break; default: // Unexpected value in cheat line? break; } } switch (type) { case 0: // 8 bit write InvalidateICache(base + op.pointerCommands.offset, 4); Memory::Write_U8((u8)val, base + op.pointerCommands.offset); break; case 1: // 16-bit write InvalidateICache(base + op.pointerCommands.offset, 4); Memory::Write_U16((u16)val, base + op.pointerCommands.offset); break; case 2: // 32-bit write InvalidateICache(base + op.pointerCommands.offset, 4); Memory::Write_U32((u32)val, base + op.pointerCommands.offset); break; case 3: // 8 bit inverse write InvalidateICache(base - op.pointerCommands.offset, 4); Memory::Write_U8((u8)val, base - op.pointerCommands.offset); break; case 4: // 16-bit inverse write InvalidateICache(base - op.pointerCommands.offset, 4); Memory::Write_U16((u16)val, base - op.pointerCommands.offset); break; case 5: // 32-bit inverse write InvalidateICache(base - op.pointerCommands.offset, 4); Memory::Write_U32((u32)val, base - op.pointerCommands.offset); break; case -1: // Operation already performed, nothing to do break; } } break; default: assert(false); } } void CWCheatEngine::Run() { for (CheatCode cheat : cheats_) { // InterpretNextOp and ExecuteOp move i. for (size_t i = 0; i < cheat.lines.size(); ) { CheatOperation op = InterpretNextOp(cheat, i); ExecuteOp(op, cheat, i); } } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有