From 2f2a453f88e5150b1ee7cc9bfe466355854b11d7 Mon Sep 17 00:00:00 2001 From: Remy van Elst Date: Thu, 2 May 2024 10:59:50 +0200 Subject: [PATCH] Update Windows github action build to build with npcap so networking should work on the downloadable version. Added a test script to run the emulator on Windows and check if the SRM ROM is downloaded and executed correctly up until the P00>>> prompt (just like the linux versions) --- .github/workflows/build-test-and-artifact.yml | 38 ++++- .gitignore | 2 + CMakeLists.txt | 36 +++-- cmake/FindPCAP.cmake | 143 ++++++++++++++++++ test/rom/test.ps1 | 36 +++++ 5 files changed, 234 insertions(+), 21 deletions(-) create mode 100644 cmake/FindPCAP.cmake create mode 100644 test/rom/test.ps1 diff --git a/.github/workflows/build-test-and-artifact.yml b/.github/workflows/build-test-and-artifact.yml index 9a11da4..d992f02 100644 --- a/.github/workflows/build-test-and-artifact.yml +++ b/.github/workflows/build-test-and-artifact.yml @@ -139,36 +139,60 @@ jobs: steps: - uses: actions/checkout@v2 + + + - name: Create npcap sdk folder + working-directory: ${{runner.workspace}}\ + run: mkdir pcap + + - name: Download npcap sdk + working-directory: ${{runner.workspace}}\pcap + run: curl -o ./npcap-sdk-1.13.zip https://npcap.com/dist/npcap-sdk-1.13.zip + + - name: unzip npcap sdk + working-directory: ${{runner.workspace}}\pcap + run: unzip npcap-sdk-1.13.zip + - name: Get current date id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%dT%H%M')" + run: echo "name=date::$(date +'%Y-%m-%dT%H%M')" >> $GITHUB_OUTPUT - name: Create build environment - run: cmake -E make_directory ${{runner.workspace}}/build + run: cmake -E make_directory ${{runner.workspace}}\build - name: Configure CMake shell: bash working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release - + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release -DPCAP_INCLUDE_DIR="${{runner.workspace}}/pcap/Include/" -DPCAP_LIBRARY="${{runner.workspace}}/pcap/Lib/x64/wpcap.lib" + - name: Build - working-directory: ${{runner.workspace}}/build + working-directory: ${{runner.workspace}}\build shell: bash run: cmake --build . --config Release env: MAKEFLAGS: "-j2" - name: Test run - working-directory: ${{runner.workspace}}/build + working-directory: ${{runner.workspace}}\build run: ${{runner.workspace}}\build\Release\axpbox.exe + - name: install netcat + uses: crazy-max/ghaction-chocolatey@v3 + with: + args: install netcat + + - name: Run rom tests script + working-directory: ${{runner.workspace}}\axpbox\test\rom\ + run: ${{runner.workspace}}\axpbox\test\rom\test.ps1 + + - name: Upload AXPbox Binary uses: actions/upload-artifact@v1 with: name: AXPbox-windows-x86-msvc-${{ env.BUILD_DATE }}.exe path: ${{runner.workspace}}\build\Release\axpbox.exe env: - BUILD_DATE: ${{ steps.date.outputs.date }} + BUILD_DATE: ${{ steps.date.outputs.date }} osx-x86-appleclang: runs-on: "macos-12" diff --git a/.gitignore b/.gitignore index 5e5539c..da6d8ee 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ build**/ .idea/ .vs/ CMakeSettings.json +run/ +img/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f66f1b..f25ed2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) -project(AXPBox VERSION 0.1) +project(AXPBox VERSION 1.1.3) # Source files file(GLOB srcs src/*.cpp src/base/*.cpp src/gui/*.cpp) @@ -10,6 +10,10 @@ list(REMOVE_ITEM srcs ${include_sources}) add_executable(axpbox ${srcs} src/Main.cpp) target_include_directories(axpbox PRIVATE src src/base src/gui ${CMAKE_BINARY_DIR}/src) + +# Path to additional CMake modules +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + if (CMAKE_GENERATOR MATCHES "Visual Studio") add_definitions(-DNOMINMAX -D_WIN32_WINNT=0x0A00 -DLANG_CXX11 -DCOMPILER_MSVC -D__VERSION__=\"MSVC\") add_definitions(-DWIN32 -DOS_WIN -D_MBCS -DWIN64 -DWIN32_LEAN_AND_MEAN -DNOGDI -DPLATFORM_WINDOWS) @@ -24,9 +28,6 @@ endif() find_package(Threads REQUIRED) target_link_libraries(axpbox Threads::Threads) -# Path to additional CMake modules -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) - # Configuration options include(CheckSymbolExists) include(CheckIncludeFile) @@ -115,17 +116,30 @@ check_symbol_exists(_stricasecmp "string.h" HAVE__STRICASECMP) check_symbol_exists(_stricmp "string.h" HAVE__STRICMP) # Features -check_include_file("pcap.h" HAVE_PCAP) check_include_file("SDL/SDL.h" HAVE_SDL) check_include_file("X11/X.h" HAVE_X11) # Large file support (fopen64 / disk files > 2 GB) AXPBOX_TEST_LARGE_FILES(HAVE_LARGE_FILES) - - if (DISABLE_PCAP STREQUAL "yes") - set(HAVE_PCAP 0) + set(WANT_PCAP 0) +else() + set(WANT_PCAP 1) +endif() + +if(WANT_PCAP) + find_package(PCAP) + if(PCAP_FOUND) + message(STATUS "pcap found. Networking support enabled") + include_directories(${PCAP_INCLUDE_DIR}) + target_link_libraries(axpbox ${PCAP_LIBRARY}) + else() + message(STATUS "pcap not found. Networking support disabled") + endif() +else() + message(STATUS "pcap disabled. Networking support disabled") endif() + if (DISABLE_SDL STREQUAL "yes") set(HAVE_SDL 0) endif() @@ -133,12 +147,6 @@ if (DISABLE_X11 STREQUAL "yes") set(HAVE_X11 0) endif() -if(HAVE_PCAP) - target_link_libraries(axpbox pcap) - message(STATUS "pcap found. Networking support enabled") -else() - message(WARNING "pcap not found. Building without network support") -endif() if(HAVE_SDL) target_link_libraries(axpbox SDL) message(STATUS "sdl found. SDL graphics support enabled") diff --git a/cmake/FindPCAP.cmake b/cmake/FindPCAP.cmake new file mode 100644 index 0000000..7ce118b --- /dev/null +++ b/cmake/FindPCAP.cmake @@ -0,0 +1,143 @@ +# ~~~ +# - Try to find libpcap include dirs and libraries +# +# Usage of this module as follows: +# +# find_package(PCAP) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# Imported Targets: +# PCAP::PCAP The libpcap library, if found +# +# Variables defined by this module: +# +# PCAP_FOUND System has libpcap, include and library dirs found +# PCAP_INCLUDE_DIR The libpcap include directories. +# PCAP_LIBRARY The libpcap library (possibly includes a thread +# library e.g. required by pf_ring's libpcap) +# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode +# HAVE_PCAP_DIRECTION If the version of libpcap found support for setting direction +# +# Hints and Backward Compatibility +# ================================ +# +# To tell this module where to look, a user may set the environment variable +# PCAP_ROOT to point cmake to the *root* of a directory with include and lib +# subdirectories for packet.dll (e.g WpdPack or npcap-sdk). Alternatively, +# PCAP_ROOT may also be set from cmake command line or GUI (e.g cmake +# -DPCAP_ROOT=C:\path\to\packet [...]) +# ~~~ + +find_path( + PCAP_INCLUDE_DIR + NAMES pcap/pcap.h pcap.h + PATH_SUFFIXES include Include) + +# The 64-bit Wpcap.lib is located under /x64 +if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + # + # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level directory contains 32-bit libraries. The + # 64-bit libraries are in the Lib/x64 directory. + # + # The only way to *FORCE* CMake to look in the Lib/x64 directory without searching in the Lib directory first appears + # to be to set CMAKE_LIBRARY_ARCHITECTURE to "x64". + # + set(CMAKE_LIBRARY_ARCHITECTURE "x64") +endif() + +find_library(PCAP_LIBRARY NAMES pcap wpcap) + +# If Pcap is not found as this level no need to continue +if(NOT PCAP_LIBRARY OR NOT PCAP_INCLUDE_DIR) + return() +endif() + +include(CheckCXXSourceCompiles) +set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) +check_cxx_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO) +set(CMAKE_REQUIRED_LIBRARIES) + +# check if linking against libpcap also needs to link against a thread library +if(NOT PCAP_LINKS_SOLO) + find_package(Threads) + if(THREADS_FOUND) + set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) + check_cxx_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS) + set(CMAKE_REQUIRED_LIBRARIES) + endif(THREADS_FOUND) + if(THREADS_FOUND AND PCAP_NEEDS_THREADS) + set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) + list(REMOVE_DUPLICATES _tmp) + set(PCAP_LIBRARY + ${_tmp} + CACHE STRING "Libraries needed to link against libpcap" FORCE) + else(THREADS_FOUND AND PCAP_NEEDS_THREADS) + message(FATAL_ERROR "Couldn't determine how to link against libpcap") + endif(THREADS_FOUND AND PCAP_NEEDS_THREADS) +endif(NOT PCAP_LINKS_SOLO) + +include(CheckFunctionExists) +set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) +check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE) +check_function_exists(pcap_setdirection HAVE_PCAP_DIRECTION) +check_function_exists(pcap_lib_version HAVE_PCAP_LIB_VERSION) +set(CMAKE_REQUIRED_LIBRARIES) + +# Check libPCAP version +if(HAVE_PCAP_LIB_VERSION AND NOT CMAKE_CROSSCOMPILING) + # Simple C code to extract the libpcap version + set(PCAP_VERSION_CODE + " + #include + #include + #include + + int main() { + const char* version = pcap_lib_version(); + const char* prefix = \"libpcap version \"; + if (strncmp(version, prefix, strlen(prefix)) == 0) { + version += strlen(prefix); + } + printf(\"%s\", version); + return 0; + } + ") + + # Write the code to a temporary file + set(detect_pcap_version_file "${PROJECT_BINARY_DIR}/detect_pcap_version.c") + file(WRITE "${detect_pcap_version_file}" "${PCAP_VERSION_CODE}") + + # Try to compile and run the program + try_run( + RUN_RESULT_VAR + COMPILE_RESULT_VAR + "${CMAKE_BINARY_DIR}" + "${detect_pcap_version_file}" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PCAP_INCLUDE_DIR}" LINK_LIBRARIES ${PCAP_LIBRARY} + RUN_OUTPUT_VARIABLE PCAP_VERSION_OUTPUT) + + # If successful, parse the output to get the version string + if(COMPILE_RESULT_VAR AND RUN_RESULT_VAR EQUAL 0) + set(PCAP_VERSION ${PCAP_VERSION_OUTPUT}) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PCAP + REQUIRED_VARS PCAP_LIBRARY PCAP_INCLUDE_DIR + VERSION_VAR PCAP_VERSION) + +# create IMPORTED target for libpcap dependency +if(NOT TARGET PCAP::PCAP) + add_library(PCAP::PCAP IMPORTED SHARED) + set_target_properties( + PCAP::PCAP + PROPERTIES IMPORTED_LOCATION ${PCAP_LIBRARY} + IMPORTED_IMPLIB ${PCAP_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${PCAP_INCLUDE_DIR}) +endif() + +mark_as_advanced(PCAP_INCLUDE_DIR PCAP_LIBRARY) \ No newline at end of file diff --git a/test/rom/test.ps1 b/test/rom/test.ps1 new file mode 100644 index 0000000..797f7bf --- /dev/null +++ b/test/rom/test.ps1 @@ -0,0 +1,36 @@ +# Download the firmware +Invoke-WebRequest -Uri 'http://raymii.org/s/inc/downloads/es40-srmon/cl67srmrom.exe' -OutFile 'cl67srmrom.exe' + +# Start AXPbox +Start-Process '..\..\..\build\Release\axpbox' -ArgumentList 'run' -NoNewWindow -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt + +# Wait for AXPbox to start +Start-Sleep -Seconds 5 + +# Connect to terminal +Start-Process -FilePath 'nc' -ArgumentList '-t', '127.0.0.1', '21000' -NoNewWindow -RedirectStandardOutput 'axp.log' + +# Wait for the last line of log to become P00>>> +$timeout = 300 +while ($true) { + if ($timeout -eq 0) { + Write-Host "waiting for SRM prompt timed out" -ForegroundColor Red + exit 1 + } + +# echo "=== start axp.log ===" +# Get-Content -Path 'axp.log' -Raw +# echo "=== end axp.log ===" + + $content = Get-Content -Path 'axp.log' -Raw + $contentWithoutNullBytes = $content -replace '\0', '' + + if ($contentWithoutNullBytes -match "P00>>>") { + exit 0 + } + + Start-Sleep -Seconds 1 + $timeout-- +} + +Stop-Process -Name 'nc'