Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 49 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,73 @@
#include <cstdint>
#include <cstring>
#include <cstddef>
#include <sys/mman.h>
#include <unistd.h>

#include "pl/Gloss.h"
#include "pl/Signature.h"

static const char* GFX_GAMMA_SIGNATURE = "? ? ? 52 ? ? ? 2F ? ? ? 1E ? ? ? 72 ? ? ? 1E ? ? ? D1 03 01 27 1E ? ? ? D1 E0 03 15 AA ? ? ? 52 ? ? ? 52";
static const char* GFX_GAMMA_SIGNATURE =
"? ? ? 52 ? ? ? 2F ? ? ? 1E ? ? ? 72 ? ? ? 1E ? ? ? D1 "
"03 01 27 1E ? ? ? D1 E0 03 15 AA ? ? ? 52 ? ? ? 52";

constexpr uint32_t FULLBRIGHT_GAMMA = 100;

static constexpr uint32_t MakeMovW8(uint32_t imm) {
return 0x52800000u | ((imm & 0xFFFFu) << 5) | 8u;
}

constexpr uint32_t MOV_W8_10 = 0x52800148;
constexpr uint32_t MOV_W8_FULLBRIGHT = MakeMovW8(FULLBRIGHT_GAMMA);
constexpr uint32_t SCVTF_S2_W8 = 0x1E220102;
constexpr uint32_t EXPECTED_FMOV_S2_1 = 0x1E2E1002;
constexpr ptrdiff_t OFFSET_GAMMA_CONST = 12;
constexpr ptrdiff_t OFFSET_FMOV = 16;

constexpr ptrdiff_t OFFSET_MOVK = 12;
constexpr ptrdiff_t OFFSET_FMOV = 16;
static bool ReadInsn(uintptr_t addr, uint32_t& out) {
std::memcpy(&out, reinterpret_cast<void*>(addr), sizeof(out));
return true;
}

static bool PatchMemory(void* addr, uint32_t insn) {
uintptr_t page_start = (uintptr_t)addr & ~(uintptr_t)4095;
size_t page_size = (sizeof(insn) + 4095) & ~(size_t)4095;
if (mprotect((void*)page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
uintptr_t p = reinterpret_cast<uintptr_t>(addr);

long page_size_long = sysconf(_SC_PAGESIZE);
uintptr_t page_size = page_size_long > 0 ? static_cast<uintptr_t>(page_size_long) : 4096;

uintptr_t page_start = p & ~(page_size - 1);
uintptr_t page_end = (p + sizeof(insn) + page_size - 1) & ~(page_size - 1);
size_t len = page_end - page_start;

if (mprotect(reinterpret_cast<void*>(page_start), len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
return false;
memcpy(addr, &insn, sizeof(insn));
__builtin___clear_cache((char*)addr, (char*)addr + sizeof(insn));
mprotect((void*)page_start, page_size, PROT_READ | PROT_EXEC);

std::memcpy(addr, &insn, sizeof(insn));
__builtin___clear_cache(reinterpret_cast<char*>(addr),
reinterpret_cast<char*>(addr) + sizeof(insn));

mprotect(reinterpret_cast<void*>(page_start), len, PROT_READ | PROT_EXEC);
return true;
}

static bool PatchGfxGamma() {
uintptr_t base = pl::signature::pl_resolve_signature(GFX_GAMMA_SIGNATURE, "libminecraftpe.so");
uintptr_t base = pl::signature::pl_resolve_signature(
GFX_GAMMA_SIGNATURE,
"libminecraftpe.so"
);

if (base == 0)
return false;

if (*reinterpret_cast<uint32_t*>(base + OFFSET_FMOV) != 0x1E2E1002)
uint32_t old_fmov = 0;
ReadInsn(base + OFFSET_FMOV, old_fmov);

if (old_fmov != EXPECTED_FMOV_S2_1)
return false;

return PatchMemory(reinterpret_cast<void*>(base + OFFSET_MOVK), MOV_W8_10)
&& PatchMemory(reinterpret_cast<void*>(base + OFFSET_FMOV), SCVTF_S2_W8);
bool ok1 = PatchMemory(reinterpret_cast<void*>(base + OFFSET_GAMMA_CONST), MOV_W8_FULLBRIGHT);
bool ok2 = PatchMemory(reinterpret_cast<void*>(base + OFFSET_FMOV), SCVTF_S2_W8);

return ok1 && ok2;
}

__attribute__((constructor))
Expand Down