summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReiko Asakura2021-02-28 18:00:35 -0500
committerReiko Asakura2021-02-28 18:00:35 -0500
commitae1b0bb770bb78a548448c2a41ef431f314dbd62 (patch)
treea8a0436ddc274fd157063b0a78e38658c6d40c0e
parentPort to Vita Development Suite (diff)
downloadmusicpremium-ae1b0bb770bb78a548448c2a41ef431f314dbd62.tar.gz
Refactor opcode decode functions
-rw-r--r--CMakeLists.txt7
-rw-r--r--musicpremium.c34
-rw-r--r--opcode.c58
-rw-r--r--opcode.h14
4 files changed, 82 insertions, 31 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7562cf2..7efbbd4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,12 +30,18 @@ add_link_options(
--prx-no-runtime-support
)
+add_compile_definitions(
+ SCE_DBG_LOG_COMPONENT="\\033[0;31;1mMusic Premium\\033[0m"
+ SCE_DBG_LOGGING_ENABLED=$<IF:$<CONFIG:Release,MinSizeRel>,0,1>
+)
+
set(ELF "${PROJECT_NAME}.elf")
set(SELF "${PROJECT_NAME}.skprx")
add_library("${ELF}" MODULE
musicpremium.c
musicpremium.emd
+ opcode.c
)
target_link_libraries("${ELF}"
@@ -44,6 +50,7 @@ target_link_libraries("${ELF}"
SceSysrootForKernel_stub
taihenForKernel_stub
taihenModuleUtils_stub
+ $<$<NOT:$<CONFIG:Release,MinSizeRel>>:SceDbgForKernel_stub>
)
VDSuiteSignElf("${SELF}" "${ELF}")
diff --git a/musicpremium.c b/musicpremium.c
index 71ade12..fe8a979 100644
--- a/musicpremium.c
+++ b/musicpremium.c
@@ -12,6 +12,8 @@
#include <sblacmgr.h>
#include <taihen.h>
+#include "opcode.h"
+
#define GLZ(x) do {\
if ((x) < 0) { goto fail; }\
} while (0)
@@ -56,30 +58,6 @@ static tai_hook_ref_t hook_ref[N_HOOK];
static int (*sceAppMgrAcquireBgmPortWithPriority)(int priority);
static int (*sceAppMgrReleaseBgmPort)(void);
-static int decode_bl_t1(int bl, int *imm) {
- // split into two shorts
- short bl_1 = bl & 0xFFFF;
- short bl_2 = (bl >> 16) & 0xFFFF;
-
- // verify the form
- RNE(bl_1 & 0xF800, 0xF000);
- RNE(bl_2 & 0xD000, 0xD000);
-
- // decode
- int S = (bl_1 & 0x0400) >> 10;
- int J1 = (bl_2 & 0x2000) >> 13;
- int J2 = (bl_2 & 0x0800) >> 11;
- int I1 = ~(J1 ^ S) & 1;
- int I2 = ~(J2 ^ S) & 1;
- int imm10 = bl_1 & 0x03FF;
- int imm11 = bl_2 & 0x07FF;
-
- // combine to 25 bits and sign extend
- *imm = (S << 31) | (I1 << 30) | (I2 << 29) | (imm10 << 19) | (imm11 << 8);
- *imm >>= 7;
- return 0;
-}
-
static int get_addr(void **inject_addr, void **hook_addr) {
// get sceAppMgrAcquireBgmPort addr
void *sceAppMgrAcquireBgmPort;
@@ -88,14 +66,8 @@ static int get_addr(void **inject_addr, void **hook_addr) {
// clear Thumb bit
sceAppMgrAcquireBgmPort = (void*)((int)sceAppMgrAcquireBgmPort & ~0x1);
- // get the bl offset
- int bl_offset;
- RLZ(decode_bl_t1(*(int*)(sceAppMgrAcquireBgmPort + 2), &bl_offset));
-
// get sceAppMgrAcquireBgmPort impl func addr
- // note that the offset is relative to the PC which for
- // bl is 4 greater than the currently executing instruction
- *hook_addr = sceAppMgrAcquireBgmPort + 6 + bl_offset;
+ RLZ(get_addr_bl((uint16_t *)sceAppMgrAcquireBgmPort + 1, (void *)hook_addr));
// get inject addr
*inject_addr = *hook_addr + 0xE2;
diff --git a/opcode.c b/opcode.c
new file mode 100644
index 0000000..1f92ed3
--- /dev/null
+++ b/opcode.c
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2020-2021 Reiko Asakura. All Rights Reserved.
+
+ Music Premium
+*/
+
+#include <libdbg.h>
+
+#include "opcode.h"
+
+static int decode_bl_common(
+ uint16_t op_lo, uint16_t op_hi, int *imm,
+ uint16_t mask_lo, uint16_t chk_lo, uint16_t mask_hi, uint16_t chk_hi)
+{
+ // verify the form
+ if ((op_lo & mask_lo) != chk_lo) {
+ SCE_DBG_LOG_ERROR("Low halfword check failed");
+ return -1;
+ }
+ if ((op_hi & mask_hi) != chk_hi) {
+ SCE_DBG_LOG_ERROR("High halfword check failed");
+ return -1;
+ }
+
+ // decode
+ int S = (op_lo & 0x0400) >> 10;
+ int J1 = (op_hi & 0x2000) >> 13;
+ int J2 = (op_hi & 0x0800) >> 11;
+ int I1 = ~(J1 ^ S) & 1;
+ int I2 = ~(J2 ^ S) & 1;
+ int imm10 = op_lo & 0x03FF;
+ int imm11 = op_hi & 0x07FF;
+
+ // combine to 25 bits and sign extend
+ *imm = (S << 31) | (I1 << 30) | (I2 << 29) | (imm10 << 19) | (imm11 << 8);
+ *imm >>= 7;
+
+ SCE_DBG_LOG_INFO("BL %04hX %04hX decoded with immediate 0x%08X (%d)", op_lo, op_hi, *imm, *imm);
+ return 0;
+}
+
+static int decode_bl_t1(uint16_t op_lo, uint16_t op_hi, int *imm) {
+ return decode_bl_common(op_lo, op_hi, imm, 0xF800, 0xF000, 0xD000, 0xD000);
+}
+
+int get_addr_bl(uint16_t *pc, uint16_t **addr) {
+ int ret;
+ int offset = 0;
+ if ((ret = decode_bl_t1(pc[0], pc[1], &offset)) < 0) {
+ return ret;
+ }
+
+ // PC is one word ahead
+ *addr = pc + 2 + offset/2;
+
+ SCE_DBG_LOG_INFO("BL at %p branches to %p", pc, *addr);
+ return 0;
+}
diff --git a/opcode.h b/opcode.h
new file mode 100644
index 0000000..e949be7
--- /dev/null
+++ b/opcode.h
@@ -0,0 +1,14 @@
+/*
+ Copyright (C) 2020-2021 Reiko Asakura. All Rights Reserved.
+
+ Music Premium
+*/
+
+#ifndef OPCODE_H_
+#define OPCODE_H_
+
+#include <stdint.h>
+
+int get_addr_bl(uint16_t *pc, uint16_t **addr);
+
+#endif