ppspp android编译,安卓PSP模拟器 PPSSPP金手指

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 << (line2.part2 & 0xF);

CheatOp opcode;

switch (arg >> 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);

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值