|
11 | 11 | #error "Kamek requires the CodeWarrior compiler!" |
12 | 12 | #endif |
13 | 13 |
|
14 | | -#define NULL 0 |
15 | | - |
16 | | -typedef unsigned char u8; |
17 | | -typedef unsigned short u16; |
18 | | -typedef unsigned int u32; |
19 | | -typedef unsigned long long u64; |
20 | | -typedef signed char s8; |
21 | | -typedef signed short s16; |
22 | | -typedef signed int s32; |
23 | | -typedef signed long long s64; |
24 | | -typedef float f32; |
25 | | -typedef double f64; |
26 | | -typedef volatile s64 vs64; |
27 | | -typedef volatile s32 vs32; |
28 | | -typedef volatile s16 vs16; |
29 | | -typedef volatile s8 vs8; |
30 | | -typedef volatile u64 vu64; |
31 | | -typedef volatile u32 vu32; |
32 | | -typedef volatile u16 vu16; |
33 | | -typedef volatile u8 vu8; |
34 | | -typedef volatile f64 vf64; |
35 | | -typedef volatile f32 vf32; |
36 | | - |
37 | | -typedef unsigned long size_t; |
38 | | - |
39 | | -#include "base/hooks.h" |
40 | | -#include "base/c_stdlib.h" |
41 | | -#include "base/rvl_sdk.h" |
| 14 | +// allow Kamek hooks to be defined from C++ source files |
| 15 | +#pragma section ".kamek" |
42 | 16 |
|
43 | | -#endif |
| 17 | +// hook type IDs _must_ match what's in the Kamek source! |
| 18 | +#define kctWrite 1 |
| 19 | +#define kctConditionalWrite 2 |
| 20 | +#define kctInjectBranch 3 |
| 21 | +#define kctInjectCall 4 |
| 22 | +#define kctPatchExit 5 |
| 23 | + |
| 24 | + |
| 25 | +#define kmIdentifier(key, counter) \ |
| 26 | + _k##key##counter |
| 27 | +#define kmHookInt(counter) \ |
| 28 | + __declspec (section ".kamek") static const unsigned int kmIdentifier(Hook, counter) |
| 29 | + |
| 30 | +// general hook definition macros |
| 31 | +// TODO: debugging data (file, line, ...) for diagnostic use by Kamek maybe? :3 |
| 32 | +#define kmHook0(type) \ |
| 33 | + kmHookInt(__COUNTER__)[2] = { 0, (type) } |
| 34 | +#define kmHook1(type, arg0) \ |
| 35 | + kmHookInt(__COUNTER__)[3] = { 1, (type), (unsigned int)(arg0) } |
| 36 | +#define kmHook2(type, arg0, arg1) \ |
| 37 | + kmHookInt(__COUNTER__)[4] = { 2, (type), (unsigned int)(arg0), (unsigned int)(arg1) } |
| 38 | +#define kmHook3(type, arg0, arg1, arg2) \ |
| 39 | + kmHookInt(__COUNTER__)[5] = { 3, (type), (unsigned int)(arg0), (unsigned int)(arg1), (unsigned int)(arg2) } |
| 40 | +#define kmHook4(type, arg0, arg1, arg2, arg3) \ |
| 41 | + kmHookInt(__COUNTER__)[6] = { 4, (type), (unsigned int)(arg0), (unsigned int)(arg1), (unsigned int)(arg2), (unsigned int)(arg3) } |
| 42 | + |
| 43 | +// kmCondWrite |
| 44 | +// Write value to address, conditionally |
| 45 | +#define kmCondWritePointer(addr, original, value) kmHook4(kctConditionalWrite, 1, (addr), (value), (original)) |
| 46 | +#define kmCondWrite32(addr, original, value) kmHook4(kctConditionalWrite, 2, (addr), (value), (original)) |
| 47 | +#define kmCondWrite16(addr, original, value) kmHook4(kctConditionalWrite, 3, (addr), (value), (original)) |
| 48 | +#define kmCondWrite8(addr, original, value) kmHook4(kctConditionalWrite, 4, (addr), (value), (original)) |
| 49 | + |
| 50 | +// kmWrite |
| 51 | +// Write value to address |
| 52 | +#define kmWritePointer(addr, ptr) kmHook3(kctWrite, 1, (addr), (ptr)) |
| 53 | +#define kmWrite32(addr, value) kmHook3(kctWrite, 2, (addr), (value)) |
| 54 | +#define kmWrite16(addr, value) kmHook3(kctWrite, 3, (addr), (value)) |
| 55 | +#define kmWrite8(addr, value) kmHook3(kctWrite, 4, (addr), (value)) |
| 56 | + |
| 57 | +// kmPatchExitPoint |
| 58 | +// Force the end of a Kamek function to always jump to a specific address |
| 59 | +// (if the address is 0, the end remains as-is (i.e. blr)) |
| 60 | +#define kmPatchExitPoint(funcStart, dest) kmHook2(kctPatchExit, (funcStart), (dest)) |
44 | 61 |
|
| 62 | +// kmBranch, kmCall |
| 63 | +// Set up a branch from a specific instruction to a specific address |
| 64 | +#define kmBranch(addr, ptr) kmHook2(kctInjectBranch, (addr), (ptr)) |
| 65 | +#define kmCall(addr, ptr) kmHook2(kctInjectCall, (addr), (ptr)) |
| 66 | + |
| 67 | +// kmBranchDefCpp, kmBranchDefAsm |
| 68 | +// Set up a branch (b) from a specific instruction to a function defined |
| 69 | +// directly underneath. If exitPoint is not NULL, the function will |
| 70 | +// branch to exitPoint when done; otherwise, it executes blr as normal |
| 71 | +#define kmBranchDefInt(counter, addr, exitPoint, returnType, ...) \ |
| 72 | + static returnType kmIdentifier(UserFunc, counter) (__VA_ARGS__); \ |
| 73 | + kmBranch(addr, kmIdentifier(UserFunc, counter)); \ |
| 74 | + kmPatchExitPoint(kmIdentifier(UserFunc, counter), exitPoint); \ |
| 75 | + static returnType kmIdentifier(UserFunc, counter) (__VA_ARGS__) |
| 76 | + |
| 77 | +#define kmBranchDefCpp(addr, exitPoint, returnType, ...) \ |
| 78 | + kmBranchDefInt(__COUNTER__, addr, exitPoint, returnType, __VA_ARGS__) |
| 79 | +#define kmBranchDefAsm(addr, exitPoint) \ |
| 80 | + kmBranchDefInt(__COUNTER__, addr, exitPoint, asm void, ) |
| 81 | + |
| 82 | +// kmCallDefCpp, kmCallDefAsm |
| 83 | +// Set up a branch with link (bl) from a specific instruction to a function |
| 84 | +// defined directly underneath. |
| 85 | +#define kmCallDefInt(counter, addr, returnType, ...) \ |
| 86 | + static returnType kmIdentifier(UserFunc, counter) (__VA_ARGS__); \ |
| 87 | + kmCall(addr, kmIdentifier(UserFunc, counter)); \ |
| 88 | + static returnType kmIdentifier(UserFunc, counter) (__VA_ARGS__) |
| 89 | + |
| 90 | +#define kmCallDefCpp(addr, returnType, ...) \ |
| 91 | + kmCallDefInt(__COUNTER__, addr, returnType, __VA_ARGS__) |
| 92 | +#define kmCallDefAsm(addr) \ |
| 93 | + kmCallDefInt(__COUNTER__, addr, asm void, ) |
| 94 | + |
| 95 | +#endif |
0 commit comments