cmake_minimum_required(VERSION 3.15) project(wowee VERSION 1.0.0 LANGUAGES CXX) include(GNUInstallDirs) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Output directories set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # Options option(BUILD_SHARED_LIBS "Build shared libraries" OFF) option(WOWEE_BUILD_TESTS "Build tests" OFF) # Find required packages find_package(SDL2 REQUIRED) find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) find_package(OpenSSL REQUIRED) find_package(Threads REQUIRED) find_package(ZLIB REQUIRED) if(WIN32) find_package(PkgConfig QUIET) else() find_package(PkgConfig REQUIRED) endif() if(PkgConfig_FOUND) pkg_check_modules(FFMPEG REQUIRED libavformat libavcodec libswscale libavutil) else() # Fallback for MSVC/vcpkg — find FFmpeg libraries manually find_path(FFMPEG_INCLUDE_DIRS libavformat/avformat.h) find_library(AVFORMAT_LIB NAMES avformat) find_library(AVCODEC_LIB NAMES avcodec) find_library(AVUTIL_LIB NAMES avutil) find_library(SWSCALE_LIB NAMES swscale) set(FFMPEG_LIBRARIES ${AVFORMAT_LIB} ${AVCODEC_LIB} ${AVUTIL_LIB} ${SWSCALE_LIB}) if(NOT AVFORMAT_LIB) message(FATAL_ERROR "FFmpeg not found. On Windows install via MSYS2: mingw-w64-x86_64-ffmpeg") endif() endif() # Unicorn Engine (x86 emulator for cross-platform Warden module execution) find_library(UNICORN_LIBRARY NAMES unicorn) find_path(UNICORN_INCLUDE_DIR unicorn/unicorn.h) if(NOT UNICORN_LIBRARY OR NOT UNICORN_INCLUDE_DIR) message(WARNING "Unicorn Engine not found. Install with: sudo apt-get install libunicorn-dev") message(WARNING "Warden emulation will be disabled") set(HAVE_UNICORN FALSE) else() message(STATUS "Found Unicorn Engine: ${UNICORN_LIBRARY}") set(HAVE_UNICORN TRUE) endif() # GLM (header-only math library) find_package(glm QUIET) if(NOT glm_FOUND) message(STATUS "GLM not found, will use system includes or download") endif() # GLM GTX extensions (quaternion, norm, etc.) require this flag on newer GLM versions add_compile_definitions(GLM_ENABLE_EXPERIMENTAL) # StormLib for MPQ extraction tool (not needed for main executable) find_library(STORMLIB_LIBRARY NAMES StormLib stormlib storm) find_path(STORMLIB_INCLUDE_DIR StormLib.h PATH_SUFFIXES StormLib) # Include ImGui as a static library (we'll add the sources) set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/imgui) if(EXISTS ${IMGUI_DIR}) add_library(imgui STATIC ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp ${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp ${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp ) target_include_directories(imgui PUBLIC ${IMGUI_DIR} ${IMGUI_DIR}/backends ) target_link_libraries(imgui PUBLIC SDL2::SDL2 OpenGL::GL ${CMAKE_DL_LIBS}) target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLEW) else() message(WARNING "ImGui not found in extern/imgui. Clone it with:") message(WARNING " git clone https://github.com/ocornut/imgui.git extern/imgui") endif() # Source files set(WOWEE_SOURCES # Core src/core/application.cpp src/core/window.cpp src/core/input.cpp src/core/logger.cpp src/core/memory_monitor.cpp # Network src/network/socket.cpp src/network/packet.cpp src/network/tcp_socket.cpp src/network/world_socket.cpp # Auth src/auth/auth_handler.cpp src/auth/auth_opcodes.cpp src/auth/auth_packets.cpp src/auth/pin_auth.cpp src/auth/integrity.cpp src/auth/srp.cpp src/auth/big_num.cpp src/auth/crypto.cpp src/auth/rc4.cpp src/auth/vanilla_crypt.cpp # Game src/game/expansion_profile.cpp src/game/opcode_table.cpp src/game/update_field_table.cpp src/game/game_handler.cpp src/game/warden_crypto.cpp src/game/warden_module.cpp src/game/warden_emulator.cpp src/game/warden_memory.cpp src/game/transport_manager.cpp src/game/world.cpp src/game/player.cpp src/game/entity.cpp src/game/opcodes.cpp src/game/world_packets.cpp src/game/packet_parsers_tbc.cpp src/game/packet_parsers_classic.cpp src/game/character.cpp src/game/zone_manager.cpp src/game/inventory.cpp # Audio src/audio/audio_engine.cpp src/audio/music_manager.cpp src/audio/footstep_manager.cpp src/audio/activity_sound_manager.cpp src/audio/mount_sound_manager.cpp src/audio/npc_voice_manager.cpp src/audio/ambient_sound_manager.cpp src/audio/ui_sound_manager.cpp src/audio/combat_sound_manager.cpp src/audio/spell_sound_manager.cpp src/audio/movement_sound_manager.cpp # Pipeline (asset loaders) src/pipeline/blp_loader.cpp src/pipeline/dbc_loader.cpp src/pipeline/asset_manager.cpp src/pipeline/asset_manifest.cpp src/pipeline/loose_file_reader.cpp src/pipeline/m2_loader.cpp src/pipeline/wmo_loader.cpp src/pipeline/adt_loader.cpp src/pipeline/dbc_layout.cpp src/pipeline/terrain_mesh.cpp # Rendering src/rendering/renderer.cpp src/rendering/shader.cpp src/rendering/texture.cpp src/rendering/mesh.cpp src/rendering/camera.cpp src/rendering/camera_controller.cpp src/rendering/material.cpp src/rendering/scene.cpp src/rendering/terrain_renderer.cpp src/rendering/terrain_manager.cpp src/rendering/frustum.cpp src/rendering/performance_hud.cpp src/rendering/water_renderer.cpp src/rendering/skybox.cpp src/rendering/celestial.cpp src/rendering/starfield.cpp src/rendering/clouds.cpp src/rendering/lens_flare.cpp src/rendering/weather.cpp src/rendering/lightning.cpp src/rendering/lighting_manager.cpp src/rendering/sky_system.cpp src/rendering/character_renderer.cpp src/rendering/character_preview.cpp src/rendering/wmo_renderer.cpp src/rendering/m2_renderer.cpp src/rendering/quest_marker_renderer.cpp src/rendering/minimap.cpp src/rendering/world_map.cpp src/rendering/swim_effects.cpp src/rendering/mount_dust.cpp src/rendering/loading_screen.cpp src/rendering/video_player.cpp # UI src/ui/ui_manager.cpp src/ui/auth_screen.cpp src/ui/realm_screen.cpp src/ui/character_create_screen.cpp src/ui/character_screen.cpp src/ui/game_screen.cpp src/ui/inventory_screen.cpp src/ui/quest_log_screen.cpp src/ui/spellbook_screen.cpp src/ui/talent_screen.cpp # Main src/main.cpp ) set(WOWEE_HEADERS include/core/application.hpp include/core/window.hpp include/core/input.hpp include/core/logger.hpp include/network/socket.hpp include/network/packet.hpp include/network/tcp_socket.hpp include/network/world_socket.hpp include/network/net_platform.hpp include/platform/process.hpp include/auth/auth_handler.hpp include/auth/auth_opcodes.hpp include/auth/auth_packets.hpp include/auth/srp.hpp include/auth/big_num.hpp include/auth/crypto.hpp include/game/game_handler.hpp include/game/world.hpp include/game/player.hpp include/game/entity.hpp include/game/opcodes.hpp include/game/zone_manager.hpp include/game/inventory.hpp include/game/spell_defines.hpp include/game/group_defines.hpp include/game/world_packets.hpp include/game/character.hpp include/audio/audio_engine.hpp include/audio/music_manager.hpp include/audio/footstep_manager.hpp include/audio/activity_sound_manager.hpp include/audio/mount_sound_manager.hpp include/audio/npc_voice_manager.hpp include/audio/ambient_sound_manager.hpp include/audio/ui_sound_manager.hpp include/audio/combat_sound_manager.hpp include/audio/spell_sound_manager.hpp include/audio/movement_sound_manager.hpp include/pipeline/blp_loader.hpp include/pipeline/asset_manifest.hpp include/pipeline/loose_file_reader.hpp include/pipeline/m2_loader.hpp include/pipeline/wmo_loader.hpp include/pipeline/adt_loader.hpp include/pipeline/dbc_loader.hpp include/pipeline/terrain_mesh.hpp include/rendering/renderer.hpp include/rendering/shader.hpp include/rendering/texture.hpp include/rendering/mesh.hpp include/rendering/camera.hpp include/rendering/camera_controller.hpp include/rendering/material.hpp include/rendering/scene.hpp include/rendering/terrain_renderer.hpp include/rendering/terrain_manager.hpp include/rendering/frustum.hpp include/rendering/performance_hud.hpp include/rendering/water_renderer.hpp include/rendering/skybox.hpp include/rendering/celestial.hpp include/rendering/starfield.hpp include/rendering/clouds.hpp include/rendering/lens_flare.hpp include/rendering/weather.hpp include/rendering/lightning.hpp include/rendering/swim_effects.hpp include/rendering/world_map.hpp include/rendering/character_renderer.hpp include/rendering/character_preview.hpp include/rendering/wmo_renderer.hpp include/rendering/loading_screen.hpp include/rendering/video_player.hpp include/ui/ui_manager.hpp include/ui/auth_screen.hpp include/ui/realm_screen.hpp include/ui/character_create_screen.hpp include/ui/character_screen.hpp include/ui/game_screen.hpp include/ui/inventory_screen.hpp include/ui/spellbook_screen.hpp include/ui/talent_screen.hpp ) set(WOWEE_PLATFORM_SOURCES) if(WIN32) list(APPEND WOWEE_PLATFORM_SOURCES resources/wowee.rc) endif() # Create executable add_executable(wowee ${WOWEE_SOURCES} ${WOWEE_HEADERS} ${WOWEE_PLATFORM_SOURCES}) # Include directories target_include_directories(wowee PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/extern ${FFMPEG_INCLUDE_DIRS} ) # Link libraries target_link_libraries(wowee PRIVATE SDL2::SDL2 OpenGL::GL GLEW::GLEW OpenSSL::SSL OpenSSL::Crypto Threads::Threads ZLIB::ZLIB ${CMAKE_DL_LIBS} ) target_link_libraries(wowee PRIVATE ${FFMPEG_LIBRARIES}) if (FFMPEG_LIBRARY_DIRS) target_link_directories(wowee PRIVATE ${FFMPEG_LIBRARY_DIRS}) endif() # Platform-specific libraries if(UNIX AND NOT APPLE) target_link_libraries(wowee PRIVATE X11) endif() if(WIN32) target_link_libraries(wowee PRIVATE ws2_32) # SDL2main provides WinMain entry point on Windows if(TARGET SDL2::SDL2main) target_link_libraries(wowee PRIVATE SDL2::SDL2main) endif() endif() # Link ImGui if available if(TARGET imgui) target_link_libraries(wowee PRIVATE imgui) endif() # Link Unicorn if available if(HAVE_UNICORN) target_link_libraries(wowee PRIVATE ${UNICORN_LIBRARY}) target_include_directories(wowee PRIVATE ${UNICORN_INCLUDE_DIR}) target_compile_definitions(wowee PRIVATE HAVE_UNICORN) endif() # Link GLM if found if(TARGET glm::glm) target_link_libraries(wowee PRIVATE glm::glm) elseif(glm_FOUND) target_include_directories(wowee PRIVATE ${GLM_INCLUDE_DIRS}) endif() # Compiler warnings if(MSVC) target_compile_options(wowee PRIVATE /W4) else() target_compile_options(wowee PRIVATE -Wall -Wextra -Wpedantic) endif() # Copy assets to build directory file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # Install targets install(TARGETS wowee RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) # Note: tool install rules are placed next to each target definition below. # Install built-in assets (exclude proprietary music) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION bin PATTERN "Original Music" EXCLUDE) # On Windows, install any DLLs that were bundled into the build output dir # (populated by the CI workflow's DLL-bundling step before cpack runs) if(WIN32) install(DIRECTORY "${CMAKE_BINARY_DIR}/bin/" DESTINATION bin FILES_MATCHING PATTERN "*.dll") endif() # Linux desktop integration (launcher + icon) if(UNIX AND NOT APPLE) set(WOWEE_LINUX_ICON_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/256x256/apps/wowee.png") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/resources/wowee.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/wowee.desktop @ONLY ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wowee.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/Wowee.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps RENAME wowee.png) endif() # ---- Tool: asset_extract (MPQ → loose files) ---- if(STORMLIB_LIBRARY AND STORMLIB_INCLUDE_DIR) add_executable(asset_extract tools/asset_extract/main.cpp tools/asset_extract/extractor.cpp tools/asset_extract/path_mapper.cpp tools/asset_extract/manifest_writer.cpp src/pipeline/dbc_loader.cpp src/core/logger.cpp ) target_include_directories(asset_extract PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/tools/asset_extract ${STORMLIB_INCLUDE_DIR} ) target_link_libraries(asset_extract PRIVATE ${STORMLIB_LIBRARY} ZLIB::ZLIB Threads::Threads ) set_target_properties(asset_extract PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) install(TARGETS asset_extract RUNTIME DESTINATION bin) message(STATUS " asset_extract tool: ENABLED") else() message(STATUS " asset_extract tool: DISABLED (requires StormLib)") endif() # ---- Tool: dbc_to_csv (DBC → CSV text) ---- add_executable(dbc_to_csv tools/dbc_to_csv/main.cpp src/pipeline/dbc_loader.cpp src/core/logger.cpp ) target_include_directories(dbc_to_csv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_link_libraries(dbc_to_csv PRIVATE Threads::Threads) set_target_properties(dbc_to_csv PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) install(TARGETS dbc_to_csv RUNTIME DESTINATION bin) # ---- Tool: auth_probe (LOGON_CHALLENGE probe) ---- add_executable(auth_probe tools/auth_probe/main.cpp src/auth/auth_packets.cpp src/auth/auth_opcodes.cpp src/auth/crypto.cpp src/network/packet.cpp src/network/socket.cpp src/network/tcp_socket.cpp src/core/logger.cpp ) target_include_directories(auth_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_link_libraries(auth_probe PRIVATE Threads::Threads OpenSSL::Crypto) set_target_properties(auth_probe PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) install(TARGETS auth_probe RUNTIME DESTINATION bin) # ---- Tool: auth_login_probe (challenge + proof probe) ---- add_executable(auth_login_probe tools/auth_login_probe/main.cpp src/auth/auth_packets.cpp src/auth/auth_opcodes.cpp src/auth/crypto.cpp src/auth/integrity.cpp src/auth/big_num.cpp src/auth/srp.cpp src/network/packet.cpp src/network/socket.cpp src/network/tcp_socket.cpp src/core/logger.cpp ) target_include_directories(auth_login_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_link_libraries(auth_login_probe PRIVATE Threads::Threads OpenSSL::Crypto) set_target_properties(auth_login_probe PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) install(TARGETS auth_login_probe RUNTIME DESTINATION bin) # ---- Tool: blp_convert (BLP ↔ PNG) ---- add_executable(blp_convert tools/blp_convert/main.cpp src/pipeline/blp_loader.cpp src/core/logger.cpp ) target_include_directories(blp_convert PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/extern ) target_link_libraries(blp_convert PRIVATE Threads::Threads) set_target_properties(blp_convert PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) install(TARGETS blp_convert RUNTIME DESTINATION bin) # Print configuration summary message(STATUS "") message(STATUS "Wowee Configuration:") message(STATUS " C++ Standard: ${CMAKE_CXX_STANDARD}") message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}") message(STATUS " SDL2: ${SDL2_VERSION}") message(STATUS " OpenSSL: ${OPENSSL_VERSION}") message(STATUS " ImGui: ${IMGUI_DIR}") message(STATUS "") # ---- CPack packaging ---- set(CPACK_PACKAGE_NAME "wowee") set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "World of Warcraft client emulator") set(CPACK_PACKAGE_VENDOR "Wowee") set(CPACK_PACKAGE_INSTALL_DIRECTORY "Wowee") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") if(WIN32) set(CPACK_GENERATOR "NSIS") set(CPACK_NSIS_DISPLAY_NAME "Wowee") set(CPACK_NSIS_PACKAGE_NAME "Wowee") set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) # Run wowee from bin/ so that ./assets/ resolves correctly. # SetOutPath sets the shortcut's working directory in NSIS. set(CPACK_NSIS_CREATE_ICONS_EXTRA "SetOutPath '$INSTDIR\\bin'\nCreateShortCut '$SMPROGRAMS\\$STARTMENU_FOLDER\\Wowee.lnk' '$INSTDIR\\bin\\wowee.exe'") set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\$STARTMENU_FOLDER\\Wowee.lnk'") elseif(APPLE) set(CPACK_GENERATOR "DragNDrop") else() # Linux — generate postinst/prerm wrapper scripts file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/packaging) # postinst: write a wrapper script at /usr/local/bin/wowee that cd's to # the install dir so ./assets/ resolves correctly. file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst [[#!/bin/sh cat > /usr/local/bin/wowee << 'WOWEE_WRAPPER' #!/bin/sh cd /opt/wowee/bin exec ./wowee "$@" WOWEE_WRAPPER chmod +x /usr/local/bin/wowee ]]) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm "#!/bin/sh\nrm -f /usr/local/bin/wowee\n") file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst ${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) set(CPACK_GENERATOR "DEB") set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/wowee") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Wowee") set(CPACK_DEBIAN_PACKAGE_SECTION "games") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libsdl2-2.0-0, libglew2.2 | libglew2.1, libssl3, zlib1g") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst;${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm") if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64") set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64") endif() endif() include(CPack)