parent
144838d708
commit
a5416d098c
|
|
@ -1,6 +1,8 @@
|
|||
add_library (
|
||||
flyff-api
|
||||
"src/flyff.cpp"
|
||||
"src/Neuz.cpp"
|
||||
"src/import.cpp"
|
||||
"include/flyff.h"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <fugg.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#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<void>) == 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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <fugg.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#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;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#include "Neuz.h"
|
||||
|
||||
#include <client.h>
|
||||
|
||||
// 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
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <client.h>
|
||||
|
||||
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<void>) == 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();
|
||||
};
|
||||
}
|
||||
|
|
@ -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
|
||||
};
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
template <const size_t kSize>
|
||||
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<typename I, typename O>
|
||||
struct ArrowProxy {
|
||||
I value;
|
||||
|
||||
O* operator->() {
|
||||
return reinterpret_cast<O*>(&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<uintptr_t>(&(*memory)->data[offset]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* to_outside(T* offset) const {
|
||||
return reinterpret_cast<T*>(
|
||||
to_outside(
|
||||
reinterpret_cast<uintptr_t>(offset)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
static auto kMemory = Memory(&Z_clientZ_memory);
|
||||
|
||||
class Table {};
|
||||
|
||||
static const auto& kTable = &Z_clientZ_table;
|
||||
|
||||
template <typename T>
|
||||
class Pointer {
|
||||
uintptr_t offset;
|
||||
|
||||
public:
|
||||
T* operator->() { return reinterpret_cast<T*>(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<std::string*>(©);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
#include <wasm-rt.h>
|
||||
#include <client.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<fugg::detail::RawBasicString>();
|
||||
auto id_ = std::make_unique<fugg::String>(id);
|
||||
|
||||
|
|
@ -59,7 +17,53 @@ fugg::String translate(const std::string& id) {
|
|||
fugg::RuntimePointer<fugg::String>(id_.get()).as_raw()
|
||||
);
|
||||
|
||||
return *reinterpret_cast<fugg::String*>(result.get());
|
||||
return *reinterpret_cast<flyff::String*>(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<fugg::String>(message);
|
||||
auto color_ = std::make_unique<flyff::Color>(color);
|
||||
|
||||
const auto& kUnknownParam1 = fugg::module_ref<uintptr_t>(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<fugg::String>(message_.get()).as_raw(),
|
||||
fugg::RuntimePointer<flyff::Color>(color_.get()).as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
void send_packet(std::vector<uint8_t> payload) {
|
||||
struct Vector {
|
||||
uintptr_t begin;
|
||||
uintptr_t end;
|
||||
uintptr_t capacity;
|
||||
};
|
||||
|
||||
auto raw_payload = reinterpret_cast<const Vector*>(&payload);
|
||||
// Copy the message into a new ptr
|
||||
auto payload_ = std::unique_ptr<Vector>(new Vector {
|
||||
.begin = fugg::RuntimePointer<uintptr_t>(raw_payload->begin).as_raw(),
|
||||
.end = fugg::RuntimePointer<uintptr_t>(raw_payload->end).as_raw(),
|
||||
.capacity = fugg::RuntimePointer<uintptr_t>(raw_payload->capacity).as_raw()
|
||||
});
|
||||
|
||||
flyff::api::w2c_f2300(
|
||||
fugg::RuntimePointer<Vector>(payload_.get()).as_raw()
|
||||
);
|
||||
|
||||
flyff::api::w2c_f2296(
|
||||
payload_->begin,
|
||||
payload_->end - payload_->begin
|
||||
);
|
||||
}
|
||||
|
||||
#include <unordered_set>
|
||||
|
|
@ -69,11 +73,130 @@ fugg::String translate(const std::string& id) {
|
|||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
void before_main_loop() {
|
||||
auto& client = fugg::Client::instance();
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
const auto& test = translate("ids_textclient_cannot_dropmoney");
|
||||
std::cout << test->c_str() << std::endl;
|
||||
#include <cstddef>
|
||||
|
||||
template<typename T>
|
||||
void packet_push(std::vector<uint8_t>& 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<uint8_t> packet;
|
||||
// Not sure yet about these
|
||||
packet.insert(packet.end(), { 0x01, 0x94 });
|
||||
packet.insert(packet.end(), { 0x4a, 0x64 });
|
||||
|
||||
packet_push<uint32_t>(packet, from_slot);
|
||||
packet_push<uint32_t>(packet, to_slot);
|
||||
|
||||
send_packet(packet);
|
||||
}
|
||||
|
||||
void use_item_in_inventory(const uint32_t& slot) {
|
||||
std::vector<uint8_t> packet;
|
||||
// Not sure yet
|
||||
packet.insert(packet.end(), { 0x10, 0xb0 });
|
||||
// Same as move_item_in_inventory
|
||||
packet.insert(packet.end(), { 0x4a, 0x64 });
|
||||
|
||||
packet_push<uint32_t>(packet, slot);
|
||||
// Unknown yet
|
||||
packet_push<uint32_t>(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<uint8_t> packet;
|
||||
packet.push_back(0x04);
|
||||
packet.push_back(0xb0);
|
||||
|
||||
// Same as move_item_in_inventory
|
||||
packet.insert(packet.end(), { 0x4a, 0x64 });
|
||||
|
||||
packet_push<float>(packet, x);
|
||||
packet_push<float>(packet, y);
|
||||
packet_push<float>(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<uint8_t> 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<uint32_t>(packet, message.length());
|
||||
// Write message
|
||||
for(const auto& character : message) {
|
||||
packet_push<uint8_t>(packet, character);
|
||||
}
|
||||
// Unknown 1
|
||||
packet_push<uint32_t>(packet, 0);
|
||||
// Unknown 2
|
||||
packet_push<uint32_t>(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<flyff::Mover>(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<ObjectHolder>(
|
||||
// w2c_f208(player.selected_target_id)
|
||||
// );
|
||||
// static_assert(bla == test, "OMG");
|
||||
|
||||
// auto& selected_target = fugg::module_ref<flyff::Mover>(
|
||||
// selected_target_holder.mover
|
||||
// );
|
||||
// // static_assert(offsetof(Mover, name) == 2020, "ASD");
|
||||
|
||||
// std::cout << "(" << reinterpret_cast<void*>(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<ObjectHolder>(
|
||||
// flyff::api::w2c_f208(player.selected_target)
|
||||
// );
|
||||
|
||||
// auto& selected_target = fugg::module_ref<Mover>(
|
||||
// selected_target_holder.mover
|
||||
// );
|
||||
|
||||
// std::cout << "(" << reinterpret_cast<void*>(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<fugg::Vector<flyff::ItemProperty>>(0x00035194);
|
||||
|
|
|
|||
|
|
@ -1,23 +1,10 @@
|
|||
#include <fugg.h>
|
||||
|
||||
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<typename T>
|
||||
T* allocate(size_t size);
|
||||
|
||||
template<typename T>
|
||||
void deallocate(T* ptr);
|
||||
};
|
||||
// };
|
||||
}
|
||||
|
|
@ -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<em_key_callback_func>(original_keyup_callback);
|
||||
|
|
|
|||
|
|
@ -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<const char*>(name)
|
||||
<< " with " << arg_count << " arguments." << std::endl;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <wasm-rt.h>
|
||||
#include <client.h>
|
||||
#include <flyff.h>
|
||||
#include <fugg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -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<const char> { url_ };
|
||||
const auto& url = fugg::module_ref<const char>(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<const char*>(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",
|
||||
|
|
|
|||
|
|
@ -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<unsigned long>() << " bytes" << std::endl;
|
||||
|
||||
|
||||
struct Test {
|
||||
emscripten::EM_VAL handle;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
#include <fugg.h>
|
||||
#include <flyff.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
Reference in New Issue