Skip to content
riyukuro edited this page Nov 10, 2026 · 24 revisions

MS2Recomp

MS2Recomp is a work-in-progress recompilation of the MapleStory 2 client (KMS2 development build, x64, April 2022). Functions recovered from the original executable are rewritten as C++ and compiled into a replacement executable. Most recovered functions match the original machine code byte for byte. The project also builds a development proxy DLL that redirects calls into the recovered code.

The full executable can be built in Visual Studio with the required toolchain and SDKs, without needing the original client executable. The repository does not include the client, game assets, Gamebryo source, or other SDKs; consult the build guide for prerequisites.

Progress

The table below is regenerated on each publish, along with the progress image.

Area Functions Matched Equivalent Done
Game · ms2 176,747 176,600 (99.9%) 142 (0.1%) 100.0%
Runtime & middleware 24,765 24,009 (96.9%) 639 (2.6%) 99.5%
Gamebryo engine 16,881 16,841 (99.8%) 27 (0.2%) 99.9%
Game framework · egf 13,113 13,101 (99.9%) 11 (0.1%) 100.0%
Libraries 6,731 6,372 (94.7%) 22 (0.3%) 95.0%
Foundation 13,065 13,061 (100.0%) 4 (0.0%) 100.0%
Imports 782 780 (99.7%) 1 (0.1%) 99.9%
Total 252,084 250,764 (99.5%) 846 (0.3%) 99.8%

Link aliases: 5 left: 0 /alternatename lines in the no-exe build's data/fullexe/plain/alias.rsp and 5 #pragma comment(linker, "/alternatename:...") lines in 5 source files of the same build. The linker uses an alias to send a call that the recovered code makes under a placeholder name or signature to the real function, or to bind a placeholder data name to the real object. An alias goes away once every user takes the real declaration; the goal is 0. The glue file held 19,884 on 2026-10-31. The no-exe build no longer needs any alias lines in that file; the rest are in the sources.

The totals exclude Nexon Messenger functions, which are stubbed by design. See the repository's README for the full breakdown and notes on functions that are not counted as missing.

Recent fixes that the byte-match checks can't see (merge 72): Knight basic attacks did not hit (an inline view read the wrong flag), the IME's TSF interface IDs were 8 bytes instead of 16, the ASTriggerState vftable had 16 of its 25 slots, four MFC message-map entries were wrong, two WorldService map lookups got the reference count wrong (a leak and an over-release), a fly-by camera copied an uninitialised setting, and three float constants were 1 ULP off.

Recent fixes that the byte-match checks can't see (merge 73): equipping an item crashed the client (sword dragged onto the Character window), the Merat market search read its job and sort values from each other's keys, the tooltip texts stayed stale after a string reload, a failed Razer Chroma SDK load left the SDK half-loaded, and item event broadcasts also reloaded the character-create dialog's customize controller. The equip crash is the only one seen in the client; the other effects come from reading the code.

Recent fixes that the byte-match checks can't see (merge 74): the mastery dialog's craft boxes had their Craft and Cancel labels swapped and the dungeon search page swapped its random and custom titles, four formatted strings printed large unsigned values as negative, the item trade limit came from the lowest active event instead of the highest, the world service's visible-object set held only scene-node pointers instead of whole records, a new world-service visibility entry started in the wrong group, the cube map information service mixed allocators across three maps and cleared one map's entity ids as smart pointers, an AS2 object's string hashes released some children twice on destroy, an AS3 XML describeType parent-type check and a MovieClip frame-script hole fill now follow the original, and a CRI audio decoder step added in double instead of float. None was seen in the client; the effects come from reading the code.

Merge 75 finished the link alias removal: the recovered code now names the real functions, vftables and data objects directly, the no-exe build needs no alias file, and 9 aliases remain in the sources, down from 19,884 on 2026-10-31. The no-exe Visual Studio / CMake build also makes most of its glue from the checkout at configure time (the game object list, compile commands and flags, function order and data stub), so a commit after the last glue refresh builds without the original exe too, unless it adds an engine or library unit; two link tables still come from a maintainer's smoke-passed build and are refreshed with each publish. No new fixes the byte-match checks can't see landed in this merge. The matched count dropped by 5 and equivalent rose by 5 only because the matcher now pairs one renamed call target with a byte-identical twin; the call in the built executable is unchanged.

Merge 76 is about names: 1,422 game functions that were still called FUN_<address> now have descriptive names, and three placeholder classes have real names. Two independent naming passes had to agree on each name, and a full rebuild checked the result without losing an exact match. The default build needs no original executable, and this was checked end to end: a clean checkout configured with the stock linux preset and no options built the whole client (3,734 steps, no unresolved symbol), and the result ran into the game field. Link aliases in the sources went from 9 to 5. The 5 functions that merge 75 moved from matched to equivalent are byte matches again. No new fixes the byte-match checks can't see landed in this merge.

Merge 77 carries three more naming waves: 4,997 more game functions that were still called FUN_<address> now have descriptive names. Two independent naming passes had to agree on each name, and a full rebuild checked the result: no function changed state and no exact match was lost, so the table above is unchanged. 42 of the 45 small identity functions that the matcher had paired with hook-DLL helper names are now bound to the standard-library names their callers use (3 left). The no-exe default build of the merged tree was rebuilt from a clean checkout with the stock linux preset and no options (3,734 steps, no unresolved symbol), and the result ran into the game field. Link aliases stay at 5.

Merge 78 carries one more naming wave: 1,439 more game functions that were still called FUN_<address> now have descriptive names. Two independent naming passes had to agree on each name, and a full rebuild checked the result: no function changed state and no exact match was lost, so the totals above are unchanged; three standard-library functions whose new names place them in the game framework moved there from Foundation. One proposed name was taken back because it clashed with Lua binding helpers in the engine code. A step back, not yet fixed: 10 small identity functions are now paired with hook-DLL helper names, against 3 at the last publish; the 7 new ones are still to be bound to the standard-library names their callers use. The no-exe default build of the merged tree was rebuilt from a clean checkout with the stock linux preset and no options (3,734 steps, no unresolved symbol), and the result ran into the game field. Link aliases stay at 5.

Merge 79 finishes the step back that merge 78 reported: the 10 small identity functions that were paired with hook-DLL helper names are now bound to the standard-library names their callers use, and none is left in the status table, the symbol table or the no-exe build's link order. A full rebuild checked the result: no function changed state and no exact match was lost, so the table above is unchanged. The no-exe default build of the merged tree was rebuilt from a clean checkout with the stock linux preset and no options (3,734 steps, no unresolved symbol), and the result ran into the game field. No new fixes the byte-match checks can't see landed in this merge. Link aliases stay at 5.

MS2Recomp is now licensed under the GNU GPL v3 with an attribution requirement; see LICENSE and NOTICE.

Functions rose by 458 in merge 73: 458 atexit destructors, real functions of the original that no earlier table listed, are now counted.

Guides

  • How Matching Works — matching terminology, symbols, and compiler setup.
  • Codegen Patterns — practical clues for recovering source shapes from compiler output.
  • Schema Atlas — index for generated game data, packet, and type references.

Project documentation: README · Building · Contributing.

Clone this wiki locally