專案總覽:.sln 與 .vcxproj 是什麼
在開始看程式碼之前,我們要先搞清楚「這個專案長什麼樣子」。打開 Ezorsia V2 的資料夾,你會看到兩個很重要的檔案:Ezorsia V2.sln 和 ezorsia\ezorsia.vcxproj。這篇筆記就來說明它們各自代表什麼意思。
一、.sln 是什麼?「工廠的大門」
.sln 是 Solution(方案) 檔的副檔名,由 Visual Studio 建立。
用一個比喻來說:
比喻:工廠與廠區
把整個開發環境想像成一座工廠園區。
- .sln 是工廠大門:你雙擊它,整個工廠就打開了。
- 一個 .sln 裡面可以有多個子專案(就像一個園區可以有多棟廠房)。
- 每一棟廠房各自負責生產不同的東西。
實際上,.sln 本身不包含任何程式碼,它只是一份**「清單」**,告訴 Visual Studio:「嘿,這個方案底下有哪些子專案,各在哪個資料夾」。
Ezorsia V2.sln 的核心內容長這樣:
Project("...") = "ezorsia", "ezorsia\ezorsia.vcxproj", "{0F213461-...}"
EndProject
這一行的意思是:「這個方案有一個子專案,名叫 ezorsia,它的設定檔放在 ezorsia\ezorsia.vcxproj。」
實際操作
以後要開啟專案,永遠雙擊 .sln 檔,不要直接點 .vcxproj。雙擊 .sln 才能讓 Visual Studio 把整個環境(包含設定、編譯選項)全部一起載入。
二、.vcxproj 是什麼?「廠房的建造藍圖」
.vcxproj 是 Visual Studio C++ 專案(Project) 檔,是真正告訴編譯器「怎麼蓋出這棟廠房」的藍圖。
它記錄了三件事:
| 問題 | .vcxproj 的回答(Ezorsia 的值) |
|---|---|
| 要編譯哪些 .cpp 檔? | dllmain.cpp、Client.cpp、Memory.cpp… |
| 要連結哪些外部函式庫? | Winmm.lib、Ws2_32.lib、detours.lib |
| 輸出檔案叫什麼、放哪裡? | dinput8.dll,放到 out\Release\ |
小心!輸出的 DLL 名稱不叫 ezorsia.dll
專案名稱雖然叫
ezorsia,但 vcxproj 裡設定了TargetName = dinput8,所以編譯出來的檔案叫做dinput8.dll,不是ezorsia.dll。這是故意的——MapleStory 啟動時會自動去讀取遊戲資料夾裡的
dinput8.dll(DirectInput 8 的系統 DLL),我們把自己的 DLL 命名成一樣的名字,遊戲就會把它當作系統 DLL 載入。這就是 DLL Proxy 的核心手法。
三、本專案結構一覽
這個 Solution 只有一個子專案,結構如下:
Ezorsia V2.sln ← 雙擊這個開啟 VS
└── ezorsia\
├── ezorsia.vcxproj ← C++ 專案設定檔
├── ezorsia.vcxproj.filters ← VS 裡的資料夾分組顯示
│
├── [核心機制]
│ ├── dllmain.cpp ← DLL 入口點
│ ├── dinput8.h / .cpp ← Proxy 轉發器
│ ├── MainMain.h / .cpp ← 初始化與設定讀取
│ ├── Client.h / .cpp ← 客戶端修改主體
│ ├── Memory.h / .cpp ← 記憶體讀寫工具
│ ├── AddyLocations.h ← 記憶體地址表
│ ├── AutoTypes.h ← MapleStory 型別定義
│ ├── codecaves.h ← Code Cave 實作
│ ├── ReplacementFuncs.h ← 函式替換宣告
│ ├── INIReader.h ← config.ini 讀取器
│ ├── stdafx.h / .cpp ← 預先編譯標頭
│ └── targetver.h ← Windows 版本目標
│
├── [MapleStory 型別定義]
│ └── MapleClientCollectionTypes\
│ ├── ZAllocEx.h / .cpp ← 自訂記憶體分配器
│ ├── ZAllocBase.h
│ ├── ZArray.h / ZList.h / ZMap.h
│ ├── ZRef.h / ZRefCounted.h
│ ├── ZXString.h ← 寬字串型別
│ ├── ZtlSecure.h / TSecType.h
│ └── ZFatalSection.h ← 臨界區(執行緒鎖)
│
├── [Microsoft Detours 函式庫]
│ ├── detours.h ← Hook 主函式庫標頭
│ ├── detver.h ← 版本定義
│ └── syelog.h ← 除錯日誌(Detours 附屬)
│
└── [嵌入資源]
├── resource.h / Resource.rc ← 資源腳本
├── config.ini ← 嵌入的設定檔
├── EzorsiaV2_UI.wz ← 嵌入的 UI 資源
└── MapleEzorsiaV2wzfiles.img ← 嵌入的 IMG 資源
四、各 .cpp 檔的職責一覽
什麼是 .cpp 檔?
.cpp是 C++ 的程式碼本體檔,你可以把它想像成工廠裡的生產線。每一條生產線負責一件事。編譯器會把所有 .cpp 合在一起,生產出最終的dinput8.dll。
| 檔案 | 職責說明 |
|---|---|
dllmain.cpp | DLL 入口點。Windows 把 DLL 載入時,第一個執行的地方。負責呼叫初始化流程。 |
dinput8.cpp | Proxy 轉發。把遊戲對 DirectInput 8 的呼叫轉發給真正的系統 DLL,確保鍵盤/搖桿正常運作。 |
MainMain.cpp | 初始化主體。讀取 config.ini 設定、決定開啟哪些功能、啟動其他模組。 |
Client.cpp | 客戶端修改核心。所有對 MapleStory 的記憶體修改、封包攔截、功能注入都在這裡。 |
Memory.cpp | 記憶體工具。提供讀取/寫入/掃描記憶體的通用函式,供其他模組呼叫。 |
ZAllocEx.cpp | 自訂記憶體分配器。讓 C++ 程式碼能使用與 MapleStory 相容的記憶體管理方式。 |
stdafx.cpp | 預先編譯標頭觸發檔。只有一行 #include "stdafx.h",用途是讓 VS 建立 PCH 快取以加速編譯。 |
五、關鍵 vcxproj 設定解讀
這幾個設定值決定了「這個專案能不能正確編譯成可用的 DLL」,非常重要:
| 設定名稱 | 值 | 白話解釋 |
|---|---|---|
ConfigurationType | DynamicLibrary | 這是 DLL 專案,不是 .exe。DynamicLibrary 就是動態函式庫,編譯結果副檔名為 .dll。 |
TargetName | dinput8 | 輸出檔名叫 dinput8.dll。如果你改成別的名字,遊戲就不會自動載入它。 |
OutDir | $(SolutionDir)\out\$(Configuration)\ | 編譯完成後,dinput8.dll 會出現在 out\Release\ 資料夾,你要手動複製到遊戲資料夾。 |
LanguageStandard | stdcpp17 | 使用 C++17 標準。這是目前主流的現代 C++ 版本,支援較多便利語法。 |
連結了哪些函式庫?
什麼是「連結函式庫(.lib)」?
就像廚師不用自己養豬,只需要從肉品供應商進貨一樣——程式設計師也不用自己實作所有功能,可以「連結」現成的函式庫。
.lib檔就是這些供應商提供的貨。
| 函式庫 | 全名 | 提供的功能 |
|---|---|---|
Winmm.lib | Windows Multimedia | 計時器、音效播放等多媒體功能 |
Ws2_32.lib | Windows Socket 2 (32-bit) | 網路連線(TCP/UDP),Proxy 連線用到 |
detours.lib | Microsoft Detours | Hook 的核心,攔截並替換函式的能力 |
六、MapleClientCollectionTypes 子資料夾是什麼?
來源:社群專案 MapleClientEditTemplate
MapleClientCollectionTypes\裡的所有 .h 檔,都是來自 RageZone 社群整理的開源專案 MapleClientEditTemplate。它把 MapleStory 遊戲內部使用的各種資料結構,用 C++ 重新定義出來,讓開發者能直接操作。
裡面的型別命名規律都以 Z 開頭,這是 MapleStory 引擎(基於 Nexon 自研的 ZLib 架構)的命名慣例:
| 型別 | 類比 | 用途 |
|---|---|---|
ZArray<T> | 動態陣列(如 Python list) | 存放一連串同類型的物件 |
ZList<T> | 鏈結串列 | 可快速插入/刪除的序列 |
ZMap<K,V> | 字典(如 Python dict) | 鍵值對應查詢 |
ZXString<T> | 寬字元字串 | 存放中文、日文等多位元組文字 |
ZRef<T> | 智慧指標 | 安全的物件參考,自動管理記憶體 |
ZAllocEx | 自訂分配器 | 讓 C++ 物件使用 MapleStory 自己的記憶體堆 |
不需要修改這個資料夾
這些型別定義是「地基」,Ezorsia 的功能程式碼建立在它們之上。除非你在追查某個 MapleStory 內部資料結構的問題,否則不需要動這個資料夾裡的任何檔案。
七、整體流程小結
你雙擊 Ezorsia V2.sln
↓
Visual Studio 讀取 ezorsia.vcxproj
↓
按下「Build(建置)」
↓
編譯器把所有 .cpp 編譯 → 連結 Winmm.lib / Ws2_32.lib / detours.lib
↓
輸出 dinput8.dll 到 out\Release\
↓
你把 dinput8.dll 複製到 MapleStory 遊戲資料夾
↓
遊戲啟動,自動載入 dinput8.dll,登入器生效
延伸閱讀
- 03_dinput8代理DLL原理 — Phase 1:DLL Proxy 的原理,為什麼要叫 dinput8.dll
- 02_dllmain.cpp_DLL入口點 — DLL 被載入後,第一行程式碼發生了什麼
- 03_dinput8.cpp_Proxy載入器 — Proxy 如何把 DirectInput 呼叫轉給真正的系統 DLL
- 03_AddyLocations.h_地址表解析 — Phase 3:AddyLocations.h 裡的地址怎麼找來的
- 01_config.ini設定系統 — Phase 7:INIReader 怎麼讀取嵌入的設定檔