專案總覽:.sln 與 .vcxproj 是什麼

在開始看程式碼之前,我們要先搞清楚「這個專案長什麼樣子」。打開 Ezorsia V2 的資料夾,你會看到兩個很重要的檔案:Ezorsia V2.slnezorsia\ezorsia.vcxproj。這篇筆記就來說明它們各自代表什麼意思。


一、.sln 是什麼?「工廠的大門」

.slnSolution(方案) 檔的副檔名,由 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 是什麼?「廠房的建造藍圖」

.vcxprojVisual 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.cppDLL 入口點。Windows 把 DLL 載入時,第一個執行的地方。負責呼叫初始化流程。
dinput8.cppProxy 轉發。把遊戲對 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」,非常重要:

設定名稱白話解釋
ConfigurationTypeDynamicLibrary這是 DLL 專案,不是 .exe。DynamicLibrary 就是動態函式庫,編譯結果副檔名為 .dll。
TargetNamedinput8輸出檔名叫 dinput8.dll。如果你改成別的名字,遊戲就不會自動載入它。
OutDir$(SolutionDir)\out\$(Configuration)\編譯完成後,dinput8.dll 會出現在 out\Release\ 資料夾,你要手動複製到遊戲資料夾。
LanguageStandardstdcpp17使用 C++17 標準。這是目前主流的現代 C++ 版本,支援較多便利語法。

連結了哪些函式庫?

什麼是「連結函式庫(.lib)」?

就像廚師不用自己養豬,只需要從肉品供應商進貨一樣——程式設計師也不用自己實作所有功能,可以「連結」現成的函式庫。.lib 檔就是這些供應商提供的貨。

函式庫全名提供的功能
Winmm.libWindows Multimedia計時器、音效播放等多媒體功能
Ws2_32.libWindows Socket 2 (32-bit)網路連線(TCP/UDP),Proxy 連線用到
detours.libMicrosoft DetoursHook 的核心,攔截並替換函式的能力

六、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,登入器生效

延伸閱讀