GBA: Improve multiboot image detection

This commit is contained in:
Vicki Pfau 2017-11-01 16:57:09 -07:00
parent ea9af9e35b
commit 74bd78f382
2 changed files with 43 additions and 9 deletions

View File

@ -35,6 +35,7 @@ Misc:
- GBA: Implement display start DMAs - GBA: Implement display start DMAs
- Qt: Prevent window from being created off-screen - Qt: Prevent window from being created off-screen
- Qt: Add option to disable FPS display - Qt: Add option to disable FPS display
- GBA: Improve multiboot image detection
0.6.1: (2017-10-01) 0.6.1: (2017-10-01)
Bugfixes: Bugfixes:

View File

@ -569,16 +569,49 @@ bool GBAIsMB(struct VFile* vf) {
LOAD_32(opcode, 0, &signature); LOAD_32(opcode, 0, &signature);
struct ARMInstructionInfo info; struct ARMInstructionInfo info;
ARMDecodeARM(opcode, &info); ARMDecodeARM(opcode, &info);
if (info.branchType != ARM_BRANCH) { if (info.branchType == ARM_BRANCH) {
return false; if (info.op1.immediate <= 0) {
return false;
} else if (info.op1.immediate == 28) {
// Ancient toolchain that is known to throw MB detection for a loop
return false;
} else if (info.op1.immediate != 24) {
return true;
}
} }
if (info.op1.immediate <= 0) {
return false; uint32_t pc = GBA_MB_MAGIC_OFFSET;
} else if (info.op1.immediate == 28) { int i;
// Ancient toolchain that is known to throw MB detection for a loop for (i = 0; i < 80; ++i) {
return false; if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
} else if (info.op1.immediate != 24) { break;
return true; }
pc += 4;
LOAD_32(opcode, 0, &signature);
ARMDecodeARM(opcode, &info);
if (info.mnemonic != ARM_MN_LDR) {
continue;
}
if ((info.operandFormat & ARM_OPERAND_MEMORY) && info.memory.baseReg == ARM_PC && info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
uint32_t immediate = info.memory.offset.immediate;
if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
immediate = -immediate;
}
immediate += pc + 8;
if (vf->seek(vf, immediate, SEEK_SET) < 0) {
break;
}
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
break;
}
LOAD_32(immediate, 0, &signature);
if (vf->seek(vf, pc, SEEK_SET) < 0) {
break;
}
if ((immediate & ~0x7FF) == BASE_WORKING_RAM) {
return true;
}
}
} }
// Found a libgba-linked cart...these are a bit harder to detect. // Found a libgba-linked cart...these are a bit harder to detect.
return false; return false;