From a5416d098c49c223b4541ac2ddf56a4a36b8c0dd Mon Sep 17 00:00:00 2001 From: Knaapchen Date: Sun, 9 Oct 2022 03:46:56 +0200 Subject: [PATCH] Mad progress Figured out how to send packets --- flyff-api/CMakeLists.txt | 2 + flyff-api/include/flyff.h | 22 ++- flyff-api/src/{raw => }/Job.h | 0 flyff-api/src/Mover.h | 30 +++ flyff-api/src/Neuz.cpp | 45 +++++ flyff-api/src/Neuz.h | 35 ++++ flyff-api/src/ObjectType.h | 13 ++ flyff-api/src/core.h | 105 +++++++++++ flyff-api/src/import.cpp | 15 ++ flyff-api/src/math.h | 21 +++ flyff-api/src/raw/Mover.h | 82 ++++---- flyff-api/src/raw/ObjectType.h | 13 -- flyff-client/src/client.c | 50 +++-- fugg-client/src/client.cpp | 282 ++++++++++++++++++++-------- fugg-client/src/client.h | 21 +-- fugg-client/src/export/callback.cpp | 6 + fugg-client/src/export/embind.cpp | 2 +- fugg-client/src/export/env.cpp | 6 +- fugg-client/src/export/platform.cpp | 2 +- fugg-client/src/main.cpp | 11 +- 20 files changed, 590 insertions(+), 173 deletions(-) rename flyff-api/src/{raw => }/Job.h (100%) create mode 100644 flyff-api/src/Mover.h create mode 100644 flyff-api/src/Neuz.cpp create mode 100644 flyff-api/src/Neuz.h create mode 100644 flyff-api/src/ObjectType.h create mode 100644 flyff-api/src/core.h create mode 100644 flyff-api/src/import.cpp create mode 100644 flyff-api/src/math.h delete mode 100644 flyff-api/src/raw/ObjectType.h diff --git a/flyff-api/CMakeLists.txt b/flyff-api/CMakeLists.txt index 061cce2..e0072b0 100644 --- a/flyff-api/CMakeLists.txt +++ b/flyff-api/CMakeLists.txt @@ -1,6 +1,8 @@ add_library ( flyff-api "src/flyff.cpp" + "src/Neuz.cpp" + "src/import.cpp" "include/flyff.h" ) diff --git a/flyff-api/include/flyff.h b/flyff-api/include/flyff.h index c4611d3..05016b6 100644 --- a/flyff-api/include/flyff.h +++ b/flyff-api/include/flyff.h @@ -1,15 +1,19 @@ #pragma once -#include - #include +#include "../src/Neuz.h" +#include "../src/Mover.h" + #include "../src/import.h" + +#include "../src/raw/Mover.h" + namespace flyff { - #include "../src/raw/ItemProperty.h" - #include "../src/raw/MusicProperty.h" - #include "../src/raw/Mover.h" + // #include "../src/raw/ItemProperty.h" + // #include "../src/raw/MusicProperty.h" + // #include "../src/raw/Mover.h" namespace api { // static_assert(sizeof(fugg::ModulePointer) == sizeof(u32), "ModulePointer needs the same size as u32"); @@ -21,6 +25,14 @@ namespace flyff { extern void w2c_f167(u32, u32); extern u32 w2c_f208(u64); + + extern void w2c_f337(u32, u32, u32); + // f271_called_on_attack + extern u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5); + // f2300_finalize_packet: Encrypts and constructs a packet for wire. + extern void w2c_f2300(u32); + // f2296_websocket_send: Sends a packet over the WebSocket connection. + extern void w2c_f2296(u32, u32); }; } diff --git a/flyff-api/src/raw/Job.h b/flyff-api/src/Job.h similarity index 100% rename from flyff-api/src/raw/Job.h rename to flyff-api/src/Job.h diff --git a/flyff-api/src/Mover.h b/flyff-api/src/Mover.h new file mode 100644 index 0000000..492be39 --- /dev/null +++ b/flyff-api/src/Mover.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include + +#include "core.h" +#include "math.h" + +namespace flyff { +struct __attribute__((packed)) Mover { + union { + DEFINE_MEMBER(0x18, flyff::Matrix4, world_matrix); + DEFINE_MEMBER(0x98, flyff::Vector3, position); + + DEFINE_MEMBER(2020, const flyff::String, name); + + DEFINE_MEMBER(1744, flyff::MoverID, selected_target); + DEFINE_MEMBER(1752, flyff::MoverID, attack_target); + DEFINE_MEMBER(1760, flyff::MoverID, follow_target); + DEFINE_MEMBER(1768, flyff::MoverID, current_attack_target); + DEFINE_MEMBER(1776, flyff::MoverID, platform_standing_on); + + DEFINE_MEMBER(1792, int, current_animation); + + const MinimumSize<4096> __size; + }; +}; + +}; \ No newline at end of file diff --git a/flyff-api/src/Neuz.cpp b/flyff-api/src/Neuz.cpp new file mode 100644 index 0000000..094e181 --- /dev/null +++ b/flyff-api/src/Neuz.cpp @@ -0,0 +1,45 @@ +#include "Neuz.h" + +#include + +// static_assert(sizeof(TestMover) == 4096, "Mover needs to be 4096 bytes"); +// static_assert(offsetof(TestMover, name) == 0x7f4, "Mover.name needs to be at 2020"); + +namespace flyff { + +// Emscripten runtime: +// 1. Pre-run +// 2. Init runtime +// 3. Pre-main +// 4. Call main +// 5. Post-run + +Neuz::Neuz() { + // 1. Pre-run: There are no pre-runs in this binary. + // 2. Init runtime: `___wasm_call_ctors` is added to on init runtime. + (*flyff::raw::_wasm_call_ctors)(); +} + +Neuz& Neuz::instance() { + static bool initialised = false; + if (!initialised) { + // Initialise the WebAssembly runtime. + wasm_rt_init(); + // Initialise the client. + flyff::raw::init(); + // Only init the module once. + initialised = true; + } + // Constructor will be called. + static Neuz instance; + // Whole module is initialised now. + return instance; +} + +int Neuz::main() const { + // 3. Pre-main: There are no pre-mains in this binary. + // 4. Call main: `_main` is main in the binary. + // TODO: Fix arguments. + return (*flyff::raw::main)(0, 0); +} +} // namespace flyff \ No newline at end of file diff --git a/flyff-api/src/Neuz.h b/flyff-api/src/Neuz.h new file mode 100644 index 0000000..408d503 --- /dev/null +++ b/flyff-api/src/Neuz.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace flyff { + namespace raw { + static const auto& init = &Z_client_init; + + static const auto& _wasm_call_ctors = &Z_clientZ____wasm_call_ctors; + static const auto& main = &Z_clientZ__main; + + static const auto& malloc = &Z_clientZ__malloc; + static const auto& free = &Z_clientZ__free; + } + // static_assert(sizeof(Pointer) == sizeof(u32), "Pointers needs to be the size of u32"); + + class Neuz { + Neuz(); + + public: + static Neuz& instance(); + + Neuz(Neuz const&) = delete; + void operator=(Neuz const&) = delete; + + // Execute the `main` function of the flyff-client. + int main() const; + + // Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered function. + // void send_keydown(); + // void send_keyup(); + // void send_keypress(); + }; +} \ No newline at end of file diff --git a/flyff-api/src/ObjectType.h b/flyff-api/src/ObjectType.h new file mode 100644 index 0000000..bc51340 --- /dev/null +++ b/flyff-api/src/ObjectType.h @@ -0,0 +1,13 @@ +#pragma once + +enum class ObjectType : int { + Object = 0 /* Background object */, + Animation = 1 /* Animation object */, + Ctrl = 2 /* Special background object */, + Sfx = 3 /* Special effect object */, + Item = 4 /* Item */, + Mover = 5 /* Moving object */, + Region = 6 /* Region (event, attribute) */, + Ship = 7, + Path = 8 +}; \ No newline at end of file diff --git a/flyff-api/src/core.h b/flyff-api/src/core.h new file mode 100644 index 0000000..dedfa12 --- /dev/null +++ b/flyff-api/src/core.h @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include + +template +class MinimumSize { + unsigned char __padding[kSize]; +}; + +#define STR_MERGE_IMPL(a, b) a##b +#define STR_MERGE(a, b) STR_MERGE_IMPL(a, b) +#define MAKE_PAD(size) STR_MERGE(_pad, __COUNTER__)[size] +#define DEFINE_MEMBER(offset, type, name) struct {unsigned char MAKE_PAD(offset); type name;} + +namespace flyff { +namespace detail { +template +struct ArrowProxy { + I value; + + O* operator->() { + return reinterpret_cast(&value); + } + + O& operator*() { + return *(operator->)(); + } +}; +} + +class Memory { + wasm_rt_memory_t** memory; + + public: + explicit Memory(wasm_rt_memory_t** mem) : memory(mem) {} + + const uintptr_t to_outside(const uintptr_t& offset) const { + return reinterpret_cast(&(*memory)->data[offset]); + } + + template + T* to_outside(T* offset) const { + return reinterpret_cast( + to_outside( + reinterpret_cast(offset) + ) + ); + } +}; + +static auto kMemory = Memory(&Z_clientZ_memory); + +class Table {}; + +static const auto& kTable = &Z_clientZ_table; + +template +class Pointer { + uintptr_t offset; + + public: + T* operator->() { return reinterpret_cast(kMemory.to_outside(offset)); } +}; + +class String { + union { + DEFINE_MEMBER(0x0, char*, text); + DEFINE_MEMBER(0x4, size_t, length); + DEFINE_MEMBER(0x8, void*, capacity); + + DEFINE_MEMBER(0x0, char, data[1]); + DEFINE_MEMBER(0xb, char, short_length); + + const MinimumSize<12> __size; + }; + +public: + // This has to be const until strings can allocate... + operator const std::string() const { + auto copy = *this; + + auto is_short = -1 < copy.short_length; + if (!is_short) { + copy.text = kMemory.to_outside(text); + // TODO: Probably offset capacity too. + } + + std::cout << "RIGHT BEFORE COPY!" << std::endl; + return *reinterpret_cast(©); + } + + friend std::ostream& operator<<(std::ostream& os, const String& str) { + const std::string conv = str; + os << conv; + return os; + } +}; + +typedef unsigned long long MoverID; + +static_assert(sizeof(String) == sizeof(std::string), + "String needs to be the same size as std::string"); +}; // namespace flyff \ No newline at end of file diff --git a/flyff-api/src/import.cpp b/flyff-api/src/import.cpp new file mode 100644 index 0000000..183430c --- /dev/null +++ b/flyff-api/src/import.cpp @@ -0,0 +1,15 @@ + +#include +#include + +namespace flyff { + namespace raw { + static const auto& init = &Z_client_init; + + static const auto& _wasm_call_ctors = &Z_clientZ____wasm_call_ctors; + static const auto& main = &Z_clientZ__main; + + static const auto& malloc = &Z_clientZ__malloc; + static const auto& free = &Z_clientZ__free; + } +} diff --git a/flyff-api/src/math.h b/flyff-api/src/math.h new file mode 100644 index 0000000..db28c0e --- /dev/null +++ b/flyff-api/src/math.h @@ -0,0 +1,21 @@ +#pragma once + +namespace flyff { + struct Vector4 { + float x, y, z, w; + }; + + struct Vector3 { + float x, y, z; + }; + + struct Matrix4 { + Vector4 a, b, c, d; + }; + + struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + }; +} \ No newline at end of file diff --git a/flyff-api/src/raw/Mover.h b/flyff-api/src/raw/Mover.h index 5e3e95d..e490bd2 100644 --- a/flyff-api/src/raw/Mover.h +++ b/flyff-api/src/raw/Mover.h @@ -30,13 +30,11 @@ typedef struct SomethingWithJob SomethingWithJob, *PSomethingWithJob; typedef uint uint32_t; -typedef uint32_t wasm_rt_funcref_t; - -#include "ObjectType.h" +#include "../ObjectType.h" +#include "../Job.h" typedef struct astruct_30 astruct_30, *Pastruct_30; -#include "Job.h" struct Vector4 { float x; @@ -3318,7 +3316,7 @@ struct __attribute__ ((packed)) Mover { }; struct astruct_30 { - wasm_rt_funcref_t * vtable; + uint32_t * vtable; }; struct SomethingWithJob { @@ -3331,7 +3329,7 @@ struct SomethingWithJob { undefined field6_0x9; undefined field7_0xa; undefined field8_0xb; - enum Job job; + Job job; undefined field10_0x10; undefined field11_0x11; undefined field12_0x12; @@ -31554,7 +31552,7 @@ struct CCtrl { undefined field183_0xc9; undefined field184_0xca; undefined field185_0xcb; - enum ObjectType maybe_dynamic_object_type; + ObjectType maybe_dynamic_object_type; undefined field187_0xd0; undefined field188_0xd1; undefined field189_0xd2; @@ -34493,40 +34491,40 @@ struct CCtrl { }; struct Mover_Vtable { - wasm_rt_funcref_t field0_0x0; - wasm_rt_funcref_t field1_0x4; - wasm_rt_funcref_t field2_0x8; - wasm_rt_funcref_t field3_0xc; - wasm_rt_funcref_t field4_0x10; - wasm_rt_funcref_t field5_0x14; - wasm_rt_funcref_t field6_0x18; - wasm_rt_funcref_t field7_0x1c; - wasm_rt_funcref_t field8_0x20; - wasm_rt_funcref_t field9_0x24; - wasm_rt_funcref_t field10_0x28; - wasm_rt_funcref_t field11_0x2c; - wasm_rt_funcref_t field12_0x30; - wasm_rt_funcref_t field13_0x34; - wasm_rt_funcref_t field14_0x38; - wasm_rt_funcref_t field15_0x3c; - wasm_rt_funcref_t field16_0x40; - wasm_rt_funcref_t field17_0x44; - wasm_rt_funcref_t field18_0x48; - wasm_rt_funcref_t field19_0x4c; - wasm_rt_funcref_t field20_0x50; - wasm_rt_funcref_t field21_0x54; - wasm_rt_funcref_t field22_0x58; - wasm_rt_funcref_t field23_0x5c; - wasm_rt_funcref_t field24_0x60; - wasm_rt_funcref_t field25_0x64; - wasm_rt_funcref_t field26_0x68; - wasm_rt_funcref_t field27_0x6c; - wasm_rt_funcref_t field28_0x70; - wasm_rt_funcref_t field29_0x74; - wasm_rt_funcref_t field30_0x78; - wasm_rt_funcref_t field31_0x7c; - wasm_rt_funcref_t field32_0x80; - wasm_rt_funcref_t field33_0x84; - wasm_rt_funcref_t field34_0x88; + uint32_t field0_0x0; + uint32_t field1_0x4; + uint32_t field2_0x8; + uint32_t field3_0xc; + uint32_t field4_0x10; + uint32_t field5_0x14; + uint32_t field6_0x18; + uint32_t field7_0x1c; + uint32_t field8_0x20; + uint32_t field9_0x24; + uint32_t field10_0x28; + uint32_t field11_0x2c; + uint32_t field12_0x30; + uint32_t field13_0x34; + uint32_t field14_0x38; + uint32_t field15_0x3c; + uint32_t field16_0x40; + uint32_t field17_0x44; + uint32_t field18_0x48; + uint32_t field19_0x4c; + uint32_t field20_0x50; + uint32_t field21_0x54; + uint32_t field22_0x58; + uint32_t field23_0x5c; + uint32_t field24_0x60; + uint32_t field25_0x64; + uint32_t field26_0x68; + uint32_t field27_0x6c; + uint32_t field28_0x70; + uint32_t field29_0x74; + uint32_t field30_0x78; + uint32_t field31_0x7c; + uint32_t field32_0x80; + uint32_t field33_0x84; + uint32_t field34_0x88; }; diff --git a/flyff-api/src/raw/ObjectType.h b/flyff-api/src/raw/ObjectType.h deleted file mode 100644 index cfc3989..0000000 --- a/flyff-api/src/raw/ObjectType.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -enum class ObjectType : int { - Object = 0 /* Background object */, - Animation = 1 /* Animation object */, - Ctrl = 2 /* Special background object */, - Sfx = 3 /* Special effect object */, - Item = 4 /* Item */, - Mover = 5 /* Moving object */, - Region = 6 /* Region (event, attribute) */, - Ship = 7, - Path = 8 -}; \ No newline at end of file diff --git a/flyff-client/src/client.c b/flyff-client/src/client.c index 70e9ef0..a2482fd 100644 --- a/flyff-client/src/client.c +++ b/flyff-client/src/client.c @@ -512,7 +512,7 @@ static u32 w2c__malloc(u32); static u32 w2c_f268(u32); static u32 w2c_f269(u32); static void w2c_f270(u32, u32); -static u32 w2c_f271(u32, u32, u64, u64, u64, u64); +u32 w2c_f271(u32, u32, u64, u64, u64, u64); static u32 w2c_f272(u32); static void w2c_f273(u32, u32); static void w2c_f274(u32); @@ -578,7 +578,7 @@ static void w2c_f333(void); static void w2c_f334(u32, u32, f32, u32); static u32 w2c_f335(u32); static void w2c_f336(u32, u32); -static void w2c_f337(u32, u32, u32); +void w2c_f337(u32, u32, u32); static u32 w2c_f338(u32, u32); static void w2c_f339(u32); static void w2c_f340(u32, u32, u32, u32); @@ -2537,11 +2537,11 @@ static void w2c_f2292(u32, u32); static u32 w2c_f2293(u32); static void w2c_f2294(u32); static u32 w2c_f2295(u32); -static void w2c_f2296(u32, u32); +void w2c_f2296(u32, u32); static void w2c_f2297(u32); static void w2c_f2298(u32, u32); static void w2c_f2299(u32); -static void w2c_f2300(u32); +void w2c_f2300(u32); static void w2c_f2301(u32); static void w2c_f2302(u32); static void w2c_f2303(u32); @@ -44146,7 +44146,11 @@ static void w2c_f270(u32 w2c_p0, u32 w2c_p1) { FUNC_EPILOGUE; } -static u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) { +u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) { + // printf("called_on_attack(): p0=%u, p1=%u, p2=%llu, p3=%llu, p4=%llu, p5=%llu\n", + // w2c_p0, w2c_p1, w2c_p2, w2c_p3, w2c_p4, w2c_p5 + // ); + u32 w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0, w2c_l9 = 0, w2c_l10 = 0, w2c_l11 = 0, w2c_l12 = 0, w2c_l13 = 0, w2c_l14 = 0, w2c_l15 = 0, w2c_l16 = 0, w2c_l17 = 0, w2c_l18 = 0, w2c_l19 = 0, w2c_l20 = 0; u64 w2c_l24 = 0; @@ -71282,7 +71286,7 @@ static void w2c_f336(u32 w2c_p0, u32 w2c_p1) { FUNC_EPILOGUE; } -static void w2c_f337(u32 w2c_p0, u32 w2c_p1, u32 w2c_p2) { +void w2c_f337(u32 w2c_p0, u32 w2c_p1, u32 w2c_p2) { u32 w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0, w2c_l9 = 0, w2c_l10 = 0, w2c_l11 = 0; FUNC_PROLOGUE; @@ -116326,9 +116330,8 @@ static void w2c_f424(u32 w2c_p0) { w2c_i1 = 4294967232u; w2c_i0 -= w2c_i1; w2c_i1 = 17381u; - w2c_i0 = w2c_f204(w2c_i0, w2c_i1); - printf("This gets printed when you have no target.\n"); + w2c_i0 = w2c_f204(w2c_i0, w2c_i1); w2c_p0 = w2c_i0; w2c_i0 = w2c_l5; @@ -1035771,6 +1035774,15 @@ static void w2c_f2291(u32 w2c_p0) { } static void w2c_f2292(u32 w2c_p0, u32 w2c_p1) { + // u32 length = w2c_p1; + // u32 buffer = w2c_p0; + + // printf("Server sent message of length %u: ", length); + // for(u32 i = 0; i < length; i++) { + // printf("%02x ", (&w2c_memory)->data[buffer + i]); + // } + // printf("\n"); + u32 w2c_l2 = 0, w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0; u64 w2c_l9 = 0; f64 w2c_l8 = 0; @@ -1036664,12 +1036676,12 @@ static u32 w2c_f2295(u32 w2c_p0) { return w2c_i0; } -static void w2c_f2296(u32 w2c_p0, u32 w2c_p1) { +void w2c_f2296(u32 w2c_p0, u32 w2c_p1) { const wasm_rt_memory_t* memory = &w2c_memory; const unsigned char* data = &memory->data[w2c_p0]; const size_t length = w2c_p1; - puts("Sending network packet:"); + printf("Sending network packet of length %zd (expecting finalized %zd): ", length, length - 9); for(int i = 0; i < length; i++) { printf("%02X ", data[i]); } @@ -1036901,17 +1036913,31 @@ static void w2c_f2299(u32 w2c_p0) { FUNC_EPILOGUE; } -static void w2c_f2300(u32 w2c_p0) { +void w2c_f2300(u32 w2c_p0) { u32 w2c_l1 = 0, w2c_l2 = 0, w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0; FUNC_PROLOGUE; u32 w2c_i0, w2c_i1, w2c_i2, w2c_i3; u64 w2c_j1; + w2c_i0 = w2c_p0; - w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u); + w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u); w2c_l4 = w2c_i0; + const uintptr_t end = w2c_l4; + w2c_i1 = w2c_p0; w2c_i1 = i32_load((&w2c_memory), (u64)(w2c_i1)); w2c_l2 = w2c_i1; + const uintptr_t begin = w2c_l2; + + const size_t length = end - begin; + const unsigned char* data = &(&w2c_memory)->data[begin]; + + printf("Finalizing packet of length %zd: ", length); + for(int i = 0; i < length; i++) { + printf("%02X ", data[i]); + } + printf("\n"); + w2c_i0 -= w2c_i1; w2c_l7 = w2c_i0; w2c_i0 = 9u; diff --git a/fugg-client/src/client.cpp b/fugg-client/src/client.cpp index 8b9e0e7..e96ce26 100644 --- a/fugg-client/src/client.cpp +++ b/fugg-client/src/client.cpp @@ -6,51 +6,9 @@ namespace fugg { - // Emscripten runtime: - // 1. Pre-run - // 2. Init runtime - // 3. Pre-main - // 4. Call main - // 5. Post-run - - using wasm::kMemory; - using wasm::kTable; - - Client::Client() { - // 1. Pre-run: There are no pre-runs in this binary. - // 2. Init runtime: `___wasm_call_ctors` is added to on init runtime. - (*flyff::_wasm_call_ctors)(); - } - - Client& Client::instance() { - static bool initialised = false; - if(!initialised) { - // Initialise the WebAssembly runtime. - wasm_rt_init(); - // Initialise the client. - flyff::init(); - // Only init the module once. - initialised = true; - } - // Constructor will be called. - static Client instance; - // Whole module is initialised now. - return instance; - } - - void Client::initialise() { - - } - - int Client::main() const { - // 3. Pre-main: There are no pre-mains in this binary. - // 4. Call main: `_main` is main in the binary. - // TODO: Fix arguments. - return (*flyff::main)(0, 0); - } } -fugg::String translate(const std::string& id) { +const flyff::String get_text(const std::string& id) { auto result = std::make_unique(); auto id_ = std::make_unique(id); @@ -59,7 +17,53 @@ fugg::String translate(const std::string& id) { fugg::RuntimePointer(id_.get()).as_raw() ); - return *reinterpret_cast(result.get()); + return *reinterpret_cast(result.get()); +} + +void show_message(const std::string& message, const flyff::Color& color) { + // Copy the message into a new auto ptr + auto message_ = std::make_unique(message); + auto color_ = std::make_unique(color); + + const auto& kUnknownParam1 = fugg::module_ref(0x00034da8); + + std::cout << "Got pointers: 1 = " << kUnknownParam1 << std::endl; + + if(kUnknownParam1 == NULL) { + std::cout << "kUnknownParam1 == 0, returning..." << std::endl; + return; + } + + flyff::api::w2c_f337( + 0x00034da8, + fugg::RuntimePointer(message_.get()).as_raw(), + fugg::RuntimePointer(color_.get()).as_raw() + ); +} + +void send_packet(std::vector payload) { + struct Vector { + uintptr_t begin; + uintptr_t end; + uintptr_t capacity; + }; + + auto raw_payload = reinterpret_cast(&payload); + // Copy the message into a new ptr + auto payload_ = std::unique_ptr(new Vector { + .begin = fugg::RuntimePointer(raw_payload->begin).as_raw(), + .end = fugg::RuntimePointer(raw_payload->end).as_raw(), + .capacity = fugg::RuntimePointer(raw_payload->capacity).as_raw() + }); + + flyff::api::w2c_f2300( + fugg::RuntimePointer(payload_.get()).as_raw() + ); + + flyff::api::w2c_f2296( + payload_->begin, + payload_->end - payload_->begin + ); } #include @@ -69,11 +73,130 @@ fugg::String translate(const std::string& id) { #include #include -void before_main_loop() { - auto& client = fugg::Client::instance(); +#include - const auto& test = translate("ids_textclient_cannot_dropmoney"); - std::cout << test->c_str() << std::endl; +#include + +template +void packet_push(std::vector& packet, const T& value) { + union ToBytes { + T value; + uint8_t bytes[sizeof(T)]; + }; + + ToBytes ref = { value }; + + packet.insert(packet.end(), std::begin(ref.bytes), std::end(ref.bytes)); +} + +void move_item_in_inventory(const uint32_t& from_slot, const uint32_t& to_slot) { + std::vector packet; + // Not sure yet about these + packet.insert(packet.end(), { 0x01, 0x94 }); + packet.insert(packet.end(), { 0x4a, 0x64 }); + + packet_push(packet, from_slot); + packet_push(packet, to_slot); + + send_packet(packet); +} + +void use_item_in_inventory(const uint32_t& slot) { + std::vector packet; + // Not sure yet + packet.insert(packet.end(), { 0x10, 0xb0 }); + // Same as move_item_in_inventory + packet.insert(packet.end(), { 0x4a, 0x64 }); + + packet_push(packet, slot); + // Unknown yet + packet_push(packet, 0); + + send_packet(packet); + +} + +void move_to(const float& x, const float& y, const float& z) { + // Mouse click + // 04 B0 4A 64 FC D9 D4 45 AC 20 D4 42 C3 B9 52 45 00 07 65 30 00 00 68 F5 D4 45 00 00 00 00 8B A8 D1 42 00 00 00 00 FE 98 52 45 00 00 00 00 + + std::vector packet; + packet.push_back(0x04); + packet.push_back(0xb0); + + // Same as move_item_in_inventory + packet.insert(packet.end(), { 0x4a, 0x64 }); + + packet_push(packet, x); + packet_push(packet, y); + packet_push(packet, z); + // ... + // send_packet(packet); +} + +void write_chat_message(const std::string& message) { + // 00 94 4A 64 [0B 00 00 00] [48 65 6C 6C 6F 20 77 6F 72 6C 64] 00 00 00 00 00 00 00 00 + + std::vector packet; + packet.push_back(0x00); + packet.push_back(0x94); + // Same as move_item_in_inventory + packet.insert(packet.end(), { 0x4a, 0x64 }); + + // Message length + packet_push(packet, message.length()); + // Write message + for(const auto& character : message) { + packet_push(packet, character); + } + // Unknown 1 + packet_push(packet, 0); + // Unknown 2 + packet_push(packet, 0); + + send_packet(packet); +} + +void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent* event, void* user_data) { + // [ + if(event->keyCode == 219) { + show_message("HAHAH DIKKE VETTE ANUSSEN", { 0xFF, 0, 0 }); + + // send_packet({ + // 0x01, 0x94, 0x4a, 0x64, + // // From slot + // 0x05, 0x00, 0x00, 0x00, + // // To slot + // 0x00, 0x00, 0x00, 0x00 + // }); + + // move_item_in_inventory(0, 50); + use_item_in_inventory(0); + + write_chat_message("Hahaha dikke vette moeders"); + } +} + +void before_main_loop() { + // auto& client = fugg::Client::instance(); + + // const auto& test = translate("ids_textclient_cannot_dropmoney"); + // const auto& test = translate("ids_textclient_skill_self"); + // const auto& test = get_text("ids_textclient_notarget"); + // const auto& test = get_text("ids_textclient_checkequip"); + // const auto& test = get_text("ids_textclient_reapskill"); + // const auto& test = get_text("ids_textclient_skillpoint_up"); + // const auto& test = get_text("ids_textclient_skill_mate"); + // const auto& test = get_text("IDS_PROPMOVER_TXT_000002"); + // { + // const auto& test = get_text("ids_textclient_app_party"); + // std::cout << test << std::endl; + // } + // { + // const auto& test = get_text("ids_ui_party_permanent"); + // std::cout << test << std::endl; + // } + // show_message("HAHAH DIKKE VETTE ANUSSEN"); } void after_main_loop() { @@ -91,40 +214,47 @@ void after_main_loop() { // if(player_pointer != 0) { // auto& player = fugg::module_ref(player_pointer); - // std::cout << "Player pos: " - // << player.world_position.x << ", " - // << player.world_position.y << ", " - // << player.world_position.z << std::endl; + // std::cout << "Player pos: " + // << player.position.x << ", " + // << player.position.y << ", " + // << player.position.z << std::endl; - // std::cout << "Current target: " << player.selected_target_id << std::endl; - // std::cout << "Current animation: " << player.current_animation << std::endl; - // std::cout << "Name: " << player.name->c_str() << std::endl; + // // std::cout << "Current target: " << player.selected_target << std::endl; + // std::cout << "Current animation: " << player.current_animation << std::endl; + // std::cout << "Name: " << player.name << std::endl; - // if(player.selected_target_id != 0) { - // struct ObjectHolder { - // uintptr_t next; - // unsigned int list_index; - // unsigned long long hash; - // uintptr_t mover; - // }; + // const int bla = offsetof(Mover, name); + // const int test = offsetof(flyff::Mover, name); - // auto& selected_target_holder = fugg::module_ref( - // w2c_f208(player.selected_target_id) - // ); + // static_assert(bla == test, "OMG"); - // auto& selected_target = fugg::module_ref( - // selected_target_holder.mover - // ); + // // static_assert(offsetof(Mover, name) == 2020, "ASD"); - // std::cout << "(" << reinterpret_cast(selected_target_holder.mover) << ") Target: " - // << selected_target.name->c_str() << " at " - // << selected_target.world_position.x << ", " - // << selected_target.world_position.y << ", " - // << selected_target.world_position.z << std::endl; + // if(player.selected_target != 0) { + // struct ObjectHolder { + // uintptr_t next; + // unsigned int list_index; + // unsigned long long hash; + // uintptr_t mover; + // }; - // } else { - // std::cout << "Got no target." << std::endl; - // } + // auto& selected_target_holder = fugg::module_ref( + // flyff::api::w2c_f208(player.selected_target) + // ); + + // auto& selected_target = fugg::module_ref( + // selected_target_holder.mover + // ); + + // std::cout << "(" << reinterpret_cast(selected_target_holder.mover) << ") Target: " + // << selected_target.name->c_str() << " at " + // << selected_target.world_position.x << ", " + // << selected_target.world_position.y << ", " + // << selected_target.world_position.z << std::endl; + + // } else { + // std::cout << "Got no target." << std::endl; + // } // } // auto& item_properties = fugg::module_ref>(0x00035194); diff --git a/fugg-client/src/client.h b/fugg-client/src/client.h index da70cc3..4bd5990 100644 --- a/fugg-client/src/client.h +++ b/fugg-client/src/client.h @@ -1,23 +1,10 @@ #include namespace fugg { - class Client { - Client(); + // class Client { + // Client(); - public: - static Client& instance(); + // public: - Client(Client const&) = delete; - void operator=(Client const&) = delete; - - void initialise(); - // Execute the `main` function of the flyff-client. - int main() const; - - template - T* allocate(size_t size); - - template - void deallocate(T* ptr); - }; + // }; } \ No newline at end of file diff --git a/fugg-client/src/export/callback.cpp b/fugg-client/src/export/callback.cpp index 850e633..fce32fd 100644 --- a/fugg-client/src/export/callback.cpp +++ b/fugg-client/src/export/callback.cpp @@ -139,6 +139,9 @@ WASM_IMPORT_IMPL(env, _emscripten_set_focusout_callback_on_thread) = [](u32 a, u emscripten_set_focusout_callback_on_thread(target, user_data, use_capture, hook, target_thread) ); }; + +extern void on_keyup_hook(int, const EmscriptenKeyboardEvent*, void*); + u32 original_keyup_callback = 0; /* import: 'a' 'Da' */ /* _emscripten_set_keyup_callback_on_thread */ @@ -157,6 +160,9 @@ WASM_IMPORT_IMPL(env, _emscripten_set_keyup_callback_on_thread) = [](u32 a, u32 original_keyup_callback = callback_; auto hook = [](int eventType, const EmscriptenKeyboardEvent* event, void* userData) { + // Call hook + on_keyup_hook(eventType, event, userData); + assert(original_keyup_callback); const auto& callback = fugg::function_ref(original_keyup_callback); diff --git a/fugg-client/src/export/embind.cpp b/fugg-client/src/export/embind.cpp index 0d233ba..4cae73c 100644 --- a/fugg-client/src/export/embind.cpp +++ b/fugg-client/src/export/embind.cpp @@ -365,7 +365,7 @@ WASM_IMPORT_IMPL(env, __embind_register_function) = [](u32 a, u32 arg_count, u32 #endif // if(std::string(name) != "platform_text_edited") { - // emscripten::internal::_embind_register_function(name, arg_count, arg_types, signature, invoker, function); + // emscripten::internal::_embind_register_function(name, arg_count, arg_types, signature, invoker, function); // } else { std::cout << "Skipping registration of " << static_cast(name) << " with " << arg_count << " arguments." << std::endl; diff --git a/fugg-client/src/export/env.cpp b/fugg-client/src/export/env.cpp index 831ccea..46684fc 100644 --- a/fugg-client/src/export/env.cpp +++ b/fugg-client/src/export/env.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -49,6 +50,7 @@ WASM_IMPORT_IMPL(env, _emscripten_cancel_main_loop) = []() { /* import: 'a' 'ab' */ // "ab": "_emscripten_async_wget_data", WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32 onload_, u32 onerror_) { + auto& neuz = flyff::Neuz::instance(); // This function is only called by the flyff runtime, so we introduce // stubs to refer the onload and onerror on to actual flyff functions. // See `onload_stub` and `onerror_stub`. @@ -95,7 +97,7 @@ WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32 delete interop_data; }; - const auto& url = fugg::ModulePointer { url_ }; + const auto& url = fugg::module_ref(url_); const auto data = new wget_data { .onload = onload_, @@ -114,7 +116,7 @@ WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32 // std::cout << "Client: Downloading " << static_cast(url) << std::endl; // This function can allocate, which will call the Flyff runtime allocate. - emscripten_async_wget_data(url, data, onload_stub, onerror_stub); + emscripten_async_wget_data(&url, data, onload_stub, onerror_stub); }; /* import: 'a' 'fb' */ // "fb": "_emscripten_set_element_css_size", diff --git a/fugg-client/src/export/platform.cpp b/fugg-client/src/export/platform.cpp index 02d6099..1978b43 100644 --- a/fugg-client/src/export/platform.cpp +++ b/fugg-client/src/export/platform.cpp @@ -84,7 +84,7 @@ void platform_websocket_close_hook(emscripten::val event) { void platform_websocket_message_hook(emscripten::val event) { // std::cout << "platform_websocket_message: Got " << event["data"]["byteLength"].as() << " bytes" << std::endl; - + struct Test { emscripten::EM_VAL handle; }; diff --git a/fugg-client/src/main.cpp b/fugg-client/src/main.cpp index 359e5be..85f4a9d 100644 --- a/fugg-client/src/main.cpp +++ b/fugg-client/src/main.cpp @@ -4,7 +4,9 @@ #include #include -#include "client.h" +// #include "client.h" + +#define TRACE_ALLOC 0 void *malloc (size_t __size) { // void * operator new(std::size_t __size) { @@ -56,14 +58,15 @@ void free (void *__ptr) { } int main() { + using flyff::Neuz; + std::cout << "Hello world from fugg!" << std::endl; std::cout << "Initialising runtime... "; - auto& client = fugg::Client::instance(); - client.initialise(); + auto& neuz = Neuz::instance(); std::cout << "Ok!" << std::endl; std::cout << "Starting Flyff..." << std::endl; - return client.main(); + return neuz.main(); } \ No newline at end of file