# port_logic — mirror of the 40250 client logic (extension/src/port//.{h,cpp}). # No godot-cpp dependency: libmtgodot links it, and it also builds on its own (top-level # -DMTGODOT_BUILD_EXTENSION=OFF -DMTGODOT_BUILD_PORT=ON) for targets without an extension build. # See docs/PORT-PLAN.md batch 2A. file(GLOB_RECURSE MT_PORT_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file(GLOB_RECURSE MT_PORT_HEADERS CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) if(WIN32) # Stand-ins for Windows SDK headers; on Windows the real ones are used. list(FILTER MT_PORT_HEADERS EXCLUDE REGEX "/common/shim/win32/") endif() # The script layer needs the embedded interpreter (mt3p::python), which has no Windows build yet # (PORT-PLAN 批次 2P step 4). Without it, ScriptLib and its shims are left out. # The units outside ScriptLib that reach it: UserInterface/StdAfx.h includes ScriptLib/StdAfx.h (as the # original PCH does), and PythonPackModule.cpp is a Python module. Both go with it. set(MT_PORT_NEEDS_PYTHON "/ScriptLib/|/UserInterface/StdAfx\\.h|/UserInterface/PythonPackModule\\.cpp") if(NOT TARGET mtpython) list(FILTER MT_PORT_SOURCES EXCLUDE REGEX "${MT_PORT_NEEDS_PYTHON}") list(FILTER MT_PORT_HEADERS EXCLUDE REGEX "${MT_PORT_NEEDS_PYTHON}|/common/shim/sdk/Python-2\\.7/") endif() add_library(port_logic STATIC ${MT_PORT_SOURCES}) target_include_directories(port_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # 40250 system headers the ported sources keep including verbatim: D3D8/D3DX/Miles SDK types everywhere, # Windows/CRT ones only where the platform has none. set(MT_PORT_SHIMS ${CMAKE_CURRENT_SOURCE_DIR}/common/shim/sdk) if(NOT WIN32) list(APPEND MT_PORT_SHIMS ${CMAKE_CURRENT_SOURCE_DIR}/common/shim/win32) endif() target_include_directories(port_logic PUBLIC ${MT_PORT_SHIMS}) # Libraries 40250 links that are vendored as-is: (EterBase/lzo.h), # (EterBase/cipher.h), (ScriptLib). target_link_libraries(port_logic PUBLIC mt3p::minilzo mt3p::cryptopp) if(TARGET mtpython) target_link_libraries(port_logic PUBLIC mt3p::python) endif() # 40250 sources carry MSVC `#pragma warning(...)` lines verbatim, and non-literal printf formats # (EterImageLib/StdAfx.h) that the Android toolchain turns into errors. set(MT_PORT_WARNING_FLAGS) if(NOT MSVC) set(MT_PORT_WARNING_FLAGS -Wno-unknown-pragmas -Wno-format-security) endif() target_compile_options(port_logic PUBLIC ${MT_PORT_WARNING_FLAGS}) target_compile_features(port_logic PUBLIC cxx_std_20) # Armadillo nanomite markers (StdAfx.h `__asm _emit` jumps over a signature): x86-32 MSVC inline asm that no # target here accepts, and a no-op without the Armadillo wrapper, so they expand to nothing. target_compile_definitions(port_logic PUBLIC "NANOBEGIN=" "NANOEND=") if(MINGW) target_compile_options(port_logic PUBLIC -include ${CMAKE_CURRENT_SOURCE_DIR}/common/Win32MinMax.h) endif() # EterPack/EterPack.cpp includes EterPackKeys.generated.h in place of the two TEA key arrays: the keys are # read from the reference EterPack.cpp at configure time and written into the build tree, never the repository. # Without the reference the arrays are zero and every COMPRESS/SECURITY entry fails to decode. set(MT_40250_SOURCE "$ENV{MT_40250_SOURCE}" CACHE PATH "40250 ClientVS22/source reference root") if(NOT MT_40250_SOURCE) set(MT_40250_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/../../../../40250/Server Client TMP4/ClientVS22/source") endif() set(MT_PORT_GENERATED ${CMAKE_CURRENT_BINARY_DIR}/generated) set(mt_eterpack_ref "${MT_40250_SOURCE}/EterPack/EterPack.cpp") set(mt_eterpack_keys "") if(EXISTS "${mt_eterpack_ref}") file(READ "${mt_eterpack_ref}" mt_ref_text) foreach(arr s_adwEterPackKey s_adwEterPackSecurityKey) string(REGEX MATCH "static DWORD ${arr}\\[\\][ \t\r\n]*=[ \t\r\n]*{[^}]*}" block "${mt_ref_text}") string(REGEX MATCHALL "[0-9]+" values "${block}") list(LENGTH values n) if(NOT n EQUAL 4) message(FATAL_ERROR "port: ${arr} not found in ${mt_eterpack_ref}") endif() list(JOIN values ", " values) string(APPEND mt_eterpack_keys "static DWORD ${arr}[] = { ${values} };\n") endforeach() set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${mt_eterpack_ref}") else() message(WARNING "port: ${mt_eterpack_ref} not found (set MT_40250_SOURCE); EterPack keys are zero") string(APPEND mt_eterpack_keys "static DWORD s_adwEterPackKey[] = { 0, 0, 0, 0 };\n" "static DWORD s_adwEterPackSecurityKey[] = { 0, 0, 0, 0 };\n") endif() file(CONFIGURE OUTPUT ${MT_PORT_GENERATED}/EterPackKeys.generated.h CONTENT "// Generated from the 40250 reference EterPack.cpp by port/CMakeLists.txt; do not commit.\n#pragma once\n${mt_eterpack_keys}") target_include_directories(port_logic PRIVATE ${MT_PORT_GENERATED}) if(WIN32) target_link_libraries(port_logic PUBLIC winmm) endif() # 40250 Distribute|Win32 preprocessor definitions per library (vs_files//.vcxproj), # minus WIN32/_WINDOWS/_LIB/_CRT_SECURE_NO_WARNINGS: Windows-only branches go through platform/, # never through ported logic. UserInterface/Locale_inc.h feature macros come with that header. set(MT_PORT_DEFINES_default NDEBUG) set(MT_PORT_DEFINES_GameLib NDEBUG USE_LOD) set(MT_PORT_DEFINES_UserInterface NDEBUG USE_LOD _DISTRIBUTE) function(mt_port_apply_defines file) file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${file}) string(REGEX REPLACE "/.*" "" lib "${rel}") if(DEFINED MT_PORT_DEFINES_${lib}) set(defs ${MT_PORT_DEFINES_${lib}}) else() set(defs ${MT_PORT_DEFINES_default}) endif() set_property(SOURCE ${file} APPEND PROPERTY COMPILE_DEFINITIONS ${defs}) endfunction() foreach(src IN LISTS MT_PORT_SOURCES) mt_port_apply_defines(${src}) endforeach() # Gate: every header under port/ compiles on its own (and twice, for its include guard), with its # library's definitions. As in 40250, where each library's StdAfx.h is the precompiled header of # every translation unit, the library's StdAfx.h comes first. Built by default, so every platform # build enforces it. set(MT_PORT_GATE_SOURCES) foreach(hdr IN LISTS MT_PORT_HEADERS) file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${hdr}) string(MAKE_C_IDENTIFIER "${rel}" id) set(tu ${CMAKE_CURRENT_BINARY_DIR}/header_gate/${id}.cpp) string(REGEX REPLACE "/.*" "" lib "${rel}") set(pch "") # 40250 spells it StdAfx.h or Stdafx.h; use the on-disk name for case-sensitive hosts. file(GLOB stdafx RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${lib}/[Ss]td[Aa]fx.h) if(NOT lib STREQUAL "common" AND stdafx) set(pch "#include \"${stdafx}\"\n") endif() file(CONFIGURE OUTPUT ${tu} CONTENT "${pch}#include \"${rel}\"\n#include \"${rel}\"\n") set_property(SOURCE ${tu} APPEND PROPERTY OBJECT_DEPENDS ${hdr}) list(APPEND MT_PORT_GATE_SOURCES ${tu}) # Definitions follow the header's library, not the generated file's location. if(DEFINED MT_PORT_DEFINES_${lib}) set_property(SOURCE ${tu} APPEND PROPERTY COMPILE_DEFINITIONS ${MT_PORT_DEFINES_${lib}}) else() set_property(SOURCE ${tu} APPEND PROPERTY COMPILE_DEFINITIONS ${MT_PORT_DEFINES_default}) endif() endforeach() add_library(port_header_gate OBJECT ${MT_PORT_GATE_SOURCES}) target_include_directories(port_header_gate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${MT_PORT_SHIMS}) target_link_libraries(port_header_gate PRIVATE mt3p::minilzo mt3p::cryptopp) if(TARGET mtpython) target_link_libraries(port_header_gate PRIVATE mt3p::python) endif() target_compile_features(port_header_gate PRIVATE cxx_std_20) target_compile_definitions(port_header_gate PRIVATE "NANOBEGIN=" "NANOEND=") if(MINGW) target_compile_options(port_header_gate PRIVATE -include ${CMAKE_CURRENT_SOURCE_DIR}/common/Win32MinMax.h) endif() target_compile_options(port_header_gate PRIVATE ${MT_PORT_WARNING_FLAGS}) add_dependencies(port_logic port_header_gate) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../platform ${CMAKE_CURRENT_BINARY_DIR}/../platform) if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME) add_executable(port_common_test ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_common_test.cpp) target_link_libraries(port_common_test PRIVATE port_logic) add_test(NAME port.common COMMAND $) # Against the real 40250 Client/pack next to the reference source; skipped (77) when it is missing, # failed instead under MT_ASSETS_STRICT=1. set(MT_40250_CLIENT "$ENV{MT_40250_CLIENT}" CACHE PATH "40250 Client directory (pack/, Eternexus/)") if(NOT MT_40250_CLIENT) set(MT_40250_CLIENT "${MT_40250_SOURCE}/../../Client") endif() add_executable(port_eterpack_test ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_eterpack_test.cpp) target_link_libraries(port_eterpack_test PRIVATE port_platform) add_test(NAME port.eterpack COMMAND $ ${MT_40250_CLIENT}) set_tests_properties(port.eterpack PROPERTIES SKIP_RETURN_CODE 77) if(TARGET mtpython) add_executable(port_python_launcher_test ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_python_launcher_test.cpp) target_link_libraries(port_python_launcher_test PRIVATE port_platform) add_dependencies(port_python_launcher_test mtpython_stdlib) add_test(NAME port.python_launcher COMMAND $ ${MT_40250_CLIENT} ${MT_PYTHON_STDLIB_ZIP}) set_tests_properties(port.python_launcher PROPERTIES SKIP_RETURN_CODE 77) endif() endif()