#pragma once #define RESULT(x) SC_ARGS_1 = (x) class func_caller { public: virtual void operator()() = 0; }; template struct get_arg; template struct get_arg // not fp, not ptr, 1..8 { static __forceinline T func(PPUThread& CPU) { return (T&)CPU.GPR[i + 2]; } }; template struct get_arg // ptr, 1..8 { static __forceinline T func(PPUThread& CPU) { return CPU.GPR[i + 2] ? (T)&Memory[CPU.GPR[i + 2]] : nullptr; } }; template struct get_arg // fp, 1..12 { static __forceinline T func(PPUThread& CPU) { return CPU.FPR[i]; } }; template struct get_arg // not fp, not ptr, 9..12 { static __forceinline T func(PPUThread& CPU) { u64 res = Memory.Read64(CPU.GPR[1] + 0x70 + 0x8 * (i - 9)); return (T&)res; } }; template struct get_arg // ptr, 9..12 { static __forceinline T func(PPUThread& CPU) { u64 addr = Memory.Read64(CPU.GPR[1] + 0x70 + 0x8 * (i - 9)); return addr ? (T)&Memory[addr] : nullptr; } }; #define ARG(n) get_arg<((n) > 8), std::is_floating_point::value, std::is_pointer::value, T##n, n>::func(CPU) template class binder_func_0 : public func_caller { typedef TR (*func_t)(); const func_t m_call; public: binder_func_0(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call()); } }; template<> class binder_func_0 : public func_caller { typedef void (*func_t)(); const func_t m_call; public: binder_func_0(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(); } }; template class binder_func_1 : public func_caller { typedef TR (*func_t)(T1); const func_t m_call; public: binder_func_1(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1))); } }; template class binder_func_1 : public func_caller { typedef void (*func_t)(T1); const func_t m_call; public: binder_func_1(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1)); } }; template class binder_func_2 : public func_caller { typedef TR (*func_t)(T1, T2); const func_t m_call; public: binder_func_2(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2))); } }; template class binder_func_2 : public func_caller { typedef void (*func_t)(T1, T2); const func_t m_call; public: binder_func_2(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2)); } }; template class binder_func_3 : public func_caller { typedef TR (*func_t)(T1, T2, T3); const func_t m_call; public: binder_func_3(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3))); } }; template class binder_func_3 : public func_caller { typedef void (*func_t)(T1, T2, T3); const func_t m_call; public: binder_func_3(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3)); } }; template class binder_func_4 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4); const func_t m_call; public: binder_func_4(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4))); } }; template class binder_func_4 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4); const func_t m_call; public: binder_func_4(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4)); } }; template class binder_func_5 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5); const func_t m_call; public: binder_func_5(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5))); } }; template class binder_func_5 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5); const func_t m_call; public: binder_func_5(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5)); } }; template class binder_func_6 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6); const func_t m_call; public: binder_func_6(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6))); } }; template class binder_func_6 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6); const func_t m_call; public: binder_func_6(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6)); } }; template class binder_func_7 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7); const func_t m_call; public: binder_func_7(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7))); } }; template class binder_func_7 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7); const func_t m_call; public: binder_func_7(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7)); } }; template class binder_func_8 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8); const func_t m_call; public: binder_func_8(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8))); } }; template class binder_func_8 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8); const func_t m_call; public: binder_func_8(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8)); } }; template class binder_func_9 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9); const func_t m_call; public: binder_func_9(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9))); } }; template class binder_func_9 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9); const func_t m_call; public: binder_func_9(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9)); } }; template class binder_func_10 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); const func_t m_call; public: binder_func_10(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10))); } }; template class binder_func_10 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); const func_t m_call; public: binder_func_10(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10)); } }; template class binder_func_11 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); const func_t m_call; public: binder_func_11(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11))); } }; template class binder_func_11 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); const func_t m_call; public: binder_func_11(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11)); } }; template class binder_func_12 : public func_caller { typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); const func_t m_call; public: binder_func_12(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); RESULT(m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11), ARG(12))); } }; template class binder_func_12 : public func_caller { typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); const func_t m_call; public: binder_func_12(func_t call) : func_caller(), m_call(call) {} virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11), ARG(12)); } }; #undef ARG template func_caller* bind_func(TR (*call)()) { return new binder_func_0(call); } template func_caller* bind_func(TR (*call)(T1)) { return new binder_func_1(call); } template func_caller* bind_func(TR (*call)(T1, T2)) { return new binder_func_2(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3)) { return new binder_func_3(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4)) { return new binder_func_4(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5)) { return new binder_func_5(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6)) { return new binder_func_6(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7)) { return new binder_func_7(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8)) { return new binder_func_8(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) { return new binder_func_9(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) { return new binder_func_10(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)) { return new binder_func_11(call); } template func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)) { return new binder_func_12(call); }