1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# Lodestone client — cross-compiled from Linux to a Windows DLL with mingw.
#
# The C++ runtime is linked statically on purpose. A DLL that depends on
# libstdc++-6.dll cannot be injected into a game that has never heard of mingw:
# LoadLibrary fails with "a dependency is missing". Linking with g++ (rather
# than gcc) is what makes -static-libstdc++ actually take effect.
CXX := x86_64-w64-mingw32-g++
CC := x86_64-w64-mingw32-gcc
STRIP := x86_64-w64-mingw32-strip
IMGUI := third_party/imgui
MINHOOK := third_party/minhook
BUILD := build
TARGET := $(BUILD)/lodestone_client.dll
INJECT := $(BUILD)/lodestone-inject.exe
# jni.h includes "jni_md.h" and the JDK keeps its own under include/<os>. We
# point at src/jni_md instead and never add include/linux, so the Windows
# definitions win — otherwise jint would be a Linux `int` in a Windows DLL.
JAVA_INC ?= /opt/java/current/include
INCLUDES := -Isrc -Isrc/jni_md -I$(JAVA_INC) \
-I$(IMGUI) -I$(IMGUI)/backends -I$(MINHOOK)/include
DEFINES := -DWIN32_LEAN_AND_MEAN -DNOMINMAX -DUNICODE -D_UNICODE
# -MMD -MP emits a .d beside each .o listing the headers it included. Nearly
# all of this client lives in headers, so without them `make` sees only the two
# .cpp files and quietly does nothing after a header edit — leaving a stale DLL
# that looks freshly built.
CXXFLAGS := -std=c++20 -O2 -Wall -Wextra -Wno-unused-parameter -fno-rtti -MMD -MP \
$(INCLUDES) $(DEFINES)
CFLAGS := -O2 -Wall -MMD -MP $(INCLUDES) $(DEFINES)
# No winpthread: everything that needs a thread uses CreateThread, which keeps
# the static link to just libstdc++ and libgcc.
LDFLAGS := -shared -static-libgcc -static-libstdc++ \
-Wl,--exclude-all-symbols \
-lopengl32 -lgdi32 -luser32 -lkernel32
CXX_SRC := src/main.cpp src/overlay.cpp \
$(IMGUI)/imgui.cpp $(IMGUI)/imgui_draw.cpp \
$(IMGUI)/imgui_tables.cpp $(IMGUI)/imgui_widgets.cpp \
$(IMGUI)/backends/imgui_impl_opengl3.cpp
C_SRC := $(MINHOOK)/src/hook.c $(MINHOOK)/src/buffer.c \
$(MINHOOK)/src/trampoline.c $(MINHOOK)/src/hde/hde64.c
CXX_OBJ := $(patsubst %,$(BUILD)/%.o,$(CXX_SRC))
C_OBJ := $(patsubst %,$(BUILD)/%.o,$(C_SRC))
.PHONY: all clean deps
all: $(TARGET) $(INJECT)
# The loader is a plain console executable: no ImGui, no MinHook, just the
# process walk and the remote LoadLibraryW.
$(INJECT): $(BUILD)/inject/main.cpp.o
@mkdir -p $(dir $@)
$(CXX) $^ -o $@ -static-libgcc -static-libstdc++ -lpsapi -luser32 -lkernel32
$(TARGET): $(CXX_OBJ) $(C_OBJ)
@mkdir -p $(dir $@)
$(CXX) $^ -o $@ $(LDFLAGS)
@echo "--- dependencies (libstdc++-6.dll here means the static link failed) ---"
@x86_64-w64-mingw32-objdump -p $@ | grep "DLL Name" | sort -u
$(BUILD)/%.cpp.o: %.cpp
@mkdir -p $(dir $@)
$(CXX) $(CXXFLAGS) -c $< -o $@
$(BUILD)/%.c.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf $(BUILD)
# Pulled in last, and with a leading '-' so a first build (no .d files yet) is
# not an error.
-include $(CXX_OBJ:.o=.d) $(C_OBJ:.o=.d) $(BUILD)/inject/main.cpp.d